2017-01-10 4 views
7

Я предсказываю рейтинги между процессами, которые участвуют в подготовке модели. Я использую подход, изложенный здесь: ALS model - how to generate full_u * v^t * v?Модель ALS - предсказано full_u * v^t * v оценки очень высокие

! rm -rf ml-1m.zip ml-1m 
! wget --quiet http://files.grouplens.org/datasets/movielens/ml-1m.zip 
! unzip ml-1m.zip 
! mv ml-1m/ratings.dat . 

from pyspark.mllib.recommendation import Rating 

ratingsRDD = sc.textFile('ratings.dat') \ 
       .map(lambda l: l.split("::")) \ 
       .map(lambda p: Rating(
            user = int(p[0]), 
            product = int(p[1]), 
            rating = float(p[2]), 
           )).cache() 

from pyspark.mllib.recommendation import ALS 

rank = 50 
numIterations = 20 
lambdaParam = 0.1 
model = ALS.train(ratingsRDD, rank, numIterations, lambdaParam) 

Затем извлечь особенности продукта ...

import json 
import numpy as np 

pf = model.productFeatures() 

pf_vals = pf.sortByKey().values().collect() 
pf_keys = pf.sortByKey().keys().collect() 

Vt = np.matrix(np.asarray(pf_vals)) 

full_u = np.zeros(len(pf_keys)) 

def set_rating(pf_keys, full_u, key, val): 
    try: 
     idx = pf_keys.index(key) 
     full_u.itemset(idx, val) 
    except: 
     pass 

set_rating(pf_keys, full_u, 260, 9), # Star Wars (1977) 
set_rating(pf_keys, full_u, 1, 8), # Toy Story (1995) 
set_rating(pf_keys, full_u, 16, 7), # Casino (1995) 
set_rating(pf_keys, full_u, 25, 8), # Leaving Las Vegas (1995) 
set_rating(pf_keys, full_u, 32, 9), # Twelve Monkeys (a.k.a. 12 Monkeys) (1995) 
set_rating(pf_keys, full_u, 335, 4), # Flintstones, The (1994) 
set_rating(pf_keys, full_u, 379, 3), # Timecop (1994) 
set_rating(pf_keys, full_u, 296, 7), # Pulp Fiction (1994) 
set_rating(pf_keys, full_u, 858, 10), # Godfather, The (1972) 
set_rating(pf_keys, full_u, 50, 8) # Usual Suspects, The (1995) 

recommendations = full_u*Vt*Vt.T 

top_ten_ratings = list(np.sort(recommendations)[:,-10:].flat) 

print("predicted rating value", top_ten_ratings) 

top_ten_recommended_product_ids = np.where(recommendations >= np.sort(recommendations)[:,-10:].min())[1] 
top_ten_recommended_product_ids = list(np.array(top_ten_recommended_product_ids)) 

print("predict rating prod_id", top_ten_recommended_product_ids) 

Однако предсказанные рейтинги кажутся слишком высокими:

('predicted rating value', [313.67320347694897, 315.30874327316576, 317.1563289268388, 317.45475214423948, 318.19788673744563, 319.93044594688428, 323.92448427140653, 324.12553531632761, 325.41052886977582, 327.12199687047649]) 
('predict rating prod_id', [49, 287, 309, 558, 744, 802, 1839, 2117, 2698, 3111]) 

Это кажется быть неверным. Любые советы оценены.

+1

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

+0

Ах, интересно. Я пока не смотрю на неявные отзывы. Если вы разместите свой комментарий в качестве ответа, вы получите награду по умолчанию, если никто другой не ответит;) –

+0

@ yoh.lej А это объясняет, почему я получал такие завышенные рейтинги, как Крис! Таким образом, предположение заключается в том, что рейтинги являются двоичными. Йохан, не могли бы вы вкратце объяснить, на чем основана эта формула? Я пробовал искать способы подобия и не видел этого. С чем мы рассчитываем сходство? Заинтригован, потому что я сейчас беру класс линейной алгебры. Просто логично, похоже, мы хотели бы определить, какой существующий пользователь этот новый пользователь больше всего похож, и использовать свои факторы для прогнозирования рейтингов - этот подход более изощрен? Благодаря! (Крис - проверьте ALS.trainImplicit) – ScottEdwards2000

ответ

5

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

Идея здесь - угадать скрытое представление вашего нового пользователя. Как правило, для пользователя, уже находящегося в факторизации, пользователь i, у вас есть его скрытое представление u_i (i-я строка в model.userFeatures()), и вы получаете его оценку для данного фильма (фильм j), используя model.predict, которые в основном умножают u_i на скрытое представление продукт v_j. вы можете получить все прогнозируемые рейтинги сразу, если умножить на весь v: u_i*v.

Для нового пользователя вы должны угадать, что его скрытое представление u_new от full_u_new. В принципе, вы хотите, чтобы 50 коэффициентов отображали ваше новое отношение к каждому из скрытых факторов продукта. Для простоты, и так как этого было достаточно для использования в неявной обратной связи, я просто использовал точечный продукт, в основном проецируя нового пользователя на скрытый фактор продукта: full_u_new*V^t дает вам коэффициент 50, коэффициент, который зависит от вашего нового пользователя латентный фактор продукта i. и он работает особенно хорошо с неявной обратной связью. Итак, использование точечного продукта даст вам это, но оно не будет масштабироваться, и это объясняет высокие оценки, которые вы видите. Чтобы получить годные к употреблению баллов, нужно более точно масштабируется u_new, я думаю, вы могли бы получить, что с помощью косинуса сходства, как они делали [здесь] https://github.com/apache/incubator-predictionio/blob/release/0.10.0/examples/scala-parallel-recommendation/custom-query/src/main/scala/ALSAlgorithm.scala

подход упоминается @ ScottEdwards2000 в комментарии интересно тоже, но скорее другой. Вы действительно можете искать наиболее похожих пользователей (пользователей) в своем учебном наборе. Если есть более одного, вы можете получить среднее значение. Я не думаю, что это будет слишком плохо, но это совсем другой подход, и вам нужна полная рейтинговая матрица (чтобы найти наиболее похожих пользователей). Получение одного закрытого пользователя обязательно решит проблему масштабирования. Если вам удастся выполнить оба подхода, вы можете сравнить результаты!

Смежные вопросы