ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

【推荐系统】{1} —— 基于用户的协同过滤算法

2020-05-06 20:37:42  阅读:344  来源: 互联网

标签:协同 users items 用户 sqrt 算法 过滤 相似 物品


协同过滤(英语:Collaborative Filtering,简称CF),简单来说是利用某兴趣相投、拥有共同经验之群体的喜好来推荐用户感兴趣的信息,个人透过合作的机制给予信息相当程度的回应(如评分)并记录下来以达到过滤的目的进而帮助别人筛选信息,回应不一定局限于特别感兴趣的,特别不感兴趣信息的纪录也相当重要。——维基百科


基于用户的协同过滤算法(简称UserCF)

在一个在线个性化推荐系统中,当一个用户A需要个性化推荐时,可以先找到和他有相似兴趣的其他用户,然后把那些用户喜欢的、而用户A没有听说过的物品推荐给A。这种方法称为基于用户的协同过滤算法。

举个例子:

用户/物品 物品A 物品B 物品C 物品D
用户A 推荐给用户A
用户B
用户C

要实现基于用户的协同过滤,需要的步骤:

  1. 收集用户偏好
  2. 通过计算相似度找到与目标用户相似的用户
  3. 将相似用户喜欢的、且目标用户没有听说过的物品推荐给目标用户

一、计算两个用户的兴趣相似度

其中关键的一步就是计算两个用户的兴趣相似度。

协同过滤算法主要利用行为的相似度计算兴趣的相似度。给定用户 uuu 和用户 vvv ,令 N(u)N(u)N(u) 表示用户 uuu 曾经有过正反馈的物品集合,令 N(v)N(v)N(v) 为用户 vvv 曾经有过正反馈的物品集合。则可以通过计算余弦相似度简单地计算 uuu 和 vvv 的兴趣相似度:wuv=N(u)N(v)N(u)N(v)w_{uv} = \frac{|N(u)\cap{N(v)|}}{\sqrt{|N(u)\cup{N(v)|}}}wuv​=∣N(u)∪N(v)∣​∣N(u)∩N(v)∣​


例子:

图片来源

如图,AAA、BBB、CCC、DDD 为用户,aaa、bbb、ccc、ddd、eee 为物品。

利用余弦相似度公式计算他们之间的兴趣相似度分别为:wAB={a,b,d}{a,c}{a,b,d}  {a,c}=16w_{AB} = \frac{|{\{ a,b,d\}}\cap\{{a,c}\}|}{\sqrt{|\{a,b,d\}|\,\,|\{a,c\}}|}=\frac{1}{\sqrt{6}}wAB​=∣{a,b,d}∣∣{a,c}​∣∣{a,b,d}∩{a,c}∣​=6​1​

wAC={a,b,d}{b,e}{a,b,d}  {b,e}=16w_{AC} = \frac{|{\{ a,b,d\}}\cap\{{b,e}\}|}{\sqrt{|\{a,b,d\}|\,\,|\{b,e\}}|}=\frac{1}{\sqrt{6}}wAC​=∣{a,b,d}∣∣{b,e}​∣∣{a,b,d}∩{b,e}∣​=6​1​

wAC={a,b,d}{c,d,e}{a,b,d}  {c,d,e}=13w_{AC} = \frac{|{\{ a,b,d\}}\cap\{{c,d,e}\}|}{\sqrt{|\{a,b,d\}|\,\,|\{c,d,e\}}|}=\frac{1}{3}wAC​=∣{a,b,d}∣∣{c,d,e}​∣∣{a,b,d}∩{c,d,e}∣​=31​
但事实上,很多用户相互之间并没有对同样的物品产生过行为,即 N(u)N(v)=0|N(u)\cap{N(v)}|=0∣N(u)∩N(v)∣=0 。


因此换一种思路,我们可以首先计算出 N(u)N(v)0|N(u)\cap{N(v)}|≠0∣N(u)∩N(v)∣​=0 的用户对 (u,v)(u,v)(u,v) ,然后再对这种情况除以分母 N(u)N(v)\sqrt{{|N(u)\cup{N(v)|}}}∣N(u)∪N(v)∣​ 。

为此,可以首先建立 >物品->用户物品−>用户 的倒排表。令稀疏矩阵 C[u][v]=N(u)N(v)C[u][v]=|N(u)\cap{N(v)}|C[u][v]=∣N(u)∩N(v)∣ 。因此,可以遍历倒排表中每个物品对应的用户列表,将用户列表中的两两用户对应的 C[u][v]C[u][v]C[u][v] 同时加 111,最终就可以得到所有用户之间不为 000 的 C[u][v]C[u][v]C[u][v]。

代码实现如下:

def UserSimilarity(train):
	# 建立倒排表
	item_users = dict()
	for u, items in train.items():
		for i in items.keys():
			if i not in item_users:
				item_users[i] = set()
			item_users[i].add(u)
	
	# 修改相似度矩阵
	C = dict()
	N = dict()
		for i, users in item_users.items():
			for u in users:
				N[u] += 1
				for V in users:
					if u == v:
						continue
					C[u][v] += 1
	
	# 计算相似度矩阵
	W = dict()
	for u, related_users in C.items():
		for V, cuv in related_users.items():
			W[u][v] = cuv / math.sqrt(N[u] * N[v])
	return W

