推荐系统36式笔记(一)

为知识付费:https://time.geekbang.org/column/intro/74

本文仅为个人学习笔记。

推荐系统:是一种信息过滤系统,预测用户(User)对物品(Item)的评分和偏好。

推荐系统的问题模式

分为评分预测和行为预测。

评分预测

假如用户消费完一个物品之后会给出一个打分,比如通常是 1~5分,那么我们要做的就是建立一个模型,利用用户历史上打过分的物品,预测用户对一个没有见过的物品的打分。

显示反馈:用户对物品的明确评分,直接表达了用户对物品的态度。

隐式反馈:与显示反馈相对,实际中用户的物品的评分这类数据不易收集,我们需要利用隐式反馈,即用户的各种行为(如点击,浏览,收藏等),去找到用户对物品的态度。即行为预测。

行为预测

行为预测包括:直接预测行为本身发生的概率,和预测物品的相对排序。

其中直接预测行为本身发生的概率,也称为点击率预估(Click through rate, CTR)。即计算用户是否会点击某一物品的概率。当然,这个行为也可以换成别的行为,如收藏。

因此行为预测就是指利用隐式反馈数据预测某种行为发生的概率。

隐式反馈的一些好处:

  1. 隐式反馈数据比显示反馈数据更加稠密。

  2. 隐式反馈更加符合用户内心的真实想法。

  3. 隐式反馈和模型的目标函数关联更加密切。

推荐系统存在的顽疾

冷启动问题,探索与利用问题,安全问题。

  1. 冷启动问题

    如何解决新用户,或者新物品的推荐。

  2. 探索与利用问题 (EE问题,Explore & Exploit)

    假设我们已经知道了用户的喜好,那么最合理的推荐方式是:

    大部分推荐他感兴趣的(Exploit对用户身上已经探明的兴趣加以利用),小部分试探新的兴趣(Explore探明用户还不知道的兴趣)。

    如何平衡这里的大部分和小部分构成了EE问题。

  3. 安全问题

    给出的推荐结果不靠谱,或者收集了不靠谱的脏数据对产品产生了影响。

    推荐系统的关键元素

四个关键因素:1. UI和UE 2. 数据 3.领域知识 4.算法

重要性依次递减。

内容推荐

推荐系统初始阶段,由于用户行为数据较少,通常采用基于内容的推荐。

用户画像 User Profile

构建方法:

  1. 直接利用原始数据,如注册资料,用户购买历史,阅读历史等
  2. 统计数据,从用户历史行为中挖掘出标签,如兴趣标签,然后在标签维度做数据统计
  3. 词向量,利用机器学习的方式将用户特征以向量的形式表示

利用文本信息构建用户画像

用户端:

  1. 注册资料中的姓名,个人签名
  2. 发表的评论,动态,日记等;
  3. 聊天记录

物品端:

  1. 物品的标题、描述
  2. 物品本身的内容(如新闻资讯)
  3. 物品的其他属性的文本

结构化文本

将非结构化的数据结构化。

  1. 关键词提取:TF-IDF,TextRank
  2. 实体识别: NER, Named-Entity Recognition, 采用HMM隐马模型和CRF条件随机场
  3. 内容分类: 将文本按照分类体系分类,用分类来表达较粗粒度的结构化信息。工具:FastText
  4. 文本:聚类
  5. 主题模型:LDA, 工具:gensim, PLDA
  6. 嵌入embedding:Word2Vec

近邻推荐

协同过滤:基于记忆的协同过滤,基于模型的协同过滤。

基于记忆:基于历史行为,推荐相似的消费过的东西,或者推荐相似的人消费的东西

基于模型:从用户物品关系矩阵中学习模型

基于用户的协同过滤

属于基于记忆的协同过滤的一种。根据用户的历史消费行为找到和该用户相似的用户,然后将这类用户消费的新物品作为推荐。

  1. 构建用户物品矩阵,每一行数据代表是用户的向量
  2. 计算用户之间的相似度
  3. 为每个用户产生推荐结果

产出结果:

  1. 相似用户推荐
  2. 基于相似用户的物品推荐

    基于物品的协同过滤

通常用于“看了又看“和”买了又买“。

  1. 计算物品相似度

  2. 计算推荐结果:TopK推荐,相关推荐, Slope One

