奇异值分解为矩阵分解的一种方法。
奇异值分解(SVD)
将目标矩阵A,转化为三个矩阵相乘,如下:
其中,A为目标矩阵,表示user对item的打分;P为左奇异矩阵,mm维,为User矩阵;Q为右奇异矩阵,nn维,为item矩阵;Λ为对角矩阵,对角线上的非零元素为特征值λ1, λ2, … , λk。
thinking:Λ矩阵需要由矩阵A求得,这就需要矩阵A是一个非稀疏矩阵,而现实中,就是因为矩阵A的未知元素太多,我们才做预测并推荐,所以SVD在推荐系统中反而不太使用,但可运用到图片压缩(降维)。
SVD图片压缩(降维)思路:
step1,将图片转化为二维数组(灰度化);
step2,对二维数组进行SVD,得到p,s,q;
step3,留用Λ矩阵中k个最大特征值,其他设为0;
step4,p*s‘*q得到新二维数组。
代码如下:
SVD奇异值分解——对图片处理降维
FunkSVD算法
避开稀疏矩阵问题,只用两个矩阵相乘:
M = PQ
损失函数为P和Q矩阵乘积得到的评分与实际的差异。
最小化损失函数:
为防止过拟合,增加正则项:
推荐的思路:
step1:通过梯度下降法,求解P和Q是损失函数最小化;
step2:P和Q相乘,得到预测的评分表;
step3:针对某个用户1,查找之前缺失值位置,按补全值从大到小排序。
BiasSVD算法
BiasSVD算法对比FunkSVD加入了Bias(偏好),优化目标函数:
μ:所有记录的整体平均数;bi:用户偏好;bj:商品偏好。需要同时优化四个参数,bi,bi,pi,qj,使用SGD(随机梯度下降法),得到P和Q.
SVD++算法
SVD++算法在BiasSVD算法基础上进行了改进,加入了隐式因素,如浏览时长、点击情况等
在考虑用户隐式反馈的情况下,最终得到P和Q。
surprise工具SVD算法家族的实战
surprise官网:Surprise’ documentation
代码链接:FunkSVD、BiasSVD、SVD++
from surprise import SVD,SVDpp
from surprise import Dataset
from surprise import Reader
from surprise import accuracy
from surprise.model_selection import KFold
import pandas as pd
from surprise.model_selection import cross_validate
#数据读取
reader = Reader(line_format='user item rating timestamp',sep = ',',skip_lines=1)
data = Dataset.load_from_file('ratings.csv',reader = reader)
train_set = data.build_full_trainset()
#funkSVD
algo_f = SVD(biased = False)
#BiasSVD
algo_b = SVD(biased = True)
#SVD++
algo_p = SVDpp()
#定义k折交叉验证迭代器,K=3
def eval_model(model):
kf = KFold(n_splits=3)
for trainset,testset in kf.split(data):
#训练并预测
model.fit(trainset)
predictions = model.test(testset)
#计算RMSE
accuracy.rmse(predictions,verbose=True)
#查看评估结果
print('FunkSVD的RMSE为:')
eval_model(algo_f)
print('BiasSVD的RMSE为:')
eval_model(algo_b)
print('SVD++的RMSE为:')
eval_model(algo_p)
#get_neighbors做电影推荐
uid = str(200)
iid = str(200)
# 输出uid对iid的预测结果
pred = algo_f.predict(uid, iid, r_ui=None, verbose=True)