飞道的博客

推荐算法---协同过滤2021-4-13

259人阅读  评论(0)


提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

下面主要以个别例子来探讨一下何为协同过滤以及鄙人一些个性化的理解,希望能帮到你们。


提示:以下是本篇文章正文内容,下面案例可供参考

一、什么是协同过滤?(Collaborative Filtering)

协同过滤(简称CF)是推荐系统最重要的思想之一。协同协同,不明思议,那就是有“共同”部分,过滤是指滤去相关性不强的部分。不管是基于用户的协同过滤还是基于物品的协同过滤,均是由一定的数据计算出得相关性大小来对使用者进行较为合理的推荐而衍生出的一种算法。

二、协同过滤涉及的相关性强弱的计算(相似度)

计算相似度强弱时,用英文单词similarity的简写sim(a,b)表示a与b的相识度,下面主要介绍一种基于用户协同过滤的例子用到的经典算法皮尔逊相关系数(Pearson Correlation Coefficient)的详细用法,当然还有余弦相识度(Cosine-based Similarity),调整后的余弦相识度(Adjusted Cosine Similarity),欧式距离相似度,杰卡德相似系数等(有关公式可上网查询)

1.皮尔逊相关系数

公式:
其中,i 表示项,例如商品;Iu 表示用户 u 评价的项集;Iv 表示用户 v 评价的项 集;ru.i表示用户 u 对项 i 的评分;rv.i 表示用户 v 对项 i 的评分;带上划线的表示用户 的平均评分。

2.余弦相似度

公式:

余弦距离通过向量空间中两个向量夹角的余弦值作为衡量两个个体间差异的大小的度量。

三角形余弦定理公式:
由三角形余弦定理公式可知,角 A 越小,bc 两边越接近。当 A 为 0 度时,bc 两边完全重合。

在向量空间中,对于向量 a 和向量 b 符合公式
当 a 和 b 越接近(越相似),即两个向量越接近时,二者之间的夹角为0,此时余弦值为1,恰恰这个时候,二者的相似度最大。
所以在比对 a 和 b 的相似度时,可以将其向量化后,计算它的余弦值,从而比较其相似度。即:
类似的也可以推广到n个样本的相似性度量公式:
对于用户A和B两者形成的数据集合的相似性度量,为了方便起见,我们常常也用到下面的公式:

3.评分预测公式

不管是由余弦,皮尔逊系数,还是其他的相似度公式求得的关联常数,都可代入以下公式求得预测值。

ru加上划线记做aver(ru)表示用户u的评分的平均值等类似的信息,s(u,u*)表示两者的相似度

三、具体分类

1.基于用户的协同过滤(UserCF)

简介:用户指的是商品的购买者或者说是某件商品的使用者,基于他们涉及购买的物品的交集以及相关性的有关计算(通常为购买后的评价或者有关浏览量)来锁定两个相关性最强的用户,假设为A和B,然后把A方未购买的物品推荐给B方。

1.1实例解说UserCF

为了能更直观的解释基于用户的协同过滤,下面映入的将是实实在在的现实中应用的有关数据以及推荐原理的解说。

1.11 例子

假设你通过网络后台得到了一些用户与商品的一些评分数据,那你是否能用刚才提到的相关知识和理论来探讨以下基于用户的推荐原理吗?

当然实际上的数据是不能拿来讲理论知识的,这里只是极简极简的丁点数据,欢迎大家深探,当然也可发明更为可靠的算法推荐,后生可畏也。

用户 商品1 商品 2 商品 3 商品 4 average
A 4 0 3 5 4
B 0 5 4 0 4.5
C 5 4 2 0 3.667
D 2 4 0 3 3
E 3 4 5 0 4

(1)寻找可利用的“好友”
比如现在我们需要预测用户 C 对商品 4 的评分,我们就要找到已经对商品4进行过评分的用户来“利用”,肉眼可见,为用户A和D。然后根据公共评分来求相关系数。

根据皮尔逊相关系数公式有:
其他的计算类似。

1.12 代码实现

温馨提示:下面两个代码虽然长,除了相似度计算函数不一样外,其他大致相同,不必被纸老虎吓住。

(1)利用皮尔逊系数的代码实现