Slope one算法

经典的基于物品的相似度计算无法实时更新。Slope One算法可以进行在线更新。

针对评分矩阵,而不是行为矩阵。计算的是物品之间的距离,而不是相似度。下图是用户物品评分矩阵。

1537862529368

通过两两计算物品之间的差距得到,注意现在是物品物品矩阵

1537862596768

括号里的数量代表两个物品的共同用户数量,如物品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,1]或者[0,1]之间,因此还要对欧氏距离进行转换。

  2. 余弦相似度

    余弦相似度与向量的长度无关,因为会对向量长度进行归一化。因此,在利用余弦相似度情况下的两个向量,只要方向相似,而不用考虑大小,就可以认为是相似的。

  3. 皮尔逊相关度

    改进版的余弦相似度,先对向量进行了中心化,然后再计算余弦相似度。

  4. 杰卡德相似度

    计算两个集合中的交集元素个数在并集元素中所占的比例,适合布尔类型向量。

在社交网络中计算好友的相似度?

采用如下特征:帖子发布数量,月均发帖数量,平均帖子字数,头像,一些标签数据,例如是否大V,是否营销号,是否网红,职业等标签数据。另外还可以统计发文Top关键词向量及词频。标签数据可计算杰卡德相似度,Top关键词可计算余弦相似度,发布量,字数等可计算欧氏距离,然后再融合这几种相似度得到总和相似度。

近邻推荐存在的问题

  1. 物品之间存在相关性,信息量并不随着向量维度增加而线性增加;
  2. 矩阵元素稀疏,计算结果不稳定,增减一个向量维度,导致近邻结果差异很大的情况存在。

矩阵分解

Netflix Prize解决的是评分预测问题。

矩阵分解可以解决近邻推荐存在的问题,简单来说,矩阵分解就是把原来的大矩阵近似分解为两个小矩阵的乘积。矩阵分解的物理意义,就是把用户和物品都映射到一个k维空间,这样每一个用户得到一个向量p, 每一个物品得到一个向量q,两个向量的点积即为预测出的用户对物品的预测评分。

矩阵分解可以看作是因子分解机(FM)的特例。

SVD

  1. 基础的SVD

    目标损失函数:

    1537965667181

    第一部分:控制着模型的偏差,第二部分:正则项,控制着模型的方差

  2. 增加偏置信息

    存在情况:有些用户习惯给出偏高的评分;有些物品通常会收到偏高的评分。

    因此改进SVD后得到带偏置信息的SVD.

    一个用户给一个物品的评分会有4部分构成:

    1537966379478

    分别代表:全局平均分,物品的评分偏置,用户的评分偏置,用户和物品之间的兴趣偏好。

    增加了偏置项的SVD目标函数变为:

    1537970586067

  3. 增加历史行为

    存在情况:有的用户评分少。即,显示反馈比隐式反馈少,因此可以利用隐式反馈来弥补。

    SVD++结合用户的隐式反馈行为和属性。

    假设评分矩阵中的物品有一个隐因子向量(维度为k),因此用户有过行为的每个物品就有一个隐因子向量,把该用户操作过的物品隐因子加起来,用来表示用户的兴趣偏好。

    类似的,用户属性进行onehot后,对每个特征也存在一种隐因子向量表示,将该用户的所有属性的对应的隐因子向量相加,也代表了一些偏好。

    SVD++的目标函数,只要在用户向量p的基础上进行扩展增加隐式反馈向量x和用户属性向量y), 因此在学习时对隐向量也进行了学习:

    1537971223313

  4. 时间因素
    a. 对评分按照时间加权,让久远的评分趋近平均值;

    b. 对评分时间划分区间,不同区间学习出不同的隐因子向量;

    c. 对特殊时间点单独进行训练

ALS 交替最小二乘原理

在有了目标函数以后,优化方法通常有两种:随机梯度下降,交替最小二乘(ALS),ALS在实际中应用较多。

ALS的核心概念就是交替。我们的任务是,找到两个矩阵P和Q, 让她们相乘后约等于原矩阵:

1538012743215

但是P和Q是未知的 ,因此无法直接求得。假设Q现在是已知的,那么P就可以根据R和Q计算:

