Когда дело доходит до систем рекомендаций, особенно основанных на содержании, сходство продуктов, которые следует рекомендовать, становится важной мерой.

Давайте рассмотрим пример, чтобы понять рекомендации, основанные на содержании.

Предположим, к вам приходит друг с предложением фильма. Мы не начинаем снимать названия фильмов случайным образом, вместо этого мы учитываем вкусы нашего друга в жанре кино и, соответственно, предлагаем им фильмы. Системы рекомендаций, основанные на содержании, используют ту же методологию.

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

В этой статье мы будем использовать две меры сходства:

1 - коэффициент Пирсона и

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

Используемый набор данных будет набором данных Wine, доступным в репозитории машинного обучения UCI. Реализация кода находится в R (R версии 3.5.3 и RStudio 1.1.447). Я предлагаю вам продолжить и реализовать то же самое, чтобы лучше понять процесс.

> library(data.table)
> wine.data <- fread("https://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data")

После загрузки набора данных давайте исследуем данные внутри него.

> head(wine.data)
   V1    V2   V3   V4   V5  V6   V7   V8   V9  V10  V11  V12  V13  V14
1:  1 14.23 1.71 2.43 15.6 127 2.80 3.06 0.28 2.29 5.64 1.04 3.92 1065
2:  1 13.20 1.78 2.14 11.2 100 2.65 2.76 0.26 1.28 4.38 1.05 3.40 1050
3:  1 13.16 2.36 2.67 18.6 101 2.80 3.24 0.30 2.81 5.68 1.03 3.17 1185
4:  1 14.37 1.95 2.50 16.8 113 3.85 3.49 0.24 2.18 7.80 0.86 3.45 1480
5:  1 13.24 2.59 2.87 21.0 118 2.80 2.69 0.39 1.82 4.32 1.04 2.93  735
6:  1 14.20 1.76 2.45 15.2 112 3.27 3.39 0.34 1.97 6.75 1.05 2.85 1450

В метаданных указано, что V1 представляет собой «сорт», который в основном представляет собой классификацию вин, основанную на комбинации химических свойств.

> table(wine.data$V1)
1  2  3 
59 71 48

В наборе данных есть 3 различных типа «сорта». Столбцы от V2 до V14 - это разные химические свойства вина.

Нашим следующим шагом будет разделение типа вина и химических свойств вина на два разных набора данных.

> wine_type <- wine.data[,1]
> wine_features <- wine.data[,-1]

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

> wine_features <- data.frame(scale(wine_features))
> head(wine_features)
         V2          V3         V4         V5         V6        V7        V8         V9        V10
1 1.5143408 -0.56066822  0.2313998 -1.1663032 1.90852151 0.8067217 1.0319081 -0.6577078  1.2214385
2 0.2455968 -0.49800856 -0.8256672 -2.4838405 0.01809398 0.5670481 0.7315653 -0.8184106 -0.5431887
3 0.1963252  0.02117152  1.1062139 -0.2679823 0.08810981 0.8067217 1.2121137 -0.4970050  2.1299594
4 1.6867914 -0.34583508  0.4865539 -0.8069748 0.92829983 2.4844372 1.4623994 -0.9791134  1.0292513
5 0.2948684  0.22705328  1.8352256  0.4506745 1.27837900 0.8067217 0.6614853  0.2261576  0.4002753
6 1.4773871 -0.51591132  0.3043010 -1.2860793 0.85828399 1.5576991 1.3622851 -0.1755994  0.6623487
         V11        V12       V13         V14
1  0.2510088  0.3611585 1.8427215  1.01015939
2 -0.2924962  0.4049085 1.1103172  0.96252635
3  0.2682629  0.3174085 0.7863692  1.39122370
4  1.1827317 -0.4263410 1.1807407  2.32800680
5 -0.3183774  0.3611585 0.4483365 -0.03776747
6  0.7298108  0.4049085 0.3356589  2.23274072

Поскольку для большинства функций подобия в R требуется, чтобы входные данные были в матричном формате, мы можем преобразовать набор данных в матричную форму и присвоить данным имена строк. Каждая строка в наборе данных означает свойства вина в векторном формате.

> wine_mat <- data.matrix(wine_features)
> rownames(wine_mat) <- seq(1:dim(wine_features)[1])
> wine_mat[1:2,]
         V2         V3         V4        V5         V6        V7        V8         V9        V10        V11