import numpy as np
from math import  sqrt
def pier(lst_1,lst_2,M,N):#求皮尔逊系数的函数的构建
    aver_1=0
    aver_2=0
    a=0
    b=0
    fenzi=0
    fang_1=0
    fang_2=0
    for i in range(M):#前两个for循环用于求得两个用户的平均值
        if lst_1[i]!=0:
            a+=1
            aver_1+=lst_1[i]
    aver_1=aver_1/a
    for i in range(M):
        if lst_2[i]!=0:
            b+=1
            aver_2+=lst_2[i]
    aver_2=aver_2/b
    for i in range(M):
        fenzi+=(lst_1[i]-aver_1)*(lst_2[i]-aver_2)
        fang_1+=pow((lst_1[i]-aver_1),2)
        fang_2+=pow(lst_2[i]-aver_2,2)
    fenmu=sqrt(fang_1)*sqrt(fang_2)
    return   fenzi/fenmu
def yuping(lst_u,R,u_u,M,N,n):#求预测评分函数   lst_u表示需要预测的用户,R为原始的用户和物品形成的二维数组,N表示用户数组
    fenzi=0
    fenmu=0
    aver_1=0#平均值
    aver_2=0
    a=0#当前用户购买物品数量
    b=0
    for i in range(M):
        if lst_u[i]!=0:
            a+=1
            aver_1 +=lst_u[i]
    aver_1=aver_1/a
    for o in range(N):
        if R[o][m]!=0:
            for i in range(M):
                if R[o][i]!=0:
                    b+=1
                    aver_2 +=R[o][i]
            aver_2=aver_2/b
            fenzi+=u_u[n][o]*(R[o][m]-aver_2)
            fenmu+=abs(pier(lst_u,R[o],M,N))
    return aver_1+fenzi/fenmu
    
R=np.array([[4,0,3,5],#生成原始矩阵R
            [0,5,4,0],
            [5,4,2,0],
            [2,4,0,3],
            [3,4,5,0]])
N=len(R)#列长
M=len(R[0])#行长
u_u=np.zeros((N,N))#建立用户与用户之间相关性矩阵u_u
for n in range(N):#建立一个对R的循环筛选未评分item并进行预测评分
    for m in range(N):
        if n<m:
            u_u[n][m]=pier(R[n],R[m],M,N)
            u_u[m][n]=u_u[n][m]
print("得到的用户-用户相似度矩阵:")        
print(u_u)#打印用户与用户相似度矩阵
user=['A','B','C','D','E']#用户集合
items=['p1','p2','p3','p4']#商品集合

for n in range(N):#建立一个对R循环寻找未评分项并且对未评分项进行预测
    for m in range(M):
        if R[n][m]==0:
            R[n][m]=yuping(R[n],R,u_u,M,N,n)
            if R[n][m]>3:
                print("将商品{:}推荐给用户{:}".format(items[m],user[n]))
print("评分预测矩阵R^:")
print("{:}".format(R))     

(2)余弦相似度的代码实现:


import numpy as np
from math import sqrt
def pex(ls_1,ls_2,M):    #求余弦相似度的函数  ls_1,ls_2表示用户1,2的相关数组,M表示总的物品数
    fenzi=0#余弦相似度分子
    fenmu=0#分母
    abs_1=0#分母左边绝对值里的值
    abs_2=0#分母右边绝对值里的值
    for i in range(M):
        fenzi += ls_1[i] * ls_2[i]
        abs_1 += pow(ls_1[i],2)
        abs_2 += pow(ls_2[i],2)
        fenmu=sqrt(abs_1*abs_2)
    return fenzi/fenmu#ls_1,ls_2用户相关系数

def yuping(lst_u,R,u_u,M,N,n):#求预测评分函数   lst_u表示需要预测的用户,R为原始的用户和物品形成的二维数组,N表示用户数组
    fenzi=0
    fenmu=0
    aver_1=0#平均值
    aver_2=0
    a=0#当前用户购买物品数量
    b=0
    for i in range(M):
        if lst_u[i]!=0:
            a+=1
            aver_1 +=lst_u[i]
    aver_1=aver_1/a
    for o in range(N):
        if R[o][m]!=0:
            for i in range(M):
                if R[o][i]!=0:
                    b+=1
                    aver_2 +=R[o][i]
            aver_2=aver_2/b
            fenzi+=u_u[n][o]*(R[o][m]-aver_2)
            fenmu+=abs(pex(lst_u,R[o],M))
    return aver_1+fenzi/fenmu
    
