为知识付费:https://time.geekbang.org/column/intro/74
本文仅为个人学习笔记。
推荐系统:是一种信息过滤系统,预测用户(User)对物品(Item)的评分和偏好。
推荐系统的问题模式
分为评分预测和行为预测。
评分预测
假如用户消费完一个物品之后会给出一个打分,比如通常是 1~5分,那么我们要做的就是建立一个模型,利用用户历史上打过分的物品,预测用户对一个没有见过的物品的打分。
显示反馈:用户对物品的明确评分,直接表达了用户对物品的态度。
隐式反馈:与显示反馈相对,实际中用户的物品的评分这类数据不易收集,我们需要利用隐式反馈,即用户的各种行为(如点击,浏览,收藏等),去找到用户对物品的态度。即行为预测。
行为预测
行为预测包括:直接预测行为本身发生的概率,和预测物品的相对排序。
其中直接预测行为本身发生的概率,也称为点击率预估(Click through rate, CTR)。即计算用户是否会点击某一物品的概率。当然,这个行为也可以换成别的行为,如收藏。
因此行为预测就是指利用隐式反馈数据预测某种行为发生的概率。
隐式反馈的一些好处:
隐式反馈数据比显示反馈数据更加稠密。
隐式反馈更加符合用户内心的真实想法。
隐式反馈和模型的目标函数关联更加密切。
推荐系统存在的顽疾
冷启动问题,探索与利用问题,安全问题。
冷启动问题
如何解决新用户,或者新物品的推荐。
探索与利用问题 (EE问题,Explore & Exploit)
假设我们已经知道了用户的喜好,那么最合理的推荐方式是:
大部分推荐他感兴趣的(Exploit对用户身上已经探明的兴趣加以利用),小部分试探新的兴趣(Explore探明用户还不知道的兴趣)。
如何平衡这里的大部分和小部分构成了EE问题。
安全问题
给出的推荐结果不靠谱,或者收集了不靠谱的脏数据对产品产生了影响。
推荐系统的关键元素
四个关键因素:1. UI和UE 2. 数据 3.领域知识 4.算法
重要性依次递减。
内容推荐
推荐系统初始阶段,由于用户行为数据较少,通常采用基于内容的推荐。
用户画像 User Profile
构建方法:
- 直接利用原始数据,如注册资料,用户购买历史,阅读历史等
- 统计数据,从用户历史行为中挖掘出标签,如兴趣标签,然后在标签维度做数据统计
- 词向量,利用机器学习的方式将用户特征以向量的形式表示
利用文本信息构建用户画像
用户端:
- 注册资料中的姓名,个人签名
- 发表的评论,动态,日记等;
- 聊天记录
物品端:
- 物品的标题、描述
- 物品本身的内容(如新闻资讯)
- 物品的其他属性的文本
结构化文本
将非结构化的数据结构化。
- 关键词提取:TF-IDF,TextRank
- 实体识别: NER, Named-Entity Recognition, 采用HMM隐马模型和CRF条件随机场
- 内容分类: 将文本按照分类体系分类,用分类来表达较粗粒度的结构化信息。工具:FastText
- 文本:聚类
- 主题模型:LDA, 工具:gensim, PLDA
- 嵌入embedding:Word2Vec
近邻推荐
协同过滤:基于记忆的协同过滤,基于模型的协同过滤。
基于记忆:基于历史行为,推荐相似的消费过的东西,或者推荐相似的人消费的东西
基于模型:从用户物品关系矩阵中学习模型
基于用户的协同过滤
属于基于记忆的协同过滤的一种。根据用户的历史消费行为找到和该用户相似的用户,然后将这类用户消费的新物品作为推荐。
- 构建用户物品矩阵,每一行数据代表是用户的向量
- 计算用户之间的相似度
- 为每个用户产生推荐结果
产出结果:
通常用于“看了又看“和”买了又买“。
计算物品相似度
计算推荐结果:TopK推荐,相关推荐, Slope One
Slope one算法
经典的基于物品的相似度计算无法实时更新。Slope One算法可以进行在线更新。
针对评分矩阵,而不是行为矩阵。计算的是物品之间的距离,而不是相似度。下图是用户物品评分矩阵。
通过两两计算物品之间的差距得到,注意现在是物品物品矩阵:
括号里的数量代表两个物品的共同用户数量,如物品A和物品B有两个共有用户,因此数值为2,同理,物品B和物品A的共有用户数仍为2。
括号外边的数代表两个物品间的距离。如物品A和物品B, 有两个共有用户,则计算两个共有用户在两个物品评分的差值的均值:$\frac{(5-3)+(3-4)}{2}=0.5$,注意,这个是有序的,因此物品B到A的距离为-0.5.
计算出物品间的距离的作用:如果只知道用户3给物品B的评分是2,并且知道了物品B到物品A的差距是0.5,则可以预测用户3对物品A的评分为2.5.
但实际上用户3也给物品C进行了评分,如果只根据用户3对物品C的评分5进行预测,我们可以计算出物品A的分数为8,现在就根据共有用户数作为加权得出最后的结果:
相似度
机器学习和相似度是推荐算法中常用的两种方式。
近邻推荐的核心就是相似度的选择。
相似度的计算对象是向量。
欧氏距离
欧式距离度量的是两个点之间的距离,但相似度计算度量结果希望是在[-1,1]或者[0,1]之间,因此还要对欧氏距离进行转换。
余弦相似度
余弦相似度与向量的长度无关,因为会对向量长度进行归一化。因此,在利用余弦相似度情况下的两个向量,只要方向相似,而不用考虑大小,就可以认为是相似的。
皮尔逊相关度
改进版的余弦相似度,先对向量进行了中心化,然后再计算余弦相似度。
杰卡德相似度
计算两个集合中的交集元素个数在并集元素中所占的比例,适合布尔类型向量。
在社交网络中计算好友的相似度?
采用如下特征:帖子发布数量,月均发帖数量,平均帖子字数,头像,一些标签数据,例如是否大V,是否营销号,是否网红,职业等标签数据。另外还可以统计发文Top关键词向量及词频。标签数据可计算杰卡德相似度,Top关键词可计算余弦相似度,发布量,字数等可计算欧氏距离,然后再融合这几种相似度得到总和相似度。
近邻推荐存在的问题
- 物品之间存在相关性,信息量并不随着向量维度增加而线性增加;
- 矩阵元素稀疏,计算结果不稳定,增减一个向量维度,导致近邻结果差异很大的情况存在。
矩阵分解
Netflix Prize解决的是评分预测问题。
矩阵分解可以解决近邻推荐存在的问题,简单来说,矩阵分解就是把原来的大矩阵近似分解为两个小矩阵的乘积。矩阵分解的物理意义,就是把用户和物品都映射到一个k维空间,这样每一个用户得到一个向量p, 每一个物品得到一个向量q,两个向量的点积即为预测出的用户对物品的预测评分。
矩阵分解可以看作是因子分解机(FM)的特例。
SVD
基础的SVD
目标损失函数:
第一部分:控制着模型的偏差,第二部分:正则项,控制着模型的方差
增加偏置信息
存在情况:有些用户习惯给出偏高的评分;有些物品通常会收到偏高的评分。
因此改进SVD后得到带偏置信息的SVD.
一个用户给一个物品的评分会有4部分构成:
分别代表:全局平均分,物品的评分偏置,用户的评分偏置,用户和物品之间的兴趣偏好。
增加了偏置项的SVD目标函数变为:
增加历史行为
存在情况:有的用户评分少。即,显示反馈比隐式反馈少,因此可以利用隐式反馈来弥补。
SVD++结合用户的隐式反馈行为和属性。
假设评分矩阵中的物品有一个隐因子向量(维度为k),因此用户有过行为的每个物品就有一个隐因子向量,把该用户操作过的物品隐因子加起来,用来表示用户的兴趣偏好。
类似的,用户属性进行onehot后,对每个特征也存在一种隐因子向量表示,将该用户的所有属性的对应的隐因子向量相加,也代表了一些偏好。
SVD++的目标函数,只要在用户向量p的基础上进行扩展增加隐式反馈向量x和用户属性向量y), 因此在学习时对隐向量也进行了学习:
时间因素
a. 对评分按照时间加权,让久远的评分趋近平均值;b. 对评分时间划分区间,不同区间学习出不同的隐因子向量;
c. 对特殊时间点单独进行训练
ALS 交替最小二乘原理
在有了目标函数以后,优化方法通常有两种:随机梯度下降,交替最小二乘(ALS),ALS在实际中应用较多。
ALS的核心概念就是交替。我们的任务是,找到两个矩阵P和Q, 让她们相乘后约等于原矩阵:
但是P和Q是未知的 ,因此无法直接求得。假设Q现在是已知的,那么P就可以根据R和Q计算:
反之,假设知道了P, 那么就可以求出Q. 交替的思路就是不断假设某一个子矩阵是已知的。
具体步骤:
- 初始化随机矩阵Q
- 将Q当作已知,根据R计算初矩阵P
- 得到矩阵P后,将P当作已知,重新去计算矩阵Q
- 两个过程交替进行,直到误差可以接受
ALS实际上就是对目标函数进行优化的方法,通过先固定其他维度,在单独对某一维度进行更新。
ALS-WR 隐式反馈+ALS
隐式反馈关注的是用户的行为,而不是用户的评分。
One-Class问题:
如果把预测用户行为看为二分类问题,猜测用户会不会做某件事,但实际上收集到的数据只有一种:用户干了某件事,而用户明确”不干“某件事的数据没有明确数据。
在ALS引入隐式反馈,得到加权的ALS.
加权的概念:查看商品的次数越多,代表喜欢程度越高,因此行为次数可以作为加权。
加权交替最小二乘:
如果用户对物品无隐式反馈则认为评分为0
如果用户对物品有至少一次隐式反馈则认为评分是1,次数作为该评分的置信度。
因此,现在目标函数变为:
其中多出来的$c_{ui}$就是置信度,因此目标函数变成了带权重的函数,次数越多,就越可信。实际上,置信度通常不直接用次数表示,而是如下表示:
其中α是超参数,C就是实际次数。
存在问题:
对于没有反馈的缺失值,在设定下,取值为0的评分非常多,因此我们不能直接把所有的缺失值作为负类别。
原因:
本身隐式反馈只有正类别是确定的,而负类别是假设的
导致正负样本不平衡,负样本多于正样本
因此需要对负样本进行采样, 挑选一部分缺失值作为负样本即可:
随机均匀采样和正类别一样多(不靠谱)
按照物品的热门程度采样(实践中采用): 一个越热门的物品, 用户越可能直到他的存在.如果这种情况下, 用户对他还没有反馈就表明这真的是负样本.
推荐计算
当我们得到用户和物品的隐向量后,直接点积就可以得到预测结果了。
但实际应用中,由于维度依然很大,直接计算点积复杂度很高。
FaceBook给出了两种方案:
利用专门设计的数据结构存储所有物品的隐因子向量,从而实现通过一个用户向量可以返回最相似的k个物品。工具:Faiss
先将物品的隐因子做聚类,然后在逐一计算用户和每个聚类中心的推荐分数,给用户推荐物品就变成了给用户推荐物品聚类。得到推荐的聚类后,再从聚类中挑选出物品作为推荐结果。
贝叶斯个性化排序 BPR
矩阵分解的本质上是预测用户对一个物品的偏好程度,然后根据偏好程度进行排序。这是一种point wise的排序,很难得到最优排序。
接下来利用pair-wise的方式看待矩阵分解。
评价指标
AUC的计算步骤:
用模型给样本计算推荐分数
得到打过分的样本,每条样本保留两个信息,第一个是分数,第二个代表用户有没有消费过,1代表消费,0代表未消费
按照分数对样本重新排序,降序排列
给每一个样本赋一个排序值,第一位r1=n, r2=n-1, …; 如果几个样本分数一样, 需要将排序值调整为平均值;
最终按照如下公式计算出AUC
AUC的值越接近1越好,接近0.5是最差的。
BPR模型主要分为:样本构造,目标函数,学习框架
样本构造:
在矩阵分解中,样本形式为:<用户,物品,反馈>。其中反馈又包含真实反馈和缺失值,缺失值充当的是负样本职责。
BPR中关注的是物品之间对于用户的相对排序,因此构造的样本是:<用户,物品1,物品2,两个物品相对顺序>.
其中,两个物品的相对顺序是指:
如果物品1是消费过的,而物品2不是, 那么相对顺序值为1,正样本;否则负样本
如果物品1和物品2同时消费或未消费过,则不构成样本
具体贝叶斯个性化排序参见我的另一篇博客.