Collaborative Filtering Recommendation
向量之间的相似度
度量向量之间的相似度方法很多了,你可以用距离(各种距离)的倒数,向量夹角,Pearson相关系数等。
皮尔森相关系数计算公式如下:
分子是协方差,分子是两个变量标准差的乘积。显然要求X和Y的标准差都不能为0。
因为,所以皮尔森相关系数计算公式还可以写成:
当两个变量的线性关系增强时,相关系数趋于1或-1。
用户评分预测
用户评分预测的基本原理是:
step1.如果用户i对项目j没有评过分,就找到与用户i最相似的K个邻居(使用向量相似度度量方法)
step2.然后用这K个邻居对项目j的评分的加权平均来预测用户i对项目j的评分。
iterm1 | ………… | itemn | |
user1 | R11 | R1n | |
…… | Rij | ||
userm | Rm1 | Rmn |
用户评分数据矩阵
step1.
用户评分矩阵是个高度稀疏的矩阵,即用户对很多项目都没有评分。在高度稀疏的情况下用传统的向量相似度度量方法来度量两个用户的相似度就会很不准确。一种简单的处理办法是对未评分的项都令其等于该用户的平均评分值。
度量用户i和用户j相似度更好的方法是:
1.用户i参与评分的项目集合为Ii,用户i参与评分的项目集合为Ij,找到它们的并集
2.在集合中用户i未评分的项目是,重新估计用户i对中每个项目的评分。
2.1.取出评分矩阵的两列,计算这两列的相似度就是这两个项目的相似度。。找到与最相似的V个项目构成集合。
2.2.
3.这样用户i和j对的评分就都是非0值了,在此情况下计算他们的相似度。
step2.
表示用户u对所有评分过的项目的评分平均值。
完了,可以看到算法非常的简单,核心就是计算向量的相似度。代码量也很少。
#include#include #include #include #include #include #include #include #include using namespace std;const int ITERM_SIZE=1682;const int USER_SIZE=943;const int V=15; //ITERM的最近邻居数const int S=10; //USER的最近邻居数struct MyPair{ int id; double value; MyPair(int i=0,double v=0):id(i),value(v){}};struct cmp{ bool operator() (const MyPair & obj1,const MyPair & obj2)const{ return obj1.value < obj2.value; }};double rate[USER_SIZE][ITERM_SIZE]; //评分矩阵MyPair nbi[ITERM_SIZE][V]; //存放每个ITERM的最近邻居MyPair nbu[USER_SIZE][S]; //存放每个USER的最近邻居double rate_avg[USER_SIZE]; //每个用户的平均评分//从文件中读入评分矩阵int readRate(string filename){ ifstream ifs; ifs.open(filename.c_str()); if(!ifs){ cerr<<"error:unable to open input file "< < >str1>>str2>>str3; int userid=atoi(str1.c_str()); int itermid=atoi(str2.c_str()); double rating=atof(str3.c_str()); rate[userid-1][itermid-1]=rating; line.clear(); } ifs.close(); return 0;}//计算每个用户的平均评分void getAvgRate(){ for(int i=0;i &vec1,const vector &vec2){ int len=vec1.size(); assert(len==vec2.size()); double sum1=0; double sum2=0; double sum1_1=0; double sum2_2=0; double sum=0; for(int i=0;i vec1; priority_queue ,cmp> neighbour; for(int k=0;k vec2; for(int k=0;k &user,int index){ double sum1=0; double sum2=0; for(int i=0;i &user1,const vector &user2){ vector vec1; vector vec2; int len=user1.size(); assert(len==user2.size()); for(int i=0;i user1; priority_queue ,cmp> neighbour; for(int k=0;k user2; for(int k=0;k >user>>iterm; cout< <