以上图的用户行为解释上述算法。首先,需要建立 >物品->用户物品−>用户 的倒排表(如图1)。然后建立一个 4×44×44×4 的用户相似度矩阵 WWW,对于物品 aaa,将 W[A][B]W[A][B]W[A][B] 和 W[B][A]W[B][A]W[B][A] 加 111,对于物品 bbb,将 W[A][C]W[A][C]W[A][C] 和 W[C][A]W[C][A]W[C][A] 加 111,以此类推(如图2)。扫描完所有物品后,我们可以得到最终的 WWW 矩阵。 此处 WWW 是余弦相似度中的分子部分,将 WWW 除以分母即可得到最终的用户兴趣相似度(如图3)。

图片来源


二、进行推荐

得到用户之间的兴趣相似度后,UserCFUserCFUserCF 算法会给用户推荐和他兴趣最相似的 KKK 个用户喜欢的物品。以下公式度量了 UserCFUserCFUserCF 算法中用户 uuu 对物品 iii 的感兴趣程度: p(u,i)=vS(u,K)N(i)wuvrvip(u,i)=\displaystyle \sum_{v\in{S(u,K)\cap{N(i)}}}w_{uv}r_{vi}p(u,i)=v∈S(u,K)∩N(i)∑​wuv​rvi​

K是 UserCFUserCFUserCF 算法的一个重要参数

其中,S(u,K)S(u,K)S(u,K) 包含和用户 uuu 兴趣最接近的 KKK 个用户,N(i)N(i)N(i) 是对物品 iii 有过行为的用户集合,wurw_{ur}wur​
是用户 uuu 和用户 vvv 的兴趣相似度,rvir_{vi}rvi​ 代表用户 vvv 对物品 iii 的兴趣,因为使用的是单一行为的隐反馈数据(否则使用评分等指标),所以所有的 rvi=1r_{vi}=1rvi​=1。

评分可以经过归一化处理

代码如下:

def Recommend(user, train, W):
	rank = dict()
	interacted_items = train[user]
	for v, wuv in sorted (W[u].items, key=itemgetter(1), reverse=True)[0:K]:
		for i, rvi in train[v].items:
			if i in interacted_items:
				# 过滤互动过的项目
				continue
			rank[i] += wuv * rvi
	return rank

利用上述 UserCFUserCFUserCF 算法,可以给上述图1、2、3的用户 AAA 进行推荐。选取 K=3K=3K=3,用户 AAA 对物品 ccc、eee 没有过行为,因此可以把这两个物品推荐给用户 AAA。相似用户则是 BBB、CCC、DDD,他们喜欢过并且 AAA 没有喜欢过的物品有 ccc、eee。根据 UserCFUserCFUserCF 算法,用户 AAA 对物品 ccc、eee 的兴趣是:p(A,c)=wAB×1+wAD×1=16+19=0.7416p(A,c)=w_{AB} ×1+ w_{AD} ×1= \frac{1}{\sqrt{6}}+\frac{1}{\sqrt{9}}=0.7416p(A,c)=wAB​×1+wAD​×1=6​1​+9​1​=0.7416p(A,e)=wAC×1+wAD×1=16+19=0.7416p(A,e)=w_{AC}×1+ w_{AD} ×1= \frac{1}{\sqrt{6}}+\frac{1}{\sqrt{9}}=0.7416p(A,e)=wAC​×1+wAD​×1=6​1​+9​1​=0.7416


用户相似度计算的改进:

两个用户对冷门物品采取过同样的行为比热门物品更能说明他们兴趣的相似度。因此,为了防止热门物品的影响,提出如下公式计算用户的兴趣相似度:wuv=iN(u)N(v)1log1+N(i)N(u)N(v)w_{uv}=\frac{\displaystyle \sum_{i\in{N(u)\cap{N(v)}}}\frac{1}{log1+|N(i)|}}{\sqrt{|N(u)||N(v)|}}wuv​=∣N(u)∣∣N(v)∣​i∈N(u)∩N(v)∑​log1+∣N(i)∣1​​

上述公式通过 1log1+N(i)\frac{1}{log1+|N(i)|}log1+∣N(i)∣1​ 惩罚了用户 uuu 和用户 vvv 共同兴趣列表中热门物品对他们相似度的影响。

基于上述用户相似度公式的算法记为 UserIIFUser-IIFUser−IIF 算法。

代码如下:

def UserSimilarity(train):
	# 建立倒排表
	item_users = dict()
	for u, items in train.items():
		for i in items.keys():
			if i not in item_users:
				item_users[i] = set()
			item_users[i].add(u)
	# 统计相似度矩阵
	C = dict()
	N = dict()
	for i, users in item_users.items():
		for u in users:
			N[u] += 1
			for v in users: 
				if u == v:
					continue
				C[u][v] += 1 / math.1og(1 + len(users))
	# 计算相似度矩阵
	W = dict()
	for u, related_users in C.items():
		for v, cuv in related.users.items():
			W[u][v] = cuv / math.sqrt(N[u] * N[v])
	return W

UserCFUserCFUserCF 算法存在的问题:

  • 对于一个新用户,很难找到相似用户。
  • 对于一个物品,所有相似用户都在其上没有多少行为。
  • 矩阵稀疏。
  • 用户量越来越大
  • 人类善变

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

标签:协同,users,items,用户,sqrt,算法,过滤,相似,物品
来源: https://blog.csdn.net/weixin_45961774/article/details/105915805

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有