协同过滤算法

协同过滤算法




协同过滤算法

​ 搭建智能推荐系统的算法有很多,其中商业实战中用的较多的为协同过滤(collaborative filtering)。

协同过滤算法的原理

​ 根据用户群体对产品偏好的数据,发现用户之间的相似性或者物品之间的相似性,并基于这些相似性为用户作推荐。

  • 基于用户的协同过滤算法(User-based Collaborative Filtering)

​ 其本质是:寻找相似的用户,进而对用户推荐相似用户关注的产品。

​ 如下表所示,用户1和用户2都给商品A,B,C打了高分,那么可以将用户1和用户2划分在同一个用户群体,此时若用户2还给商品D打了高分,那么就可以将商品D推荐给用户1。

  • 基于物品的协同过滤算法(Item-based Collaborative Filtering)

​ 其本质是:根据用户的历史偏好信息,将类似的物品推荐给用户

​ 如下表所示,图书A和图书B都被用户1,2,3购买过(1表示购买,0表示未购买),那么可以认为图书A和图书B具有较强的相似度,即可判断喜欢图书A的用户同样也会喜欢图书B。当用户4购买图书B时,根据图书A和图书B的相似性,可将图书A推荐给用户4。

​ 在商业实战中,大多应用场景偏向于使用基于物品的协同过滤算法。主要有如下两个原因:

​ 原因一:通常用户的数量是非常庞大的(如淘宝数亿的用户群体),而物品的数量相对有限,因此计算不同物品之间的相似度往往比计算不同用户的相似度容易很多。

​ 原因二:用户的喜好较为多变,而物品属性较明确不随时间变化,过去用户对物品的评分长期有效,所以物品间的相似度比较固定,因此可以预先离线计算好物品间的相似度,把结果存在表中,向客户进行推荐时再使用。

实时效果反馈

1. 关于基于用户的协同过滤算法,下列说法正确的是:

A 对用户推荐不相关用户关注的产品

B 寻找相似的用户,进而对用户推荐相似用户关注的产品

C 根据用户的历史偏好信息,将类似的物品推荐给用户

D 以上说法均不正确

2. 关于基于物品的协同过滤算法,下列说法正确的是:

A 根据用户的历史偏好信息,将类似的物品推荐给用户

B 在商业实战中,很少使用基于物品的协同过滤算法

C 无需考虑物品之间的相似性

D 以上说法均不正确

答案

1=>B 2=>A

相似度计算的常用方法

​ 无论是基于用户还是基于物品的协同过滤算法,其本质都是寻找数据之间的相似度。本节介绍计算相似度的三种常见方法:

  • 欧式距离

∑ i = 1 n ( X i ( a ) − X i ( b ) ) 2 \Large \sqrt{\sum_{i=1}^n{(X_i^{(a)}-X_i^{(b)})}^2} i=1n(Xi(a)Xi(b))2

  • 余弦相似度

​ 使用两向量夹角θ的余弦值cosθ来表示两个向量的相似度,称为余弦相似度。余弦相似度的范围是:[-1,1],夹角越小,余弦值越接近于1,两个向量越靠近,两者越相似。两个向量有相同的指向时,余弦相似度的值为1;两个向量夹角为90°时,余弦相似度的值为0;两个向量指向完全相反的方向时,余弦相似度的值为-1。

余弦相似度公式为:
c o s θ = < a , b > ∣ ∣ a ∣ ∣ ∣ ∣ b ∣ ∣ \Large cos\theta = \frac{<a,b>}{|| a|||| b||} cosθ=∣∣a∣∣∣∣b∣∣<a,b>
​ 其中,<a,b>表示的是向量a和向量b的内积,||a||和||b||分别表示向量a和向量b的模(长度)。

例如,向量a=(X1,Y1),向量b=(X2,Y2),代入余弦相似度公式可以得到:
c o s θ = X 1 ∗ X 2 + Y 1 ∗ Y 2 X 1 2 + Y 1 2 ∗ X 2 2 + Y 2 2 cos\theta = \frac{X_1*X_2+Y_1*Y_2}{\sqrt{X_1^2+Y_1^2}*\sqrt{X_2^2+Y_2^2}} cosθ=X12+Y12 X22+Y22 X1X2+Y1Y2
​ 可以将其推广至n维向量空间:

​ 若向量a=(X1,X2,X3,…,Xn),向量b=(Y1,Y2,Y3,…,Yn),其夹角的余弦值(余弦相似度)可以表示为:

c o s θ = x 1 ∗ y 1 + x 2 ∗ y 2 + x 3 ∗ y 3 + . . . + x n ∗ y n x 1 2 + x 2 2 + x 3 2 + . . . + x n 2 ∗ y 1 2 + y 2 2 + y 3 2 + . . . + y n 2 cos\theta = \frac{x_1*y_1+x_2*y_2+x_3*y_3+...+x_n*y_n}{\sqrt{x_1^2+x_2^2+x_3^2+...+x_n^2}*\sqrt{y_1^2+y_2^2+y_3^2+...+y_n^2}} cosθ=x12+x22+x32+...+xn2 y12+y22+y32+...+yn2 x1y1+x2y2+x3y3+...+xnyn

  • 皮尔逊相关系数

​ 皮尔逊相关系数r是用来描述两个数值型变量间线性相关强弱程度的统计量,r的绝对值越大表明相关性越强。r取值范围为[-1,1],为正代表两个变量存在正相关,为负代表两个变量存在负相关,r=0,说明两个变量之间无线性相关关系。要计算变量X与Y的皮尔逊相关系数,其计算公式如下:

r = C o v ( X , Y ) S X S Y \Large r=\frac{Cov(X,Y)}{S_XS_Y} r=SXSYCov(X,Y)
其中SX和SY分别为变量X和变量Y的标准差,COV(X,Y)为变量X和变量Y的协方差。

实时效果反馈

1. 关于余弦相似度,下列说法正确的是:

A 余弦相似度的范围是:[0,1]

B 夹角越小两个向量越不同

C 两向量的夹角θ称为余弦相似度

D 两个向量指向完全相反的方向时,余弦相似度的值为-1

2. 关于皮尔逊相关系数,下列说法正确的是:

A 取值范围为[-1,1]

B r=0,说明两个变量之间无任何相关关系

C r的绝对值越大表明相关性越弱

D 以上说法均不正确

答案

1=>D 2=>A

相似度计算的Python实现

  • 欧式距离的Python实现

利用numpy库的norm可以间接地计算两个向量的欧氏距离

import pandas as pd
df = pd.DataFrame([[5, 1, 5], [4, 2, 2], [4, 2, 1]], columns=['用户1', '用户2', '用户3'], index=['物品A', '物品B', '物品C'])
import numpy as np
dist = np.linalg.norm(df.iloc[0] - df.iloc[1])
  • 余弦相似度的Python实现

通过sklearn的cosine_similarity函数实现余弦相似度的计算

import pandas as pd
df = pd.DataFrame([[5, 1, 5], [4, 2, 2], [4, 2, 1]], columns=['用户1', '用户2', '用户3'], index=['物品A', '物品B', '物品C'])
from sklearn.metrics.pairwise import cosine_similarity
# 对两两样本之间(此处是物品之间)做余弦相似度矩阵
item_similarity = cosine_similarity(df)
pd.DataFrame(item_similarity, columns=['物品A', '物品B', '物品C'], index=['物品A', '物品B', '物品C'])
  • 皮尔逊相关系数的Python实现

通过scipy库中的pearsonr函数实现皮尔逊相关系数的计算

只需给它两个数组或列表(X,Y),它就能返回两个数值(r,P):

相关系数r值在[-1,1]之间,为正数则表示正相关,负数则表示负相关,绝对值越大相关性越高;

P值是显著性,与皮尔逊相关显著性检验有关,P<0.05时表示相关显著,即指变量X和Y之间真的存在相关性,而不是因为偶然因素引起的。

from scipy.stats import pearsonr
X = [1, 3, 5, 7, 9]
Y = [9, 8, 6, 4, 2]
corr = pearsonr(X, Y)
print("皮尔逊相关系数r的值为:",corr[0],"显著性水平P值为:",corr[1])

实时效果反馈

1. 通过_____________________函数实现余弦相似度的计算。

A norm

B pearsonr

C cosine_similarity

D score

2. 通过_____________________函数实现皮尔逊相关系数的计算。

A norm

B pearsonr

C cosine_similarity

D score

答案

1=>C 2=>B

相关系数在DataFrame中的应用

在项目中计算相关系数的场景里,DataFrame的corrwith()和corr()方法经常被使用

  • corrwith()

dataframe.corrwith()用于计算行或列之间的成对相关关系

  • corr()

dataframe.corr()用于计算DataFrame中所有列的成对相关性

代码演示

import pandas as pd
df = pd.DataFrame([[5, 4, 4], [1, 2, 2], [5, 2, 1]], columns=['物品A', '物品B', '物品C'], index=['用户1', '用户2', '用户3'])  
# 物品A与其他物品的皮尔逊相关系数
A = df['物品A']
corr_A = df.corrwith(A) # 等同于corr_A = df.corrwith(A,axis=0)

# 皮尔逊系数表,获取各物品(列)的皮尔逊相关系数
df.corr()

实时效果反馈

1. 通过DataFrame的_____________________方法计算行或列之间的成对相关关系。