R=np.array([[4,0,3,5],#生成原始矩阵R
            [0,5,4,0],
            [5,4,2,0],
            [2,4,0,1],
            [3,4,5,0]])
N=len(R)#列长
M=len(R[0])#行长
u_u=np.zeros((N,N))#建立用户与用户之间相关性矩阵u_u
for n in range(N):#建立一个对R的循环筛选未评分item并进行预测评分
    for m in range(N):
        if n<m:
            u_u[n][m]=pex(R[n],R[m],M)
            u_u[m][n]=u_u[n][m]
print("得到的用户-用户相似度矩阵:")        
print(u_u)#打印用户与用户相关系数矩阵
user=['A','B','C','D','E']#用户集合
items=['p1','p2','p3','p4']#商品集合

for n in range(N):#建立一个对R循环寻找未评分项并且对未评分项进行预测
    for m in range(M):
        if R[n][m]==0:
            R[n][m]=yuping(R[n],R,u_u,M,N,n)
            if R[n][m]>3:
                print("将商品{:}推荐给用户{:}".format(items[m],user[n]))
print("评分预测矩阵R^:")
print("{:}".format(R))     

2,基于物品的协同过滤(ItemCF)

基于物品,是指主要以计算物品间的相似度,来对用户推荐另一件物品。假设你购买了手机和笔记本,有相当一部分人在购买了手机,笔记本之后也购买了ipad,那么通过相关计算就会定下ipad与手机和笔记本的相似度较高,而给你推荐ipad。声明的是这里用购买的相关记录的统计来计算物品间的相似度大小。

2.1 相似度计算的套路公式

两物品的相似度的计算与用户的相似度的计算大体相同,公式如下:
上述图片为修改过的计算公式,是为了避开热门商品的巨大影响,有兴趣的可以了解一下。公式中的N(i)^N(j)表示用户N对商品i和j同时喜欢(即购买)的次数,Wij表示i与j的相似度。

2.11 直接上例子

由于某种力量,你又再次得到了好几个用户与商品的历史信息,如下表所示:

A a b d
B a c b
C b e c
D c d e

结果你发现并不能很好的得到物品之间同时被你和他一起喜欢的次数,于是接下来要引入的是共现矩阵
提示:下表纯粹是为了更直观的统计同时购买两件商品的用户数,与代码没有任何联系,不要误以为我会在代码中建立图1的矩阵.

a b c d e
a 2 2 1 0
b 2 2 1 1
c 2 2 2 2
d 1 1 2 1
e 0 1 2 1
                        图1

然后由公式计算a与b的相似度:

得到共现矩阵:(物品相似度矩阵)

a b c d e
a 0 0.8164 0.7071 0.5 0
b 0.8164 0 0.8660 0.4082 0.4082
c 0.7071 0.8660 0 0.7071 0.7071
d 0.5 0.4082 0.7071 0 0.5
e 0 0.4082 0.7071 0.5 0
                         图2

2.2 求用户对某件商品的兴趣

如何让计算机去帮我们求用户u对于物品j的兴趣浓厚呢?
下面给出如下公式:
这里 N(u)是用户喜欢(购买)的物品的集合,S(j,K)是和物品 j 最相似的 K 个物品的集合,Wji 是物品 j 和 i 的相似度,rui 是用户 u 对物品 i 的兴趣。(对于隐反馈数据集, 如果用户 u 对物品 i 有过购买评分的行为,即可令rui=1。为啥令他等于1不是等于其他数值呢?个人认为是因为物品与物品之间的相似度最大值为1的原因,就是绝对关联) 该公式的含义是,和用户历史 上感兴趣的物品越相似的物品,越有可能在用户的推荐列表中获得比较高的排名。

注意:那么这个公式具体要表达什么呢?看不懂怎么办?那就用上面的例子代入使用一下:


转载:https://blog.csdn.net/qq_52134394/article/details/115642256
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场