Использование матричного факторизации для рекомендательной системы
Я работаю над рекомендательной системой для ресторанов, используя элементарный совместный фильтр в C# 6.0. Я хочу, чтобы мой алгоритм работал как можно лучше, поэтому я провел некоторые исследования по различным способам прогнозирования рейтингов для ресторанов, которые пользователь еще не рассмотрел.
Я начну с исследования, которое я сделал
сначала я хотел настроить пользовательский совместный фильтр, используя корреляцию Пирсона между пользователями, чтобы иметь возможность видеть какие пользователи хорошо сочетаются.
Основная проблема заключалась в количестве данных, необходимых для расчета этой корреляции. Сначала вам нужно было 4 отзывы на 2 пользователей в одном ресторане. Но мои данные будут очень скудными. Маловероятно, что 2 пользователя рассмотрели бы те же самые 4 ресторана. Я хотел исправить это, расширив условия матча (т. е. не соответствующие пользователям в тех же ресторанах, но в том же типе ресторана), но это дало мне проблему, где это было трудно определить, какие отзывы я бы использовал в корреляции, так как пользователь мог оставить 3 отзыва о ресторане с типом "фаст-фуд". Какой из них лучше всего подходит для обзора другого пользователя в ресторане быстрого питания?
после дополнительных исследований я пришел к выводу, что элемент на основе совместного фильтра превосходит пользовательский совместный фильтр. Но опять же, я столкнулся с проблемой разреженности данных. В моих тестах я успешно смог рассчитать прогноз для рейтинга на a ресторан пользователь еще не рассмотрел, но когда я использовал алгоритм на разреженном наборе данных, результаты были недостаточно хорошими. (Большую часть времени сходство не было возможным между двумя ресторанами, так как пользователи 2 не оценили один и тот же ресторан).
После еще большего исследования я обнаружил, что использование метода факторизации матрицы хорошо работает на разреженных данных.
теперь моя проблема
Я искал по всему интернету учебники по использованию этого способ, но у меня нет никакого опыта в рекомендательных системах, и мои знания по алгебре, также ограничено. Я понимаю справедливость метода. У вас есть Матрица, где у вас есть 1 сторона пользователей и другая сторона ресторанов. Каждая ячейка-это рейтинг, который пользователь дал в ресторане.
Метод матричного факторизации создает две матрицы этого, одну с весом между пользователями и типом ресторана, а другую между ресторанами и этими типами.
Я просто не могу понять, как рассчитать вес между типом ресторана и ресторанами/пользователями (если я правильно понимаю матричную факторизацию). Я нашел десятки формул, которые вычисляют эти числа, но я не могу понять, как их разбить и применить в своем приложении.
Я приведу вам пример того, как данные выглядят в моем приложении:
В этой таблице U1 означает пользователя, а R1 - ресторан.
Каждый ресторан имеет свои теги (тип ресторана). Т. е. R1 имеет тег "итальянский", R2 имеет "фаст-фуд"и т. д.
| R1 | R2 | R3 | R4 |
U1 | 3 | 1 | 2 | - |
U2 | - | 3 | 2 | 2 |
U3 | 5 | 4 | - | 4 |
U4 | - | - | 5 | - |
кто-нибудь может мне точку в правильном направлении или объяснить, как я должен использовать этот метод на моих данных? Любая помощь будет очень признательна!
1 ответов
матричная факторизация предполагает, что" латентные факторы", такие как предпочтение итальянской кухни пользователем и итальянность продукта питания, связаны с рейтингами в матрице.
таким образом, вся проблема преобразуется в проблему реконструкции матрицы, для которой существует множество различных решений. Простое, возможно, медленное решение (помимо ALS и некоторых других возможностей реконструкции матрицы) аппроксимирует матрицу с помощью алгоритма градиентного спуска. Я рекомендую эту короткую статью статья ieee о рекомендательных системах.
извлечение скрытых факторов-это другая проблема.
таким образом, реализация GDM может выглядеть так:
public void learnGDM(){
//traverse learnSet
for(int repeat = 0; repeat < this.steps; repeat++){
for (int i = 0; i < this.learnSet.length; i++){
for (int j = 0; j < this.learnSet[0].length; j++){
if(this.learnSet[i][j] > 0.0d){
double Rij = this.learnSet[i][j];
for(int f = 0 ; f <= latentFactors; f++){
double error = Rij - dotProduct(Q.getRow(i), P.getRow(j));/*estimated_Rij;*/
//ieee computer 1.pdf
double qif = Q.get(i, f);
double pif = P.get(j, f);
double Qvalue = qif + gradientGamma * (error * pif - gradientLambda * qif);
double Pvalue = pif + gradientGamma * (error * qif - gradientLambda * pif);
Q.set(i,f, Qvalue);
P.set(j, f, Pvalue);
}
}
}
}
//check global error
if(checkGlobalError() < 0.001d){
System.out.println("took" + repeat + "steps");
break;
}
}
где learnset представляет собой двумерный массив, содержащий Ratingmatrix, как в статье ieee. Алгоритм GDM изменяет векторы рейтинга P и Q бит на каждой итерации, чтобы они приближались к рейтингам в ratingmatrix. Тогда "не дано" рейтинги могут быть рассчитаны по точечному произведению P и Q. самыми высокими оценками для не заданных рейтингов будут рекомендации.
Так что это для начала. Существует множество оптимизаций и других алгоритмов или модифицированных версий GDM, которые также можно запускать параллельно.
некоторые хорошие гласит:
рекомендательные системы в Энциклопедии машинного обучения