Изучите код и математику, лежащие в основе евклидова расстояния, косинусного сходства и корреляции Пирсона для двигателей рекомендаций по мощности

Я запустил в производство несколько рекомендательных систем. Неудивительно, что самое простое оказалось самым эффективным.

В основе большинства рекомендательных систем лежит совместная фильтрация. А в основе совместной фильтрации лежит подобие документов.

Мы рассмотрим 3 алгоритма расчета схожести документов.

1) Евклидово расстояние
2) Косинусное подобие
3) Коэффициент корреляции Пирсона

Даже общее представление о том, как они работают, поможет вам выбрать правильный инструмент для работы и создать более интеллектуальный двигатель.

Что общего у этих алгоритмов

Держите эти предостережения в памяти, пока мы будем обсуждать алгоритмы.

  1. Расчеты производятся по векторным изображениям объектов. Каждый объект сначала необходимо преобразовать в числовой вектор.
  2. Сходство / расстояние вычисляется между одной парой векторов за раз.
  3. Независимо от алгоритма выбор функции будет иметь огромное влияние на ваши результаты.

Евклидово расстояние

В двух словах

Евклидово расстояние - это расстояние между двумя точками в многомерном пространстве.

Более близкие точки больше похожи друг на друга. Дальнейшие пункты более отличаются друг от друга. Итак, выше Марио и Карлос больше похожи, чем Карлос и Дженни.

Я намеренно выбрал два измерения (также известные как особенности: [богатство, друзья]), потому что их легко построить. Мы все еще можем рассчитать расстояние за пределами двух измерений, но требуется формула.

Интуитивно этот метод имеет смысл как мера расстояния. Вы строите свои документы в виде точек и можете буквально измерить расстояние между ними с помощью линейки.

Сравнение городов с евклидовым расстоянием

Сравним 3 города: Нью-Йорк, Торонто и Париж.

Торонто = [3,7]
Нью-Йорк = [7,8]
Париж = [2,10]

Вектор признаков содержит 2 объекта: [population, temperature]. Население исчисляется миллионами. Температура в градусах Цельсия.

Теперь, поскольку мы снова представили задачу как двумерную, мы могли бы измерить расстояние между точками с помощью линейки, но вместо этого мы воспользуемся формулой.

Формула работает независимо от того, есть ли 2 или 1000 измерений.

Реализуйте евклидово расстояние в Python

Никто не ненавидит математические обозначения больше, чем я, но ниже приводится формула евклидова расстояния.

Давайте напишем функцию, которая реализует это и вычисляет расстояние между двумя точками.

from math import sqrt
def euclidean_dist(doc1, doc2):
    '''
    For every (x,y) pair, square the difference
    Then take the square root of the sum
    '''
    pre_square_sum = 0
    for idx,_ in enumerate(doc1):
        pre_square_sum += (doc1[idx] - doc2[idx]) ** 2
    
    return sqrt(pre_square_sum)

toronto = [3,7]
new_york = [7,8]

euclidean_dist(toronto, new_york)
#=> 4.123105625617661

Хорошо. Расстояние между Торонто и Нью-Йорком 4.12.

Евклидово расстояние с помощью Sklearn

Функция, которую мы написали выше, немного неэффективна. Sklearn реализует более быструю версию с использованием Numpy. В производстве мы бы просто использовали это.

toronto = [3,7]
new_york = [7,8]
import numpy as np
from sklearn.metrics.pairwise import euclidean_distances
t = np.array(toronto).reshape(1,-1)
n = np.array(new_york).reshape(1,-1)
euclidean_distances(t, n)[0][0]
#=> 4.123105625617661

Обратите внимание, что для этого требуются массивы вместо списков в качестве входных данных, но мы получаем тот же результат. Буйя!

Косинусное подобие

В двух словах

Косинусное подобие - это косинус угла между двумя точками в многомерном пространстве. Точки с меньшими углами более похожи. Точки с большими углами более разные.

Хотя это сложнее понять, косинусное сходство решает некоторые проблемы с евклидовым расстоянием. А именно величина.

На приведенном выше рисунке мы сравниваем 3 документа на основании того, сколько раз они содержат слова «кулинария» и «ресторан».

Евклидово расстояние говорит нам, что блог и журнал больше похожи, чем блог и газета. Но я думаю, что это заблуждение.

Блог и газета могут иметь похожее содержание, но они далеки в евклидовом смысле, потому что газета длиннее и содержит больше слов.

На самом деле, они оба упоминают «ресторан» больше, чем «кулинарию», и, вероятно, больше похожи друг на друга, чем нет. Косинусное сходство не попадает в эту ловушку.

