推荐算法的核心在于对相似用户和相似物品的识别,下面手动重复下这个过程帮助理解。
数据准备:
初始数据:
1 | 101 | 5 |
1 | 102 | 3 |
1 | 103 | 2.5 |
2 | 101 | 2 |
2 | 102 | 2.5 |
2 | 103 | 5 |
2 | 104 | 2 |
3 | 101 | 2.5 |
3 | 104 | 4 |
3 | 105 | 4.5 |
3 | 107 | 5 |
4 | 101 | 5 |
4 | 103 | 3 |
4 | 104 | 4.5 |
4 | 106 | 4 |
5 | 101 | 4 |
5 | 102 | 3 |
5 | 103 | 2 |
5 | 104 | 4 |
5 | 105 | 3.5 |
5 | 106 | 4 |
变成矩阵表示:
用户ID/资源编号 | 101 | 102 | 103 | 104 | 105 | 106 | 107 |
1 | 5 | 3 | 2.5 |
|
|
|
|
2 | 2 | 2.5 | 5 | 2 |
|
|
|
3 | 2.5 |
|
| 4 | 4.5 |
| 5 |
4 | 5 |
| 3 | 4.5 |
| 4 |
|
5 | 4 | 3 | 2 | 4 | 3.5 | 4 |
|
推荐算法步骤:
- 首先计算相似性:
计算方法有:欧几里得距离法,皮尔逊相关系数,cosine相似度,Tanimoto系数。
以欧几里得距离法为例:
1) 基于相似用户
用户相似度矩阵(保留两位小数):
用户/用户 | 1 | 2 | 3 | 4 | 5 |
1 | 0 | 0.2 | 0.29 | 0.67 | 0.47 |
2 | 0.2 | 0 | 0.33 | 0.19 | 0.19 |
3 | 0.29 | 0.33 | 0 | 0.28 | 0.36 |
4 | 0.67 | 0.19 | 0.28 | 0 | 0.4 |
5 | 0.47 | 0..19 | 0.36 | 0.4 | 0 |
计算公式:以用户1和用户2为例:
Distance(U1,U2) =sqrt( sum(pow(5-2, 2), pow(3-2.5, 2), pow(2.5-5, 2))) = ;
Similar(U1,U2) = 1/(1+Distance(U1,U2));
double[][] userMatrix = new double[App.USERNUM][App.USERNUM];
for(int i=0; i<App.USERNUM; i++){
//没有做任何优化
for(int j=0; j<App.USERNUM; j++){
if(i == j)
continue;
double sum = 0;
for(int k=0; k<App.ITEMNUM ;k++){
if(App.matrix[i][k]!=0&& App.matrix[j][k]!=0)
sum += Math.pow(App.matrix[i][k]-App.matrix[j][k], 2);
}
if(sum >0)
userMatrix[i][j] = Double.parseDouble(newDecimalFormat("#.00").format(1.0/(1+Math.sqrt(sum))));
}
}
计算结果如上表,从上表中就可以看出如果取两个最近邻居,推荐结果最多3个的话,则:
用户 | 相似用户 | 推荐物品 |
用户1 | 4,5 | 104,105,106 |
用户2 | 3 | 105,107 |
用户3 | 2,5 | 102,103,106 |
用户4 | 1,5 | 102,105 |
用户5 | 1,4 | 没有推荐 |
Mahout结果如下:
结论:从上面结果可以看出,结果大致差不多,同时mahout会对一些推荐的结果进行了修正,去掉了一些结果。
2) 基于物品相似度:
物品相似度矩阵
物品/物品 | 101 | 102 | 103 | 104 | 105 | 106 | 107 |
101 | 0 | 0.3 | 0.17 | 0.39 | 0.33 | 0.5 | 0.29 |
102 | 0.3 | 0 | 0.27 | 0.47 | 0.67 | 0.5 | 0 |
103 | 0.17 | 0.27 | 0 | 0.2 | 0.4 | 0.31 | 0 |
104 | 0.39 | 0.47 | 0.2 | 0 | 0.59 | 0.67 | 0.5 |
105 | 0.33 | 0.67 | 0.4 | 0.59 | 0 | 0.67 | 0.67 |
106 | 0.5 | 0.5 | 0.31 | 0.67 | 0.67 | 0 | 0 |
107 | 0.29 | 0 | 0 | 0.5 | 0.67 | 0 | 0 |
计算公式:以物品1和物品2为例:
Distance(I1,I2) =sqrt( sum(pow(5-3, 2), pow(2-2.5, 2), pow(4-3, 2)));
Similar(I1,I2) = 1/(1+Distance(I1,I2));
相似性计算公式:
计算物品间的余弦相似度。
Cosine Similarity是相似度的一种常用度量,根据《推荐系统实践》一书第2.4.2节关于Item-CF算法部分的说明,其计算公式如下:
举个例子,若对item1有过行为的用户集合为{u1, u2, u3},对item2有过行为的用户集合为{u1, u3, u4, u5},则根据上面的式子,item1和item2间的相似度为2/(3*4),其中分子的2是因为item1的user_list与item2的 user_list的交集长度为2,即item1和item2的共现(co-occurence)次数是2
在工程实现上,根据论文"Empirical Analysis of Predictive Algorithms for CollaborativeFiltering"的分析,为对活跃用户做惩罚,引入了IUF (Inverse User Frequency)的概念(与TF-IDF算法引入IDF的思路类似:活跃用户对物品相似度的贡献应该小于不活跃的用户),因此,对余弦相似度做改进后相似度计算公式如下:
可以看到,上式分子部分的1/log(1 + N(u))体现了对活跃用户的惩罚。
此外,通常认为用户在相隔很短的时间内喜欢的物品具有更高相似度。因此,工程实现上,还会考虑时间衰减效应。一种典型的时间衰减函数如下所示:
最终,时间上下文相关的Item-CF算法中的相似度计算公式如下:
上式中,分母部分与标准的相似度公式分母保持一致;分子部分参与运算的是item_i和item_j的共现用户集合,其中,f(t)是时间衰减效应的体现,N(u)对活跃用户做了惩罚