1 最近在看线性代数的相关知识,昨晚看到矩阵QR分解,然后后面又介绍了一个LFM的分解,说是矩阵能分解出k隐含维数据,看了一眼后面用梯度下降推的公式,感觉好复杂,就没有再往下面看。
2.坐在几个搞推荐的大神旁边,整天听到“转化率”,“反馈”什么的,因为本身不是搞这个方向的,所以听起来挺神奇。
3.刚好在CSDN上看到一篇讲LFM隐语义应用在推荐系统上的文章,想到能复习一下线代上将的内容又能了解一下推荐系统,就做了下面的研究。推到了公式,但是算法还没有具体实现,后面会附上参考伪代码
浅谈推荐系统
之前很早就听说过关于推荐的那个“啤酒尿布”的故事,这次学习推荐系统了解到:
专业术语解释:
- UserCF:User Collaborative Filter(用户协同过滤)
- itemCF:Item Collaborative Filter(项/元素协同过滤)
- 显性反馈:用户行为的一种反馈,包含正样本和负样本
- 隐性反馈:只包含正样本,不包含负样本
关于推荐的几个思路:
- UserCF:给用户B推荐的商品是和用户B相似的用户A相关的商品
- ItemCF:给用户推荐的商品是根据用户之前拥有的商品决定的
- 兴趣分类:
3.1. 传统分类不适合复杂场景
3.2. LFM(隐含语义分析)接下来要讲的内容
隐性语义
因为之前做的项目,有幸了解到NLP
领域隐含主题模型LDA
,模型认为一片文章讲道理是由多个主题构成的,而多个主题下面又包含关于这个主题的词语,即:doc-topic-word。利用该模型能够挖掘到文章之间隐含的主题关系,根据隐含主题的关联关系可以确定出文章之间的关系。和LDA
相关的叫做隐含语义分析技术。隐含语义分析技术采用基于用户行为统计的自动聚类,挖掘出a-latent-b的关系。
- 依据用户行为自动的进行分类,而非认为的确定类别个数
- 可以确定要分类的类别数量,数量多,粒度细
- 可以计算出物品属于某个类别的权重,哪个物品能够更好的代表这个类别,实现软分类
应用实例
在豆瓣图书推荐栏目,根据用户浏览的,购买的,收藏的关于图书的行为记录数据,要推荐给用户合适的图书。怎么实现图书推荐呢?这里主要根据LFM原理进行解释。假设有关于用户喜爱书籍的表格如下所示:
|
|——-|——–|——–|——-|
|user1: |侦探小说|科普 |计算机 |
| user2:| 数学 |机器学习| |
| … | … | … | … |
LFM矩阵分解
根据线性代数中的知识可知:将一个
m∗n
的矩阵
Am∗n
可以分解为具有
k
个隐变量的 latent factor
。
现假定有3个用户user1,user2,user3。他们各自分别对标记为item1,item2,item3,item4的图书(商品)的喜爱程度可形成一个 3∗4 的user-item兴趣矩阵 R3∗4 。
根据前面讲的LFM关于矩阵分解的知识,我们可以将这个
3∗4
的user-item矩阵
R3∗4
分解为含有3个隐含变量的
P3∗3∗Q3∗4
的矩阵,其中
P3∗3
表示用户对隐含类别的兴趣矩阵user-latent,而
Q3∗4
表示图书(商品)在隐含类别中所占权重的矩阵。即:
故,对用户商品user-item矩阵
R
中的每一个
让我们梳理一下逻辑
- 现要依据
P,Q
参数矩阵来估计
R
矩阵中的某个估计量
r¯u,i ,总体思路采用损失函数最小化来求取参数矩阵 P,Q 。 - 这里对 R 矩阵中样本的选取要注意:由于采用的是隐性反馈,只有正样本,没有负样本,所以要依据一定的原则选取合适数量的负样本。在样本选定后进行参数估计。
样本选取原则:1.样本中包含正,负标记的样本数量相当;2.在推荐系统中负样本侧重选择热门商品中用户没有点击的那些
故,对
其中:
1 第一个等号右边的表达式总体上表示了标记实际值 ru,i 与估计值 r¯u,i 之间差值平方,我们的目标就是将这个损失函数最小化,求得在最小化值下的 P,Q 参数矩阵。
2 后面带 λ 的两项为正则化项,是用来防止过拟合的。这里解释一下两个竖线表示2范数
3 这里损失函数最小化可以使用梯度下降法求得对应 pu,k 和 qi,k 的偏导数,利用一个 α 学习速率每次迭代 pu,k , qi,k 的值,直至达到阈值。
我们对上面的损失函数
c
分别对
通过确定学习速率 λ ,来对 pu,k , qi,k 进行优化:
总结
由此可以看出模型需要确定的几个参数:
1. 隐变量的个数
F
2. 梯度下降法迭代的次数:
3. 梯度下降学习速率:
α
4. 正则化项对应的参数:
λ
最后贴上python版本的伪代码:
def LFM(user_items, F, N, alpha, lambda):
[P, Q] = InitModel(user_items, F)
For step in range(0, N):
for user, items in user_item.iterms():
samples = RandSelectNegativeSamples(items)
for item, rui in samples.items():
eui = eui - Predict(user, item)
for f in range(0, F):
P[user][f] += alpha * (eui * Q[f][item] - lambda * P[user][f])
Q[f][item] += alpha * (eui * P[user][f] - lambda * Q[f][item])
alpha *= 0.9