Когда дело доходит до систем рекомендаций, особенно основанных на содержании, сходство продуктов, которые следует рекомендовать, становится важной мерой.
Давайте рассмотрим пример, чтобы понять рекомендации, основанные на содержании.
Предположим, к вам приходит друг с предложением фильма. Мы не начинаем снимать названия фильмов случайным образом, вместо этого мы учитываем вкусы нашего друга в жанре кино и, соответственно, предлагаем им фильмы. Системы рекомендаций, основанные на содержании, используют ту же методологию.
Рассмотрим сценарий, в котором пользователь просматривает определенный набор продуктов. На основе атрибутов продукта, который просматривает пользователь, мы можем рекомендовать продукты с аналогичными атрибутами. Некоторые системы рекомендаций, основанные на содержании, используют множественные меры сходства для различных функций, доступных в базовых данных.
В этой статье мы будем использовать две меры сходства:
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.
В заключение, в модели векторного пространства так много методов подобия, и можно поэкспериментировать с ними и выбрать тот, который лучше всего подходит для варианта использования, который вы хотите решить.