IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> 任务3 实现用户和物品的相似性计算 -> 正文阅读

[Python知识库]任务3 实现用户和物品的相似性计算

任务3 实现用户和物品的相似性计算

根据协同过滤基础资料当中的相似度的定义,主要有以下几种。
由于下面三种相似度的计算涉及到大量的矩阵运算,我采用了pytorch来实现。

物品和用户计算相似度其实是一样的,只需要将打分矩阵转置一下即可。下面我就只以用户相似度的计算为例

1. 杰卡德(Jaccard)相似系数

定义

这个是衡量两个集合的相似度一种指标。两个用户 u u u v v v交互商品交集的数量占这两个用户交互商品并集的数量的比例,称为两个集合的杰卡德相似系数,用符号 s i m u v sim_{uv} simuv?表示,其中 N ( u ) , N ( v ) N(u),N(v) N(u),N(v)分别表示用户 u u u和用户 v v v交互商品的集合。
s i m u v = ∣ N ( u ) ∩ N ( v ) ∣ ∣ N ( u ) ∣ ∪ ∣ N ( v ) ∣ sim_{uv}=\frac{|N(u) \cap N(v)|}{\sqrt{|N(u)| \cup|N(v)|}} simuv?=N(u)N(v) ?N(u)N(v)?
由于杰卡德相似系数一般无法反映具体用户的评分喜好信息, 所以常用来评估用户是否会对某商品进行打分, 而不是预估用户会对某商品打多少分。

代码实现

def SimJaccardS(ratings):
    sim1 = (ratings > 0).float()# 把打分矩阵变成0和1的矩阵,1就是有打分行为,0就是没有打分行为

	# 计算分母部分,用矩阵表示来计算算起来快一点,要计算两个0-1向量a,b为并集当中1的个数大概分成3部分来算
	# 先计算a中不为1但b中为1的元素个数,再计算a,b当中都为1的元素个数,再计算a中为1但b中不为1的元素个数,最后求和
    norm1 = torch.mm(1 - sim1, sim1.T) + torch.mm(sim1, sim1.T) + torch.mm(sim1, 1 - sim1.T)
    # print(norm1)
    # 由于是0-1向量,交集中1的个数直接算向量积就行了
    sim1 = torch.mm(sim1, sim1.T)
    # print(sim1)
    
    # 最终结果
    sim1 = sim1 / torch.sqrt(norm1)
	# 由于自己和自己计算相似度没啥意义,所以直接把对角线填成0
    sim1 = sim1.fill_diagonal_(fill_value=0)

    return sim1

测试一下

生成测试数据

test1 = torch.randint(low=0, high=2, size=(5, 6)).float()
test1
tensor([
		[1., 1., 0., 0., 1., 1.],
        [0., 0., 1., 0., 1., 1.],
        [0., 0., 1., 1., 0., 0.],
        [1., 1., 1., 0., 0., 1.],
        [1., 1., 0., 0., 1., 1.]])
SimJaccardS(test1)
tensor([[0.0000, 0.1667, 0.0000, 0.1875, 0.2500],
        [0.1667, 0.0000, 0.1667, 0.1667, 0.1667],
        [0.0000, 0.1667, 0.0000, 0.1250, 0.0000],
        [0.1875, 0.1667, 0.1250, 0.0000, 0.1875],
        [0.2500, 0.1667, 0.0000, 0.1875, 0.0000]])

我们手算第一个行向量与第二个行向量的Jaccard相似度来验证一下
分子部分为:2, 分母部分为 5 \sqrt{5} 5 ?, 最终相似度为 2 5 ≈ 0.8944 \frac{2}{\sqrt{5}} \approx 0.8944 5 ?2?0.8944

tensor([[0.0000, 0.8944, 0.0000, 1.3416, 2.0000],
        [0.8944, 0.0000, 0.5000, 0.8944, 0.8944],
        [0.0000, 0.5000, 0.0000, 0.4472, 0.0000],
        [1.3416, 0.8944, 0.4472, 0.0000, 1.3416],
        [2.0000, 0.8944, 0.0000, 1.3416, 0.0000]])

算法基本正确

2. 余弦相似度

余弦相似度衡量了两个向量的夹角,夹角越小越相似。这个应该不难理解,公式如下

