1. LFM的产生背景
推荐算法常见的协同过滤算法有两种,一种是基于用户或基于物品的,这种推荐算法简单,但对稀疏矩阵的处理较为困难。因此有学者提出了LFM算法
此算法将用户对物品的评价拆分为用户对隐层因子的评价与物品含有隐层因子特征大小两个向量空间。从而解决了稀疏矩阵的问题。
2. LFM的特点
2.1. 矩阵拆分
2.2 梯度下降
3. LFM的网络结构
上图为盗图,从上图可以看到最左边的矩阵为稀疏矩阵,表示为A,为6*12的矩阵,表示6个用户对12个物品的评价,其中空白的部分表示用户未对此物品有过评价,如果将factors表示为特征,那么6*3的Q矩阵则表示6个用户分别对3个不同的属性特征的评分;而12*3的P矩阵则表示这12个物品分别具有这3个不同属性特征的“分量”。然后利用向量的内积,让Q*P的内积无限逼近于用户对物品的真实评分A矩阵。
4. LFM的算法思想
这里依旧不说话,默默上公式:
从算法我们可以看到,不同于基于内容的推荐算法,隐向量P和隐向量Q都是模型根据训练数据训练得到的,而不需要人为标记。
5. LFM的源码实现
# _*_coding:utf-8 _*_
__author__ = "ricky"
import random
import math
class LFM(object):
def __init__(self, rating_data, F, alpha=0.1, lmbd=0.1, max_iter=500):
"""
:param rating_data: rating_data是[(user,[(item,rate)]]类型
:param F: 隐因子个数
:param alpha: 学习率
:param lmbd: 正则化
:param max_iter:最大迭代次数
"""
self.F = F
self.P = dict() # R=PQ^T,代码中的Q相当于博客中Q的转置
self.Q = dict()
self.alpha = alpha
self.lmbd = lmbd
self.max_iter = max_iter
self.rating_data = rating_data
'''随机初始化矩阵P和Q'''
for user, rates in self.rating_data:
self.P[user] = [random.random() / math.sqrt(self.F)
for x in range(self.F)]
for item, _ in rates:
if item not in self.Q:
self.Q[item] = [random.random() / math.sqrt(self.F)
for x in range(self.F)]
def train(self):
"""
随机梯度下降法训练参数P和Q
:return:
"""
for step in range(self.max_iter):
for user, rates in self.rating_data:
for item, rui in rates:
hat_rui = self.predict(user, item)
err_ui = rui - hat_rui
for f in range(self.F):
self.P[user][f] += self.alpha * (err_ui * self.Q[item][f] - self.lmbd * self.P[user][f])
self.Q[item][f] += self.alpha * (err_ui * self.P[user][f] - self.lmbd * self.Q[item][f])
self.alpha *= 0.9 # 每次迭代步长要逐步缩小
def predict(self, user, item):
"""
:param user:
:param item:
:return:
预测用户user对物品item的评分
"""
return sum(self.P[user][f] * self.Q[item][f] for f in range(self.F))
if __name__ == '__main__':
'''用户有A B C,物品有a b c d'''
rating_data = list()
rate_A = [('a', 1.0), ('b', 1.0)]
rating_data.append(('A', rate_A))
rate_B = [('b', 1.0), ('c', 1.0)]
rating_data.append(('B', rate_B))
rate_C = [('c', 1.0), ('d', 1.0)]
rating_data.append(('C', rate_C))
lfm = LFM(rating_data, 2)
lfm.train()
for item in ['a', 'b', 'c', 'd']:
print(item, lfm.predict('A', item)) # 计算用户A对各个物品的喜好程度
用户A对各个物品的预测评分结果为:
6. 参考文献
https://blog.csdn.net/weixin_41843918/article/details/90216729,此blog很清晰,就照搬了