Сравните книги и статьи с косинусным сходством

Давайте проработаем наш пример выше. Сравним документы по количеству конкретных слов.

magazine_article = [7,1]
blog_post = [2,10]
newspaper_article = [2,20]

Вместо того, чтобы измерять расстояние между ними, мы теперь возьмем косинус угла между ними от начальной точки. Теперь, даже просто взглянув на это, блог и газета выглядят более похожими.

Реализация косинусного подобия в Python

Обратите внимание, что подобие косинуса - это не сам угол, а косинус угла. Таким образом, меньший угол (менее 90 градусов) возвращает большее сходство.

Давайте реализуем функцию, чтобы вычислить это самостоятельно.

import numpy as np
from math import sqrt
def my_cosine_similarity(A, B):
    numerator = np.dot(A,B)
    denominator = sqrt(A.dot(A)) * sqrt(B.dot(B))
    return numerator / denominator
    
    
magazine_article = [7,1]
blog_post = [2,10]
newspaper_article = [2,20]
m = np.array(magazine_article)
b = np.array(blog_post)
n = np.array(newspaper_article)
    
print( my_cosine_similarity(m,b) ) #=> 0.3328201177351375
print( my_cosine_similarity(b,n) ) #=> 0.9952285251199801
print( my_cosine_similarity(n,m) ) #=> 0.2392231652082992

Теперь мы видим, что блог и газета действительно больше похожи друг на друга.

Косинусное сходство со Sklearn

В производстве нам лучше просто импортировать более эффективную реализацию Sklearn.

from sklearn.metrics.pairwise import cosine_similarity
m = np.array(magazine_article).reshape(1,-1)
b = np.array(blog_post).reshape(1,-1)
n = np.array(newspaper_article).reshape(1,-1)
print( cosine_similarity(m,b)[0,0] ) #=> 0.3328201177351375
print( cosine_similarity(b,n)[0,0] ) #=> 0.9952285251199801
print( cosine_similarity(n,m)[0,0] ) #=> 0.2392231652082992

Те же ценности. Большой!

Корреляции Пирсона

Обычно это количественная оценка взаимосвязи между двумя переменными. Например, образование и доход.

Но мы также можем использовать его для измерения сходства между двумя документами, где мы рассматриваем вектор 1-го документа как x, а вектор 2-го документа как y.

Поскольку коэффициент корреляции Пирсона r возвращает значение от 1 до -1, расстояние Пирсона может быть вычислено как 1 — r, чтобы вернуть значение от 0 до 2.

Реализация коэффициента корреляции Пирсона в Python

Давайте сами реализуем эту формулу, чтобы понять, как она работает.

Мы собираемся создать поддельные данные, представляющие нескольких человек. Мы сравним, насколько они похожи, на основе вектора с тремя признаками.

emily = [1,2,5]
kartik = [1,3,5]
todd = [5,3,5]

Наша реализация.

import numpy as np
def pearsons_correlation_coef(x, y):
    x = np.array(x)
    y = np.array(y)
    
    x_mean = x.mean()
    y_mean = y.mean()
    x_less_mean = x - x_mean
    y_less_mean = y - y_mean
    
    numerator = np.sum(xm * ym)
    denominator = np.sqrt(
        np.sum(xm**2) * np.sum(ym**2)
    )
    
    return r_num / r_den
pearsons_correlation_coef(emily,kartik)
#=> 0.9607689228305226

Прохладный. Эмили и Картик выглядят очень похожими. Мы сравним все 3 с Scipy через секунду.

Коэффициент корреляции Пирсона с Scipy

Scipy реализует более эффективные и надежные вычисления.

emily = [1,2,5]
kartik = [1,3,5]
todd = [5,3,5]
pearsonr2(emily,kartik)
print( pearsonr2(emily, kartik) ) 
#=> (0.9607689228305226, 0.1789123750220673)
print( pearsonr2(kartik, todd) ) 
#=> (0.0, 1.0)
print( pearsonr2(todd, emily) ) 
#=> (0.27735009811261446, 0.8210876249779328)

Хотя я выбрал случайные числа в качестве точек данных, мы видим, что Эмили и Картик больше похожи, чем Эмили и Тодд.

Заключение

Хотя мы решили одну часть головоломки, путь к полноценной рекомендации еще не завершен.

В контексте механизма электронной коммерции мы теперь построим матрицу оценок сходства между каждой парой пользователей. Затем мы могли бы использовать это, чтобы рекомендовать продукты, которые купили похожие пользователи.

Тем не менее, хороший рекомендатель может также включать правила для домена и предпочтения пользователей.