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

该博客介绍了协同过滤算法中用于计算用户和物品相似度的三种方法:杰卡德相似系数、余弦相似度和皮尔逊相关系数。通过PyTorch实现了这些相似度的计算,并提供了测试案例验证算法的正确性。杰卡德系数适用于判断用户是否会为商品打分,而余弦相似度和皮尔逊相关系数则可用于预测评分。
摘要由CSDN通过智能技术生成

任务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 20.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)=uvuv
代码实现如下

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=irui2 irvi2 iruirvi
再看看皮尔逊相关系数的计算公式为
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(ruirˉu)2 iI(rvirˉv)2 iI(ruirˉu)(rvirˉv)

差别就是把 r u i r_{ui} rui替换成了 r u i − r ˉ u r_{ui}-\bar r_u ruirˉ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。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值