1 1.5143408 -0.5606682  0.2313998 -1.166303 1.90852151 0.8067217 1.0319081 -0.6577078  1.2214385  0.2510088
2 0.2455968 -0.4980086 -0.8256672 -2.483841 0.01809398 0.5670481 0.7315653 -0.8184106 -0.5431887 -0.2924962
        V12      V13       V14
1 0.3611585 1.842721 1.0101594
2 0.4049085 1.110317 0.9625263

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

> wine_mat <- t(wine_mat)

У нас есть каждая строка, представляющая каждое из вин. Другими словами, каждая строка имеет несколько свойств вин. Мы будем использовать коэффициент Пирсона, чтобы найти сходство между винами. Коэффициент Пирсона измеряет корреляцию между двумя переменными. В нашем случае каждая строка рассматривается как переменная.

> cor_matrix <- cor(wine_mat, use = "pairwise.complete.obs", method = "pearson")
> dim(cor_matrix)
[1] 178 178
> cor_matrix[1:5,1:5]
          1          2         3             4             5
1 1.0000000  0.7494842 0.5066551  0.7244043066  0.1850897291
2 0.7494842  1.0000000 0.4041662  0.6896539740 -0.1066822182
3 0.5066551  0.4041662 1.0000000  0.5985843958  0.1520360593
4 0.7244043  0.6896540 0.5985844  1.0000000000 -0.0003942683
5 0.1850897 -0.1066822 0.1520361 -0.0003942683  1.0000000000

Как видно из вышеприведенного вывода, итоговая матрица имеет размер 178 x178. Это означает, что каждое вино имеет показатель сходства по сравнению с любым другим вином в наборе данных. Все элементы по диагонали. то есть каждое из вин будет иметь показатель схожести безупречно друг с другом. Положительное число покажет положительную корреляцию, как и отрицательное число в результирующей матрице.

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

> user_view <- wine_features[3,]
> user_view
         V2         V3       V4         V5         V6        V7       V8        V9      V10       V11
3 0.1963252 0.02117152 1.106214 -0.2679823 0.08810981 0.8067217 1.212114 -0.497005 2.129959 0.2682629
        V12       V13      V14
3 0.3174085 0.7863692 1.391224
> sim_items <- cor_matrix[3,]
> sim_items.sorted <- sort(sim_items, decreasing = TRUE)
> sim_items.sorted[1:5]
        3        52        51        85        15 
1.0000000 0.7719273 0.7606256 0.7475886 0.7325499

В итоге мы видим, что вино с номерами 52, 52, 85 и 15 похоже на вино с номером 3, которое пользователь просматривал изначально.

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

Давайте продвинемся вперед с косинусным подобием и реализуем его в R:

> library("lsa")
> cor_matrix = cosine(wine_mat)
> dim(cor_matrix)
[1] 178 178
> cor_matrix[1:5,1:5]
          1          2         3         4          5
1 1.0000000  0.5622599 0.6726599 0.8107890  0.4871602
2 0.5622599  1.0000000 0.2368420 0.4871792 -0.1573216
3 0.6726599  0.2368420 1.0000000 0.7461053  0.5227389
4 0.8107890  0.4871792 0.7461053 1.0000000  0.4043439
5 0.4871602 -0.1573216 0.5227389 0.4043439  1.0000000

Мы использовали библиотеку «lsa», чтобы использовать из нее функцию косинуса. На выходе получается та же матрица, которая дает косинусное сходство между каждым вином и любым другим вином в наборе данных.

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

> user_view <- wine_features[3,]
> user_view
         V2         V3       V4         V5         V6        V7       V8        V9      V10       V11
3 0.1963252 0.02117152 1.106214 -0.2679823 0.08810981 0.8067217 1.212114 -0.497005 2.129959 0.2682629
        V12       V13      V14
3 0.3174085 0.7863692 1.391224
> sim_items <- cor_matrix[3,]
> sim_items.sorted <- sort(sim_items, decreasing = TRUE)
> sim_items.sorted[1:5]
        3        31        52        49        56 
1.0000000 0.8271992 0.8192096 0.8137115 0.8057562

Как видим, по косинусному сходству вина, похожие на вино номер 3, - это вина с номерами 31, 52, 49 и 56.

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