基于模型的协同过滤思想
●基本思想
-用户具有一定的特征,决定着他的偏好选择;
-物品具有一定的特征,影响着用户需是否选择它;
-用户之所以选择某一个商品,是因为用户特征与物品特征相互匹配;
●基于这种思想,模型的建立相当于从行为数据中提取特征,给用户和物品同时打上“标签”;这和基于人口统计学的用户标签、基于内容方法的物品标签本质是一样的,都是特征的提取和匹配
●有 显性特征时(比如用户标签、物品分类标签)我们可以直接匹配做出推荐;没有时,可以根据已有的偏好数据,去发掘出隐藏的特征,这需要用到隐语义模型(LFM)
基于模型的协同过滤
●基于模型的协同过滤推荐,就是基于样本的用户偏好信息,训练一个推荐模型,然后根据实时的用户喜好的信息进行预测新物品的得分,计算推荐
●基于近邻的推荐和基于模型的推荐
-基于近邻的推荐是在预测时直接使用已有的用户偏好数据,通过近邻数据来预测对新物品的偏好(类似分类)
-而基于模型的方法, 是要使用这些偏好数据来训练模型,找到内在规律,再用模型来做预测(类似回归)
●训练模型时,可以基于标签内容来提取物品特征,也可以让模型去发掘物品的潜在特征;这样的模型被称为隐语义模型(L atent Factor Model, LFM)
●用隐语义模型来进行协同过滤的目标
-揭示隐藏的特征 ,这些特征能够解释为什么给出对应的预测评分这类特征可能是无法直接用语言解释描述的,事实上我们并不需要知道,类似"玄学"
● 通过矩阵分解进行降维分析
-协同过滤算法非常依赖历史数据,而一般的推荐系统中,偏好数据又往往是稀疏的;这就需要对原始数据做降维处理
-分解之后的矩阵 ,就代表了用户和物品的隐藏特征
隐语义模型的实例
一基于概率的隐语义分析 ( pLSA )
-隐式迪利克雷分布模型 ( LDA )
-矩阵因子分解模型 (基于奇异值分解的模型, SVD )
●假设用户物品评分矩阵为R, 现在有m个用户,n个物品
●我们想要发 现k个隐类,我们的任务就是找到两个矩阵P和Q,使这两个矩阵的乘积近似等于R,即将用户物品评分矩阵R分解成为两个低维矩阵相乘:
矩阵因子分解:
●我们可以认为,用户之所以给电影打出这样的分数,是有内在原因的,我们可以挖掘出影响用户打分的隐藏因素,进而根据未评分电影与这些隐藏因素的关联度,决定此未评分电影的预测评分
●应该有- -些隐藏的因素,影响用户的打分,比如电影:演员、题材、年代.甚至不一定是人直接可以理解的隐藏因子
●找到隐藏因子,可以对user和item进行关联(找到是由于什么使得user喜欢/不喜欢此item,什么会决定user喜欢/不喜欢此item),就可以推测用户是否会喜欢某一部未看过的电影
●对于用户看过的电影,会有相应的打分,但一个用户不可能看过所有电影,对于用户没有看过的电影是没有评分的,因此用户评分矩阵大部分项都是空的,是一个稀疏矩阵
● 如果我们能够根据用户给已有电影的打分推测出用户会给没有看过的电影的打分,那么就可以根据预测结果给用户推荐他可能打高分的电影
现在我们利用矩阵因子分解现在来做一个-一般性的分析:
一个m*n的打分矩阵R可以用两个小矩阵和的乘积R来近似:
得到和的乘积R不再是稀疏的,之前R中没有的项也可以由P、Q的乘积算出,这就得到了一个预测评分矩阵
如果得到的预测评分矩阵与原评分矩阵R在已知评分位置上的值都近似,那么我们认为它们在预测位置上的值也是近似的
●现在的问题是,怎样得到这样的分解方式R= PxQ呢?
●矩阵分解得到的预测评分矩阵R,与原评分矩阵R在已知的评分项上可能会有误差,我们的目标是找到一个最好的分解方式,让分解之后的预测评分矩阵总误差最小
➢损失函数
我们选择平方损失函数,并且加入正则化项,以防过拟合
●现在,矩阵因子分解的问题已经转化成了一个标准的优化问题,需要求解P、Q,使目标损失函数取最小值
●最小化过程的求解,- -般采用随机梯度下降算法或者交替最小二乘法来实现
➢交替最小二乘法 ( Alternating Least Squares , ALS )
●AL S的思想是,由于两个矩阵P和Q都未知,且通过矩阵乘法耦合在一起,为了使它们解耦,可以先固定Q,把P当作变量,通过损失函数最小化求出P,这就是一个经典的最小二乘问题;再反过来固定求得的P,把Q当作变量,求解出Q:如此交替执行,直到误差满足阈值条件,或者到达迭代上限
ALS算法
● ALS算法具体过程如下:
I. 为Q指定一个初值Qo, 可以是随机生成或者全局平均值
II. 固定当前Qo值,求解Po
I.固定当前P。值,求解Q1
IV. 固定当前Q1值,求解P1
V. ... (重复以上过程)
VI.直到损 失函数的值C收敛,迭代结束
➢求解过程
●以固定Q,求解P为例
●由于每一个用户u都是相互独立的,当Q固定时,用户特征向量Pu应该取得的值与其它用户特征向量无关;所以每- -个Pu都可以单独求解
●优化目标可转化为
●那么我们的目标变成了:求每一个用户特征向量,使得取得最小值
● 对求偏导:
● 是物品i的特征向量,所以等式可以写为:
●可以看到,物品特征向量构成的矩阵,其实就是Q:
●所以可以得到:
●解得:
●这样一一解出每一个,就可以得到这一步的用户特征矩阵P了
●同样,下一次固定P时,可以解得
●对每一个Pu求偏导
梯度下降算法代码实现:
# 0 引入依赖
import numpy as np
import pandas as pd
# 1 数据准备
# 评分矩阵R
R=np.array([[4,0,2,0,1],
[2,3,2,0,1],
[4,0,6,0,1],
[5,0,0,0,1],
[1,0,2,7,1],
[0,0,0,3,1],
])
print(len(R[0]))
#2 算法实现
"""
@输入参数:
R: M*N 的评分矩阵
K:隐特征向量个数
steps:最大迭代次数
alpha:步长
lamda:正则化系数
@输出:
分解之后的P, Q
P:初始化用户特征矩阵M*K
Q:初始化物品特征矩阵N*K
"""
#给定参数
K=2
max_iter=5000 #迭代次数
alpha=0.0002 #步长
lamda=0.004 #正则化系数
#核心算法
def LFM_grad_desc(R,K=2,max_iter=1000,alpha=0.001,lamda=0.002):
#基本维度参数定义
M=len(R)
N=len(R[0])
# P,Q初始值,随机生成==随机梯度下降
P=np.random.rand(M,K)
Q=np.random.rand(N,K)
Q=Q.T #转置
#开始迭代
for step in range(max_iter):
#对所以的用户u,物品i做遍历,对应的特征向量Pu,Qi梯度下降
for u in range(M):
for i in range(N):
#对于每一个大于0的评分,求出预测评分误差
if R[u][i]>0:
eui=np.dot(P[u,:],Q[:,i])-R[u][i] #P里的第u行与Q里的第i列数据两个向量相乘
#代入公式,按照梯度下降算法更新当前的Pu,Qi
for k in range(K):
P[u][k]=P[u][k]-alpha*(2 * eui * Q[k][i] +2*lamda*P[u][k])
Q[k][i]=Q[k][i]-alpha*(2 * eui * P[u][k] +2*lamda*Q[k][i])
# u、i遍历完成,所有特征向量更新完成,可以得到P,Q,可以计算预算评分矩阵
predR=np.dot(P,Q)
# 计算当前损失函数
cost=0
for u in range(M):
for i in range(N):
if R[u][i]>0:
cost+=(np.dot(P[u,:],Q[:,i])-R[u][i]) **2
#加上正则化项
for k in range(K):
cost+=lamda*(P[u][k] ** 2 + Q[k][i] ** 2)
if cost<0.0001:
break
return P,Q.T,cost
# 3 测试
P,Q,cost=LFM_grad_desc(R,K,max_iter,alpha,lamda)
print(P)
print(Q)
print(cost)
predR=P.dot((Q.T))
print(R)
print(predR)
运行结果: