电影推荐中的预测值
Predicting Values in Movie Recommendations
我一直在尝试使用 python 中的 movielens 数据集创建推荐系统。我的目标是确定用户之间的相似度,然后以这种格式为每个用户输出前五名推荐的电影:
User-id1 movie-id1 movie-id2 movie-id3 movie-id4 movie-id5
User-id2 movie-id1 movie-id2 movie-id3 movie-id4 movie-id5
我现在使用的数据是这个ratings数据集。
目前的代码如下:
import pandas as pd
import numpy as np
from sklearn import cross_validation as cv
from sklearn.metrics.pairwise import pairwise_distances
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.metrics import mean_squared_error
from math import sqrt
import scipy.sparse as sp
from scipy.sparse.linalg import svds
import matplotlib.pyplot as plt
import seaborn as sns
df = pd.read_csv('ratings.csv')
df.drop('timestamp', axis=1, inplace=True)
n_users = df.userId.unique().shape[0]
n_items = df.movieId.unique().shape[0]
#Pivot table so users are rows and movies are columns, ratings are then values
df = df.pivot(index='userId', columns='movieId', values='rating')
#subtract row mean from each rating to center data
df = df.sub(df.mean(axis=1), axis=0)
#copy to fill in predictions
c1 = df.copy()
c1 = c1.fillna('a')
#second copy to find which values were filled in and return the highest rated values
c2 = c1.copy()
#fill NAN with 0
df = df.fillna(0)
#Get cosine similarity between rows
similarity = pd.DataFrame(cosine_similarity(df))
#get top 5 similar profiles
tmp = similarity.apply(lambda row: sorted(zip(similarity.columns, row), key=lambda c: -c[1]), axis=1)
tmp = tmp.ix[:,1:6]
l = np.array(tmp)
##Prediction function - does not work needs improvement
def predict(df, c1, l):
for i in range(c1.shape[0]):
for j in range(i+1, c1.shape[1]):
try:
if c1.iloc[i][j] == 'a':
num = df[l[i][0][0]]*l[i][0][1] + df[l[i][1][0]]*l[i][1][1] + df[l[i][2][0]]*l[i][2][1] + df[l[i][3][0]]*l[i][3][1] + df[l[i][4][0]]*l[i][4][1]
den = l[i][0][1] + l[i][1][0] + l[i][2][0] + l[i][3][0] + l[i][4][0]
c1[i][j] = num/den
except:
pass
return c1
res = predict(df, c1, l)
print(res)
res = predict(df, c1, l)
print(res)
我正在尝试实现预测功能。我想预测缺失值并将它们添加到 c1。我正在尝试实施 this。公式以及如何使用它的示例在图片中。如您所见,它使用了最相似用户的相似度得分。
相似度的输出如下所示:例如这里是用户 1 的相似度:
[(34, 0.19269904365720053) (196, 0.19187531680008307)
(538, 0.14932027335788825) (67, 0.14093020024386654)
(419, 0.11034407313683092) (319, 0.10055810007385564)]
我需要帮助使用预测函数中的这些相似性来预测缺失的电影评级。如果这个问题解决了,我将不得不为每个用户找到前 5 名推荐的电影,并以上面的格式输出它们。
我目前需要有关预测功能的帮助。任何建议都有帮助。如果您需要更多信息或说明,请告诉我。
感谢阅读
首先,矢量化使复杂的问题变得容易得多。这里有一些改进您已有的建议
- 将 userID 用作数据透视表中的列 table,这使得预测示例更易于查看
- NaN 代表缺失值,在概念上与 0 不同,在这种特殊情况下,一个高负数就可以了,并且只有在使用余弦相似度函数时才需要
- 利用 pandas 高级功能,例如要保留原始值但添加预测值,可以使用 fillna
- 在构造
similarity
数据框时一定要跟踪 useIds,您可以通过将索引和列设置为 df.columns
来实现
这是我编辑的代码版本,包括预测实现:
```
import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.preprocessing import scale
def predict(l):
# finds the userIds corresponding to the top 5 similarities
# calculate the prediction according to the formula
return (df[l.index] * l).sum(axis=1) / l.sum()
# use userID as columns for convinience when interpretering the forumla
df = pd.read_csv('ratings.csv').pivot(columns='userId',
index='movieId',
values='rating')
similarity = pd.DataFrame(cosine_similarity(
scale(df.T.fillna(-1000))),
index=df.columns,
columns=df.columns)
# iterate each column (userID),
# for each userID find the highest five similarities
# and use to calculate the prediction for that user,
# use fillna so that original ratings dont change
res = df.apply(lambda col: ' '.join('{}'.format(mid) for mid in col.fillna(
predict(similarity[col.name].nlargest(6).iloc[1:])).nlargest(5).index))
print(res)
```
这里是一个输出样本
userId
1 1172 1953 2105 1339 1029
2 17 39 150 222 265
3 318 356 1197 2959 3949
4 34 112 141 260 296
5 597 1035 1380 2081 33166
dtype: object
编辑
上面的代码将推荐前 5 个,无论用户是否已经 watched/rated 他们。要解决此问题,我们可以在选择推荐时将原始评分的值重置为 0,如下所示\
res = df.apply(lambda col: ' '.join('{}'.format(mid) for mid in (0 * col).fillna(
predict(similarity[col.name].nlargest(6).iloc[1:])).nlargest(5).index))
输出
userId
1 2278 4085 3072 585 256
2 595 597 32 344 316
3 590 457 150 380 253
4 1375 2571 2011 1287 2455
5 480 590 457 296 165
6 1196 7064 26151 260 480
....
我一直在尝试使用 python 中的 movielens 数据集创建推荐系统。我的目标是确定用户之间的相似度,然后以这种格式为每个用户输出前五名推荐的电影:
User-id1 movie-id1 movie-id2 movie-id3 movie-id4 movie-id5
User-id2 movie-id1 movie-id2 movie-id3 movie-id4 movie-id5
我现在使用的数据是这个ratings数据集。
目前的代码如下:
import pandas as pd
import numpy as np
from sklearn import cross_validation as cv
from sklearn.metrics.pairwise import pairwise_distances
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.metrics import mean_squared_error
from math import sqrt
import scipy.sparse as sp
from scipy.sparse.linalg import svds
import matplotlib.pyplot as plt
import seaborn as sns
df = pd.read_csv('ratings.csv')
df.drop('timestamp', axis=1, inplace=True)
n_users = df.userId.unique().shape[0]
n_items = df.movieId.unique().shape[0]
#Pivot table so users are rows and movies are columns, ratings are then values
df = df.pivot(index='userId', columns='movieId', values='rating')
#subtract row mean from each rating to center data
df = df.sub(df.mean(axis=1), axis=0)
#copy to fill in predictions
c1 = df.copy()
c1 = c1.fillna('a')
#second copy to find which values were filled in and return the highest rated values
c2 = c1.copy()
#fill NAN with 0
df = df.fillna(0)
#Get cosine similarity between rows
similarity = pd.DataFrame(cosine_similarity(df))
#get top 5 similar profiles
tmp = similarity.apply(lambda row: sorted(zip(similarity.columns, row), key=lambda c: -c[1]), axis=1)
tmp = tmp.ix[:,1:6]
l = np.array(tmp)
##Prediction function - does not work needs improvement
def predict(df, c1, l):
for i in range(c1.shape[0]):
for j in range(i+1, c1.shape[1]):
try:
if c1.iloc[i][j] == 'a':
num = df[l[i][0][0]]*l[i][0][1] + df[l[i][1][0]]*l[i][1][1] + df[l[i][2][0]]*l[i][2][1] + df[l[i][3][0]]*l[i][3][1] + df[l[i][4][0]]*l[i][4][1]
den = l[i][0][1] + l[i][1][0] + l[i][2][0] + l[i][3][0] + l[i][4][0]
c1[i][j] = num/den
except:
pass
return c1
res = predict(df, c1, l)
print(res)
res = predict(df, c1, l)
print(res)
我正在尝试实现预测功能。我想预测缺失值并将它们添加到 c1。我正在尝试实施 this。公式以及如何使用它的示例在图片中。如您所见,它使用了最相似用户的相似度得分。
相似度的输出如下所示:例如这里是用户 1 的相似度:
[(34, 0.19269904365720053) (196, 0.19187531680008307)
(538, 0.14932027335788825) (67, 0.14093020024386654)
(419, 0.11034407313683092) (319, 0.10055810007385564)]
我需要帮助使用预测函数中的这些相似性来预测缺失的电影评级。如果这个问题解决了,我将不得不为每个用户找到前 5 名推荐的电影,并以上面的格式输出它们。
我目前需要有关预测功能的帮助。任何建议都有帮助。如果您需要更多信息或说明,请告诉我。
感谢阅读
首先,矢量化使复杂的问题变得容易得多。这里有一些改进您已有的建议
- 将 userID 用作数据透视表中的列 table,这使得预测示例更易于查看
- NaN 代表缺失值,在概念上与 0 不同,在这种特殊情况下,一个高负数就可以了,并且只有在使用余弦相似度函数时才需要
- 利用 pandas 高级功能,例如要保留原始值但添加预测值,可以使用 fillna
- 在构造
similarity
数据框时一定要跟踪 useIds,您可以通过将索引和列设置为df.columns
来实现
这是我编辑的代码版本,包括预测实现:
```
import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.preprocessing import scale
def predict(l):
# finds the userIds corresponding to the top 5 similarities
# calculate the prediction according to the formula
return (df[l.index] * l).sum(axis=1) / l.sum()
# use userID as columns for convinience when interpretering the forumla
df = pd.read_csv('ratings.csv').pivot(columns='userId',
index='movieId',
values='rating')
similarity = pd.DataFrame(cosine_similarity(
scale(df.T.fillna(-1000))),
index=df.columns,
columns=df.columns)
# iterate each column (userID),
# for each userID find the highest five similarities
# and use to calculate the prediction for that user,
# use fillna so that original ratings dont change
res = df.apply(lambda col: ' '.join('{}'.format(mid) for mid in col.fillna(
predict(similarity[col.name].nlargest(6).iloc[1:])).nlargest(5).index))
print(res)
```
这里是一个输出样本
userId
1 1172 1953 2105 1339 1029
2 17 39 150 222 265
3 318 356 1197 2959 3949
4 34 112 141 260 296
5 597 1035 1380 2081 33166
dtype: object
编辑
上面的代码将推荐前 5 个,无论用户是否已经 watched/rated 他们。要解决此问题,我们可以在选择推荐时将原始评分的值重置为 0,如下所示\
res = df.apply(lambda col: ' '.join('{}'.format(mid) for mid in (0 * col).fillna(
predict(similarity[col.name].nlargest(6).iloc[1:])).nlargest(5).index))
输出
userId
1 2278 4085 3072 585 256
2 595 597 32 344 316
3 590 457 150 380 253
4 1375 2571 2011 1287 2455
5 480 590 457 296 165
6 1196 7064 26151 260 480
....