30.1认识推荐系统
30.1.1 推荐系统的背景
- 随着信息技术和互联网的发展,人们逐渐从信息匮乏的时代走入了信息过
载(information overload)的时代。 - 在这个时代,无论是信息消费者还是信息生产者都遇到了很大的挑战
- 无明确需求
- 信息过载
30.1.2 什么是推荐系统
-
推荐系统任务:联系用户和产品,解决信息过载问题。
30.1.3 推荐系统和搜索引擎
- 相同点
- 帮助用户快速发现有用信息的工具
- 不同点
- 搜索引擎需要用户主动提供准确的关键词来寻找信息
- 推荐系统不需要用户提供明确的需求,而是通过分析用户的历史行为给用户的兴趣建模
- 关系
- 搜索引擎满足了用户有明确目的时的主动查找需求
- 推荐系统能够在用户没有明确目的的时候帮助他们发现感兴趣的新内容
30.1.4 推荐系统的工作原理
- 以看电影为例
- 向朋友咨询。这种方式称为社会化推荐,即让好友给自己推荐物品。
- 打开搜索引擎,输入自己喜欢的演员名,然后看看返回结果中还有什么电影是自己没有看过的。这种称为基于内容的推荐。
- 查看排行榜。这是基于流行度的推荐。
-
找到和自己历史兴趣相似的一群用户,看看他们最近在看什么电影。这是基于协同过滤的推荐。
30.1.5 推荐系统应用
- 19444人在进行视频或语音聊天
- 62.5万部优酷土豆视频被观看
- Facebook共产生701,389账号登陆
-
App Store上已有51,000个app被下载
30.1.5.1 推荐系统应用:电子商务
30.1.5.2 推荐系统应用:社交网站
30.1.5.3 用户画像
30.1.6 推荐系统评测
30.1.6.1 推荐系统实验方法
- 离线实验
- 通过日志系统获得用户行为数据, 并按照一定格式生成一个标准的数据集
- 将数据集按照一定的规则分成训练集和测试集
- 在训练集上训练用户兴趣模型, 在测试集上进行预测
- 通过事先定义的离线指标评测算法在测试集上的预测结果
- 问卷调查
- 确定用户满意度不低于现有算法
- 在线实验
- AB测试,确定指标优于现有算法
30.1.6.2 AB测试系统
30.1.6.3 推荐系统评测指标
- 用户满意度
- 预测准确度
- 覆盖率
- 多样性
- 新颖性
- 惊喜度
- 信任度
- 实时性
- 健壮性
30.1.6.4 预测准确度
- 预测准确度度量一个推荐系统或者推荐算法预测用户行为的能力
- 最重要的推荐系统离线评测指标
- 需要一个包含用户的历史行为记录的离线数据集
- 将该训练集通过时间分成训练集和测试集
- 通过在训练集上建立用户的行为和兴趣模型预测用户在测试集上的行为
- 计算预测行为和测试集上实际行为的重合度作为预测准确度
- 准确率(precision)/召回率(recall)
-
令R(u) 是根据用户在训练集上的行为给用户作出的推荐列表, 而T(u)是用户在测试集上的行为列表
-
30.1.6.5 覆盖率
- 描述一个推荐系统对物品长尾的发掘能力
- 覆盖率最简单的定义:推荐系统能够推荐出来的物品占总物品集合的比例
- 以图书推荐为例,出版社可能会很关心他们的书有没有被推荐给用户
- 覆盖率为100% 的推荐系统可以将每个物品都推荐给至少一个用户
- 热门排行榜的推荐覆盖率是很低的 , 它只会推荐那些热门的物品,这些物品在总物品中占的比例很小
- 一个好的推荐系统不仅需要有比较高的用户满意度,也要有较高的覆盖率
30.1.6.6 新颖性
- 新颖的推荐是指给用户推荐那些他们以前没有听说过的物品
- 在一个网站中实现新颖性的最简单方法 : 把那些用户之前在网站中对其有过行为的物品从推荐列表中过滤掉
- O'scar Celma在博士论文中研究了新颖度的评测
- 评测新颖度的最简单方法是利用推荐结果的平均流行度,因为越不
- 热门的物品越可能让用户觉得新颖
- 如果推荐结果中物品的平均热门程度较低,那么推荐结果就可能有
- 比较高的新颖性
- 但是 , 用推荐结果的平均流行度度量新颖性比较粗略,因为不同用户不知道的东西是不同的
- 要准确的统计新颖性需要做用户调查
30.1.6.7 总结
- 对于可以离线优化的指标,在给定覆盖率、多样性、新颖性等限制条件下,
尽量优化预测准确度。用一个数学公式表达,离线实验的优化目标是: - 最大化预测准确度
- 使得 : 覆盖率 > A
- 多样性 > B
- 新颖性 > C
30.1.7 推荐系统带来的收益
- 亚马逊科学家GregLinden称,亚马逊20%(之后一篇博文称35%)的销
售来自推荐算法; - Netflix在宣传资料中称,有60%用户是通过推荐系统找到自己感兴趣电影
和视频的; - 新闻阅读网站Digg宣称,使用推荐系统后,用户的digg行为明显活跃,
digg总数提高了40%,用户的好友数平均增加24%,评论数增加11%
30.2 推荐算法模型
30.2.1 推荐模型构建流程
30.2.1.1 使用什么数据
- 显性数据(Explicit data )
- Rating
- Comments
- 隐形数据
- Order history/return history
- Cart events
- Page views
- Click-thru
- Search log
30.2.1.2 使用什么特征?
- 一个给定的商品,可能被拥有类似品味或需求的用户购买
-
使用用户行为数据描述商品
30.2.1.3 数据表示/feature
-
将所有用户行为合并在一起 ,形成一个user-item 矩阵
30.2.1.4 推荐模型构建流程
30.2.2 推荐算法概述
- 基于内容过滤
- 从信息检索,和文本检索发展而来
- 基于商品描述及用户喜好描述,为用户推荐商品
- 协同过滤
- 基于用户行为为用户推荐感兴趣的商品
- 行为可以是过往的交易行为和商品评分,这种方式不需要显性的属性信息
- 混合推荐
30.2.2.1 基于内容过滤存在弊端
- 需了解商品内容
- 需要人工或自动标注信息
- 商品内容不能反映所有特点
- 冷启动问题
- 需要花时间学习哪些内容或feature 对用户而言是重要的
- 如果用户兴趣点改变了呢
-
Lack of serendipity
30.2.2.2 基于内容的推荐和协同过滤对比
30.2.3 基于协同过滤的推荐算法
- 协同过滤算法
- 基于用户行为的推荐
- 行为可以是过往的交易行为和商品评分,这种方式不需要显性的属性信息
- 协同过滤分类
- 最近邻(neighborhood )方法
- 借助商品的关系或者用户的关系
- 基于模型的方法
- 用隐含变量刻画商品
- 最近邻(neighborhood )方法
30.2.3.1 协同过滤算法之最邻近方法
- 最邻近方法
- 基于假设 : “跟你喜好相似的人喜欢的东西你也很有可能喜欢” 或“跟你喜欢的物品类似的物品你也很有可能喜欢 ”
- 分类
- User-based 方法
- 基于user的协同过滤,通过不同用户对item的评分来评测用户之间的相似性,基于用户之间的相似性做出推荐
- Item-based方法
- 基于item的协同过滤,通过用户对不同item的评分来评测item之间的相似性,基于item之间的相似性做出推荐
- User-based 方法
30.2.3.2 User-based
- 查找用户相似度
- 如何预测用户1对于商品4的喜好程度?
- 找到和用户1相似的用户且购买过商品4(基于购买记录)即为用户n
- 根据用户n对商品4的评价,以相似度为权重回填结果
- 针对所有用户组合,重复1~3,直到所有空格都被填满
30.2.3.3 Item-based
- 找到相似的Item
- 如何预测用户1对于商品4的喜好程度?
- 从用户1历史记录中,计算商品n和商品4的相似度(以其他用户的历史记录)
- 将用户1对于商品n的评价,以商品相似度为权重回填
- 针对所有商品组合,重复1~3直到所有空格都被填满
协同过滤
- 针对所有商品组合,重复1~3直到所有空格都被填满
30.2.4 协同过滤
30.2.4.1 相似度计算
30.2.4.2 K-Nearest Neighbor最近邻法
30.2.4.3 物品相似度计算
30.2.4.4 基于用户与物品的协同过滤比较
30.2.4.5 总结
- 基于用户的协同过滤要解决的问题
- 已知用户评分矩阵Matrix R(一般都是非常稀疏的)
-
推断矩阵中空格empty cells处的值
- UserCF存在的问题issues
- 对于一个新用户,很难找到邻居用户。
- 对于一个物品,所有最近的邻居都在其上没有多少打分。
- 基础解决方案
- 相似度计算最好使用皮尔逊相似度
- 考虑共同打分物品的数目,如乘上min(n,N)/N n:共同打分数 N:指定阈值
- 对打分进行归一化处理
- 设置一个相似度阈值
- 基于用户的协同过滤为啥不流行?
- 稀疏问题
- 数百万的用户计算,这量?
- 人是善变的
-
基于物品的协同过滤
- 基于物品的协同过滤优势!
- 计算性能高,通常用户数量远大于物品数量
- 可预先计算保留,物品并不善变
- 用户冷启动问题
- 引导用户把自己的一些属性表达出来
- 利用现有的开放数据平台
- 根据用户注册属性
- 推荐排行榜单
- 物品冷启动问题
- 文本分析
- 主题模型
- 打标签
-
推荐排行榜单
30.3 SVD
- SVD(Singular Value Decomposition)主要用来进行数据降维、特征提取、消除数据噪声、消去数据中的冗余信息、数据压缩等
- 用于提高机器学习算法的效果,或压缩数据存储空间。利用SVD能够用小的多的数据集表示原始数据,其实质是去除了噪声以及冗余项
- SVD常用于隐形语义检索的搜索系统(LSI)、隐性语义分析(LSA)、推荐引擎、图像压缩
- SVD原理
-
奇异值分解是一个能适用于任意的矩阵的一种分解的方法
-
- SVD应用于推荐
-
这里pi可以看成是描述用户的向量,qj是描述物品的向量,Σ表示用户和物品的耦合关系
-
- SVD缺点
- 时间复杂度是O(N^3)
- 评分矩阵太稀疏,分解难以进行
- SVD分解会导致大量的参数,而训练样本数有限,所以每个参数不能得到足够的训练,容易出现过拟合
- SVD的改良
-
LFM隐语义模型
-
30.3.1 隐语义模型
- 从数据出发,进行个性化推荐
- 用户和物品之间有着隐含的联系
- 隐含因子让计算机能理解就好
-
将用户和物品通过中介隐含因子联系起来
- 隐语义模型求解
-
梯度下降方向:
-
迭代求解:
-
- 隐语义模型负样本选择
- 对每个用户,要保证正负样本的平衡(数目相似)
- 选取那些很热门,而用户却没有行为的物品
- 对于用户—物品集K {(u,i)} 其中如果(u, i)是正样本,则有 𝑟𝑢𝑖 = 1,负样本则𝑟𝑢𝑖=0
- 隐语义模型参数选择
- 隐特征的个数F,通常F=100
- 学习速率alpha,别太大
- 正则化参数lambda,别太大
-
负样本/正样本比例 ratio
- 协同过滤VS隐语义
- 原理:协同过滤基于统计,隐语义基于建模
- 空间复杂度,隐语义模型较小
- 实时推荐依旧难,目前离线计算多
- 评估指标
- 评估标准:
-
准确度:
-
召回率:
- 令R(u)是根据用户在训练集上的行为给用户作出的推荐列表, T(u)是用户在测试集上的行为列表
-
覆盖率:
-
多样性:
-
- 评估标准:
-
推荐系统
- 基于模型的方法
- 思想
- 通过机器学习算法,在数据中找出模式,并将用户与物品间的互动方式模式化
- 基于模型的协同过滤方式是构建协同过滤更高级的算法
- 分类
- 基于图的模型
- 基于矩阵分解的方法
- 思想
- 基于图的模型
- 基于邻域的模型看做基于图的模型的简单形式
-
示例
- 原理
- 将用户的行为数据表示为二分图
- 基于二分图为用户进行推荐
- 根据两个顶点之间的路径数、路径长度和经过的顶点数来评价两个顶点的相关性
- 基于矩阵分解的模型
- 原理
- 根据用户与物品的潜在表现,我们就可以预测用户对未评分的物品的喜爱程度
- 基于矩阵分解的方法
- ALS交替最小二乘
- ALS-WR(加权正则化交替最小二乘法): alternating-least-squares with weighted-λ –regularization
- 将用户(user)对商品(item)的评分矩阵分解为两个矩阵:一个是用户对商品隐含特征的偏好矩阵,另一个是商品所包含的隐含特征的矩阵。在这个矩阵分解的过程中,评分缺失项得到了填充,也就是说我们可以基于这个填充的评分来给用户最商品推荐了。
- SVD奇异值分解矩阵
- ALS交替最小二乘
- 原理
30.3.2 ALS方法
- ALS的矩阵分解算法常应用于推荐系统中,将用户(user)对商品(item)的评分矩阵,分解为用户对商品隐含特征的偏好矩阵,和商品在隐含特征上的映射矩阵。
- 与传统的矩阵分解SVD方法来分解矩阵R(R∈ℝm×n)不同的是,ALS(alternating least squares)希望找到两个低维矩阵,以 R̃ =XY 来逼近矩阵R,其中 ,X∈ℝm×d, Y∈ℝd×n,这样,将问题的复杂度由O(mn)转换为O((m+n)d)。
- 计算X和Y过程:首先用一个小于1的随机数初始化Y,并根据公式求X,此时就可以得到初始的XY矩阵了,根据平方差和得到的X,重新计算并覆盖Y,计算差平方和,反复进行以上两步的计算,直到差平方和小于一个预设的数,或者迭代次数满足要求则停止
30.4 knn和svd推荐系统实验
In:
# pip install surprise
from surprise import Dataset,Reader
In:
#数据加载,user id | item id | rating | timestamp
reader = Reader(line_format='user item rating timestamp',sep='\t')
ratings = Dataset.load_from_file("../../data/ml-100k/ml-100k/u.data",reader=reader)
In:
ratings.raw_ratings
out:
[('196', '242', 3.0, '881250949'),
('186', '302', 3.0, '891717742'),
('22', '377', 1.0, '878887116'),
...]
In:
from surprise.model_selection import train_test_split
trainset,testset = train_test_split(ratings, test_size=0.25)
KNN重要参数:
- K: 邻居数
- sim_options: {'user_based':False, 'name':'pearson',min_support:5}
In:
#KNN建模
from surprise import KNNBaseline
sim_options = {'user_based':False, 'name':'pearson','min_support':5}
knn = KNNBaseline(k=30, sim_options=sim_options)
In:
knn.fit(trainset)
out:
Estimating biases using als...
Computing the pearson similarity matrix...
Done computing similarity matrix.
<surprise.prediction_algorithms.knns.KNNBaseline at 0x21e77443ac8>
In:
#预测评估
from surprise import accuracy
pred = knn.test(testset)
accuracy.rmse(pred) #越小越好
out:
RMSE: 0.9441
0.9440878017698798
SVD
In:
from surprise import SVD
svd参数:
- n_factors:隐含因子数
- lr_all:学习率
- reg_all:正则化惩罚因子
In:
svd = SVD()
svd.fit(trainset)
out:
<surprise.prediction_algorithms.matrix_factorization.SVD at 0x21e7746e788>
In:
s_pred = svd.test(testset)
accuracy.rmse(s_pred) #越小越好
out:
RMSE: 0.9437
0.9436782849102915
In:
#交叉校验
from surprise.model_selection import GridSearchCV
grids = {'reg_all':[0.1,1],'lr_all':[0.01,0.1]}
grid_search = GridSearchCV(SVD,grids,measures=['RMSE'],cv=3)
grid_search.fit(ratings)
In:
print(grid_search.best_params)
print(grid_search.best_score)
out:
{'rmse': {'reg_all': 0.1, 'lr_all': 0.01}}
{'rmse': 0.9280309749943877}