〇.说明
本文的所有代码均可在 DML 找到,欢迎点星星。
一.引入
推荐系统(主要是CF)是我在参加百度的电影推荐算法比赛的时候才临时学的,虽然没拿什么奖,但是知识却是到手了,一直想写一篇关于推荐系统的文章总结下,这次借着完善DML写一下,权当是总结了。不过真正的推荐系统当然不会这么简单,往往是很多算法交错在一起,本文只是入门水平的总结罢了。 (本文所用测试数据是movielens100k)
本文采用的评测标准是RMSE,数值越小算法越好,在movielens100k 的 u1数据上对每个要求预测的评分输出训练集总的平均分,其RMSE是:
二.Item Based and User Based
1.原理
Item-based和User-Based是CF算法中最基础的两个了,其算法思想很intuitive:
User-based就是把与你有相同爱好的用户所喜欢的物品(并且你还没有评过分)推荐给你
(图自【1】)
Item-based则与之相反,把和你之前喜欢的物品近似的物品推荐给你:
(图自【1】)
更一般的,我们此次使用的数据集是要求你预测某个用户对某个item的评分,以Item-based为例,使用上面提到的算法思想就是检测该用户评过的所有物品和待预测物品的相似度,而两个物品的相似度我们可以找出所有同时对两个物品进行评价的评分,然后计算其皮尔逊相似度,按照相似度计算加权平均值即可,具体过程可以看下面的实现(和《集体智慧编程》中的类似)
2.实现
from __future__ import divisionimport numpy as npimport scipy as spclass Item_based_C: def __init__(self,X): self.X=np.array(X) print "the input data size is ",self.X.shape self.movie_user={} self.user_movie={} self.ave=np.mean(self.X[:,2]) for i in range(self.X.shape[0]): uid=self.X[i][0] mid=self.X[i][1] rat=self.X[i][2] self.movie_user.setdefault(mid,{}) self.user_movie.setdefault(uid,{}) self.movie_user[mid][uid]=rat self.user_movie[uid][mid]=rat self.similarity={} pass def sim_cal(self,m1,m2): self.similarity.setdefault(m1,{}) self.similarity.setdefault(m2,{}) self.movie_user.setdefault(m1,{}) self.movie_user.setdefault(m2,{}) self.similarity[m1].setdefault(m2,-1) self.similarity[m2].setdefault(m1,-1) if self.similarity[m1][m2]!=-1: return self.similarity[m1][m2] si={} for user in self.movie_user[m1]: if user in self.movie_user[m2]: si[user]=1 n=len(si) if (n==0): self.similarity[m1][m2]=1 self.similarity[m2][m1]=1 return 1 s1=np.array([self.movie_user[m1][u] for u in si]) s2=np.array([self.movie_user[m2][u] for u in si]) sum1=np.sum(s1) sum2=np.sum(s2) sum1Sq=np.sum(s1**2) sum2Sq=np.sum(s2**2) pSum=np.sum(s1*s2) num=pSum-(sum1*sum2/n) den=np.sqrt((sum1Sq-sum1**2/n)*(sum2Sq-sum2**2/n)) if den==0: self.similarity[m1][m2]=0 self.similarity[m2][m1]=0 return 0 self.similarity[m1][m2]=num/den self.similarity[m2][m1]=num/den return num/den def pred(self,uid,mid): sim_accumulate=0.0 rat_acc=0.0 for item in self.user_movie[uid]: sim=self.sim_cal(item,mid) if sim<0:continue #print sim,self.user_movie[uid][item],sim*self.user_movie[uid][item] rat_acc+=sim*self.user_movie[uid][item] sim_accumulate+=sim #print rat_acc,sim_accumulate if sim_accumulate==0: #no same user rated,return average rates of the data return self.ave return rat_acc/sim_accumulate def test(self,test_X): test_X=np.array(test_X) output=[] sums=0 print "the test data size is ",test_X.shape for i in range(test_X.shape[0]): pre=self.pred(test_X[i][0],test_X[i][1]) output.append(pre)