1538012815883

反之,假设知道了P, 那么就可以求出Q. 交替的思路就是不断假设某一个子矩阵是已知的。

具体步骤:

  1. 初始化随机矩阵Q
  2. 将Q当作已知,根据R计算初矩阵P
  3. 得到矩阵P后,将P当作已知,重新去计算矩阵Q
  4. 两个过程交替进行,直到误差可以接受

ALS实际上就是对目标函数进行优化的方法,通过先固定其他维度,在单独对某一维度进行更新。

ALS-WR 隐式反馈+ALS

隐式反馈关注的是用户的行为,而不是用户的评分。

One-Class问题

如果把预测用户行为看为二分类问题,猜测用户会不会做某件事,但实际上收集到的数据只有一种:用户干了某件事,而用户明确”不干“某件事的数据没有明确数据。

在ALS引入隐式反馈,得到加权的ALS.

加权的概念:查看商品的次数越多,代表喜欢程度越高,因此行为次数可以作为加权。

加权交替最小二乘

  1. 如果用户对物品无隐式反馈则认为评分为0

  2. 如果用户对物品有至少一次隐式反馈则认为评分是1,次数作为该评分的置信度。

因此,现在目标函数变为:

1538036466652

其中多出来的$c_{ui}$就是置信度,因此目标函数变成了带权重的函数,次数越多,就越可信。实际上,置信度通常不直接用次数表示,而是如下表示:

1538037266126

其中α是超参数,C就是实际次数。

存在问题:

对于没有反馈的缺失值,在设定下,取值为0的评分非常多,因此我们不能直接把所有的缺失值作为负类别。

原因:

  1. 本身隐式反馈只有正类别是确定的,而负类别是假设的

  2. 导致正负样本不平衡,负样本多于正样本

因此需要对负样本进行采样, 挑选一部分缺失值作为负样本即可:

  1. 随机均匀采样和正类别一样多(不靠谱)

  2. 按照物品的热门程度采样(实践中采用): 一个越热门的物品, 用户越可能直到他的存在.如果这种情况下, 用户对他还没有反馈就表明这真的是负样本.

推荐计算

当我们得到用户和物品的隐向量后,直接点积就可以得到预测结果了。

但实际应用中,由于维度依然很大,直接计算点积复杂度很高。

FaceBook给出了两种方案:

  1. 利用专门设计的数据结构存储所有物品的隐因子向量,从而实现通过一个用户向量可以返回最相似的k个物品。工具:Faiss

  2. 先将物品的隐因子做聚类,然后在逐一计算用户和每个聚类中心的推荐分数,给用户推荐物品就变成了给用户推荐物品聚类。得到推荐的聚类后,再从聚类中挑选出物品作为推荐结果。

贝叶斯个性化排序 BPR

矩阵分解的本质上是预测用户对一个物品的偏好程度,然后根据偏好程度进行排序。这是一种point wise的排序,很难得到最优排序。

接下来利用pair-wise的方式看待矩阵分解。

评价指标

AUC的计算步骤:

  1. 用模型给样本计算推荐分数

  2. 得到打过分的样本,每条样本保留两个信息,第一个是分数,第二个代表用户有没有消费过,1代表消费,0代表未消费

  3. 按照分数对样本重新排序,降序排列

  4. 给每一个样本赋一个排序值,第一位r1=n, r2=n-1, …; 如果几个样本分数一样, 需要将排序值调整为平均值;

  5. 最终按照如下公式计算出AUC

    1538097247329

AUC的值越接近1越好,接近0.5是最差的

BPR模型主要分为:样本构造,目标函数,学习框架

样本构造

在矩阵分解中,样本形式为:<用户,物品,反馈>。其中反馈又包含真实反馈和缺失值,缺失值充当的是负样本职责。

BPR中关注的是物品之间对于用户的相对排序,因此构造的样本是:<用户,物品1,物品2,两个物品相对顺序>.

其中,两个物品的相对顺序是指:

  1. 如果物品1是消费过的,而物品2不是, 那么相对顺序值为1,正样本;否则负样本

  2. 如果物品1和物品2同时消费或未消费过,则不构成样本

具体贝叶斯个性化排序参见我的另一篇博客.