A corrwith

B pearsonr

C corr

D score

2. 通过DataFrame的_____________________方法计算DataFrame中所有列的成对相关性。

A corrwith

B pearsonr

C corr

D score

答案

1=>A 2=>C

电影智能推荐系统

背景介绍

​ 人们经常会在视频平台上观看影片,有时目标明确,想要观看某部电影,但有时仅仅是随机搜寻。

​ 如果视频平台可以利用基于物品的智能推荐系统,有效地从用户对其观看过的电影的评分中挖掘数据,便可以根据用户偏好的电影个性化地推荐更多类似的电影,优化用户体验,提高用户粘性,创造额外收入。

分析步骤

  1. 读取数据
  2. 数据分析
    • 合并电影数据和评分数据
    • 计算每部电影的评分均值
    • 计算每部电影的“评分次数”
    • 创建数据透视表,以’'用户编号“为行索引,”名称“为列名称,”评分“为数据值
  3. 智能推荐

​ 以电影"阿甘正传(2031)"为例,计算各个电影与"阿甘正传(2031)"的相关系数,并删除相关系数是NaN的数据,最后筛选出评分次数超过20次的电影数据,并按照相关系数降序排序。

代码实现

# 读取数据
import pandas as pd 
movies = pd.read_excel('电影.xlsx')
movies = movies.loc[:, ~movies.columns.str.contains('Unnamed')]
movies.head()
score = pd.read_excel('评分.xlsx')
score.head()

# 合并电影数据和评分数据
df = pd.merge(movies, score, on='电影编号')
df.head()

# 计算每部电影的评分均值,并组装成DataFrame
ratings = pd.DataFrame(df.groupby('名称')['评分'].mean())
# 添加评分次数列
ratings['评分次数'] = df.groupby('名称')['评分'].count()
# 根据评分次数降序排序
ratings.sort_values('评分次数', ascending=False).head()

# 创建透视表
user_movie = df.pivot_table(index='用户编号', columns='名称', values='评分')
user_movie.tail()
user_movie.shape

# 智能推荐
FG = user_movie['阿甘正传(2031)']  # FG阿甘英文名称的缩写
pd.DataFrame(FG).head()

# axis默认为0,计算user_movie各列与FG的相关系数
corr_FG = user_movie.corrwith(FG)
similarity = pd.DataFrame(corr_FG, columns=['相关系数'])
similarity.head()

# 删除相关系数是NaN的数据
similarity.dropna(inplace=True)  
similarity.head()

# 合并DataFrame
similarity_new = pd.merge(similarity, pd.DataFrame(ratings['评分次数']), left_index=True, right_index=True)
similarity_new.head()

# 筛选出评分次数超过20次的电影数据,并按照相关系数降序排序
similarity_new[similarity_new['评分次数'] > 20].sort_values(by='相关系数', ascending=False).head(10)  

实时效果反馈

1. 合并DataFrame的方法是___________________

A corrwith()

B merge()

C groupby()

D mean()

2. 创建DataFrame透视表的方法是_______________

A crosstab()

B pivot_table()

C sort_values()

D merge()

答案

1=>B 2=>B

实战补充——groupby()分组妙用

​ 在日常的数据分析中,经常需要将数据根据某个(多个)字段划分为不同的群体进行分

析,而DataFrame中的groupby()可以灵活地完成各种分组计算的需求。

代码演示

import pandas as pd
# 创建DataFrame对象
data = pd.DataFrame([['三国', '王刚', 6, 8], ['盗梦空间', '王二', 8, 6], ['盗梦空间', '张三', 10, 8], ['海上钢琴师', '刘勇', 8, 8], ['海上钢琴师', '赵五', 8, 10]], columns=['电影名称', '影评师', '观前评分', '观后评分'])

# 根据"电影名称"分组,然后对每一组的“观后评分”计算平均值
data.groupby('电影名称')['观后评分'].mean()

# 也可以通过DataFrame的形式展示结果
data.groupby('电影名称')[['观后评分']].mean()

#对分组后的多个列求平均值
data.groupby('电影名称')[['观前评分', '观后评分']].mean()

# 通过多个字段分组
data.groupby(['电影名称', '影评师'])[['观后评分']].mean()

# 统计分组后每一组对应列的次数
count = data.groupby('电影名称')[['观后评分']].count()
# 修改列名称
count = count.rename(columns={'观后评分':'评分次数'})

实时效果反馈

1. 对DataFrame进行分组的方法是___________________

A corrwith()

B merge()

C groupby()

D mean()

2. DataFrame分组后计算平均值的方法是_________________,计算次数的方法是_______________

A mean()、 count()

B count()、mean()

C mean()、merge()

D count()、merge()

答案

1=>C 2=>A

  • 29
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值