协同过滤
User CF 和 Item CF
User CF
1. 计算用户u和v的相似权重
\[ w_{uv} = \frac{|N(u) \cap N(v)|}{|N(u) \cup N(v)|} \]
其中$u$和$v$代表用户,$N(u)$表示用户$u$有过正反馈的物品集合
2. 计算用户u最感兴趣的top k物品
得到用户之间的兴趣相似度后,UserCF算法会给用户推荐和他兴趣最相似的$K$个用户喜欢的物品。如下的公式度量了UserCF算法中用户$u$对物品$i$的感兴趣程度: \[ p(u, i) = \sum_{v \in S(u, K) \cap N(i)} w_{uv} r_{vi} \] 其中,$S(u, K)$包含和用户$u$兴趣最接近的$K$个用户,$N(i)$是对物品$i$有过行为的用户集合,$w_{uv}$是用户$u$和用户$v$的兴趣相似度,$r_{vi}$代表用户$v$对物品$i$的兴趣
Item CF
1. 计算物品$i$和物品$j$的相似分
\[ sim_score_{i,j} = \frac{|N(i) \cap N(j)|}{|N(i) \cup N(j)|} \]
2. 根据相似分,选取和物品$j$最相似的top k个物品
User CF 和 Item CF比较
1. Item CF可以根据用户的实时反馈做出及时响应,根据新的反馈及时更新推荐结果,实时性更好
2. User CF计算的是两个用户的整体相似度,适合用户兴趣变化比较慢的场景
3. Item CF 根据用户的正反馈的每个 Item 推荐相似物品,粒度更细,能捕捉用户的不同兴趣
由于 User CF 和 Item CF 纯靠共现数据统计出来的都不好加入side info信息
一. 基于用户的协同过滤
算法思想:
当给用户A做个性化推荐时,先找到和他兴趣相似的用户,然后把这些用户喜欢的、而用户A没有听说过的物品推荐给A 。
算法步骤:
(1) 找到和目标用户兴趣相似的用户集合。
(2) 找到这个集合中的用户喜欢的,且目标用户没有听说过的物品推荐给目标用户。
用户相似度计算公式
(1)Jaccard公式 :

其中u和v代表用户,N(u)用户u有过正反馈的物品集合。
(2)余弦相似度 :

计算方法一:
直接计算出所用用户间的相似度的话,时间复杂度是O(|U|2),对于用户数目很大的数据集来说时间复杂度非常高。
计算方法二:
如果数据集中的用户数目很大,且大量用户没有相同行为,对于这样的数据集我们可以先建立一个物品到用户的倒排表(即对于每个物品,有哪些用户和他有过交互), 通过这个倒排表我们可以计算出用户有过相同行为的稠密矩阵,避免计算大量没用相同行为用户间的相似度。
python代码
def user_similarity(self): '''计算用户间的相似度矩阵''' #建立用户倒排表 item_users = defaultdict(set) for user, items in self.user_items.items(): for item in items: item_users[item].add(user) #计算用户间的余弦相似度 N = defaultdict(int) C = defaultdict(dict) for item, users in item_users.items(): for u1 in users: N[u1] += 1 for u2 in users: if u1 != u2: C[u1].setdefault(u2, 0) C[u1][u2] += 1 for u, related_users in C.items(): for related_user, _ in related_users.items(): C[u][related_user] = C[u][related_user] / math.sqrt(N[u] * N[related_user]) self.C = C #user间相似度矩阵
(3)改进后的用户相似度计算公式
上面两个公式中计算两个用户间的相似度时,所有的物品是一视同仁的,但是实际上两个用户对冷门物品采取相同的行为更能说明他们兴趣相似。

python代码
def user_similarity(self): '''计算用户间的相似度矩阵''' #建立用户倒排表 item_users = defaultdict(set) for user, items in self.user_items.items(): for item in items: item_users[item].add(user) #计算用户间的改进后相似度 N = defaultdict(int) C = defaultdict(dict) for item, users in item_users.items(): for u1 in users: N[u1] += 1 for u2 in users: if u1 != u2: C[u1].setdefault(u2, 0) C[u1][u2] += 1 / math.log(1 + len(item_users[item])) for u, related_users in C.items(): for related_user, _ in related_users.items(): C[u][related_user] = C[u][related_user] / math.sqrt(N[u] * N[related_user]) self.C = C #user间相似度矩阵
用户对物品的兴趣权重

二. 基于物品的协同过滤
步骤
(1)根据用户行为记录计算物品间的相似度。
(2)当用户对某个物品产生正反馈时,给他推荐与该物品最相似的一些物品。
UserCF和ItemCF对比

参考资料
《推荐系统实践》项亮

浙公网安备 33010602011771号