s i m u v = c o s ( u , v ) = u ? v ∣ u ∣ ? ∣ v ∣ sim_{uv} = cos(u,v) =\frac{u\cdot v}{|u|\cdot |v|} simuv?=cos(u,v)=u?vu?v?
代码实现如下

def SimCos(ratings):
    sim1 = ratings.clone()
    norm1 = sim1.norm(p=2, dim=1).reshape(1, -1) #对行向量求范数
    sim1 = torch.mm(sim1, sim1.T) #计算的是分子部分
    norm1 = torch.mm(norm1.T, norm1) # 分母部分

    sim1 = sim1 / norm1 # 最终结果

    sim1 = sim1.fill_diagonal_(fill_value=0) # 对角线填充0,原因同Jaccard

    return sim1

测试例子,这个例子是参考资料里面给出的,省的手算了。

test = torch.tensor(
    [
        [5,3,4,4],
        [3,1,2,3],
        [4,3,4,3],
        [3,3,1,5],
        [1,5,5,2]
    ]
    , dtype=torch.float32
)
SimCos(test)

0.975答案符合手算的结果

tensor([[0.0000, 0.9753, 0.9922, 0.8907, 0.7967],
        [0.9753, 0.0000, 0.9436, 0.9116, 0.6748],
        [0.9922, 0.9436, 0.0000, 0.8528, 0.8581],
        [0.8907, 0.9116, 0.8528, 0.0000, 0.6708],
        [0.7967, 0.6748, 0.8581, 0.6708, 0.0000]])

3. 皮尔逊相关系数

余弦相似度的计算公式为
s i m u v = ∑ i r u i ? r v i ∑ i r u i 2 ∑ i r v i 2 sim_{uv} = \frac{\sum_i r_{ui}*r_{vi}}{\sqrt{\sum_i r_{ui}^2}\sqrt{\sum_i r_{vi}^2}} simuv?=i?rui2? ?i?rvi2? ?i?rui??rvi??
再看看皮尔逊相关系数的计算公式为
s i m ( u , v ) = ∑ i ∈ I ( r u i ? r ˉ u ) ( r v i ? r ˉ v ) ∑ i ∈ I ( r u i ? r ˉ u ) 2 ∑ i ∈ I ( r v i ? r ˉ v ) 2 sim(u,v)=\frac{\sum_{i\in I}(r_{ui}-\bar r_u)(r_{vi}-\bar r_v)}{\sqrt{\sum_{i\in I }(r_{ui}-\bar r_u)^2}\sqrt{\sum_{i\in I }(r_{vi}-\bar r_v)^2}} sim(u,v)=iI?(rui??rˉu?)2 ?iI?(rvi??rˉv?)2 ?iI?(rui??rˉu?)(rvi??rˉv?)?

差别就是把 r u i r_{ui} rui?替换成了 r u i ? r ˉ u r_{ui}-\bar r_u rui??rˉu?,稍微改动一下即可

def SimPearson(ratings):
    sim1 = ratings - ratings.mean(dim=1).view(-1, 1) #对行向量计算均值,然后用行向量减去均值,得到新的矩阵
    return SimCos(sim1) #将新的矩阵传入到计算余弦相似度的函数当中

还是用这个例子测试

test = torch.tensor(
    [
        [5,3,4,4],
        [3,1,2,3],
        [4,3,4,3],
        [3,3,1,5],
        [1,5,5,2]
    ]
    , dtype=torch.float32
)
SimPearson(test)

0.8528和上面手算的结果相符合。

tensor([[ 0.0000,  0.8528,  0.7071,  0.0000, -0.7921],
        [ 0.8528,  0.0000,  0.3015,  0.4264, -0.8866],
        [ 0.7071,  0.3015,  0.0000, -0.7071, -0.1400],
        [ 0.0000,  0.4264, -0.7071,  0.0000, -0.5941],
        [-0.7921, -0.8866, -0.1400, -0.5941,  0.0000]])

结束

三种相似度的计算的实现大致如上,以后有空再利用这些相似度来实现一下userCF和itemCF。

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-04-09 18:19:02  更:2022-04-09 18:19:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 18:36:05-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码