SVD++分解

  在现实情况下,用户的显式反馈严重不足,但一般拥有大量隐式反馈信息。所以在偏置svd基础上增加了用户的隐式反馈信息,该方法融合了用户的显式和隐式信息。

1.预测评分公式为

   

  其中,有全局平均分,user的偏置信息,item的偏置信息,Ni为该用户评价过的所有item集合,从隐式反馈出发,作为用户偏好的补充,ys为隐式偏好。

2.损失函数为平方误差+L2正则项,其中是真实评分。

  

3.利用SGD训练更新,其中

4.程序,(数据movielens 100k,https://github.com/jiangnanboy/recommendation_methods/blob/master/com/sy/reco/recommendation/matrix_factorization/svdpp.py)

import numpy as np
import math

‘‘‘
融合了BiasLFM以及用户的隐式行为
‘‘‘
class SVDPP():
    ‘‘‘
    初始化ratingMatrix,F, alpha, λ
    ratingMatrix:评分矩阵
    F:隐因子数目
    alpha:学习速率
    λ:正则化参数,以防过拟合
    ‘‘‘
    def __init__(self, ratingMatrix, F, alpha, λ):
        self.ratingMatrix = ratingMatrix
        self.F = F
        self.alpha = alpha
        self.λ = λ

    # 对U,I,Y矩阵初始化,随机填充,根据经验随机数与1/sqrt(F)成正比,bu向量与bi向量初始化为全0,u是所有有评分的全局平均
    def __initPQ(self, userSum, itemSum):
        self.U = np.zeros((userSum, self.F))
        self.I = np.zeros((itemSum, self.F))
        self.Y=np.zeros((itemSum,self.F))
        self.bu = np.zeros(userSum)
        self.bi = np.zeros(itemSum)
        self.meanV = np.mean(self.ratingMatrix[self.ratingMatrix > 0])  # 全局均值
        for i in range(userSum):
            self.U[i] = [np.random.random() / math.sqrt(self.F) for x in range(self.F)]
        for i in range(itemSum):
            self.I[i] = [np.random.random() / math.sqrt(self.F) for x in range(self.F)]
            self.Y[i]=[np.random.random()/math.sqrt(self.F) for x in range(self.F)]

    # 迭代训练分解,max_iter:迭代次数
    def iteration_train(self, max_iter):
        userSum = len(self.ratingMatrix)  # 用户个数
        itemSum = len(self.ratingMatrix[0])  # 项目个数
        self.__initPQ(userSum, itemSum)  # 初始化U,I,Y,bu,bi
        Z=np.zeros((userSum,self.F))
        for step in range(max_iter):
            for user in range(userSum):
                Z[user]=self.U[user]
                ru=1/math.sqrt(len(self.U[user][self.U[user,:]>0]))#1/sqrt(Usum>0)用户评过分的项目个数
                for item in range(itemSum):
                    if self.ratingMatrix[user, item] > 0:  # 未评分的项目不参与计算
                        for f in range(self.F):
                            Z[user,f]+=self.Y[item,f]*ru #I更新中的部分(1/sqrt(Usum))*self.Y
                sum=np.zeros(self.F)
                for item in range(itemSum):
                    if self.ratingMatrix[user,item]>0:# 未评分的项目不参与计算
                        eui = self.ratingMatrix[user, item] - self.predict(user, item,ru)  # 真实值减去预测的值
                        self.bu[user] += self.alpha * (eui - self.λ * self.bu[user])  # 更新bu
                        self.bi[item] += self.alpha * (eui - self.λ * self.bi[item])  # 更新bi
                        for f in range(self.F):
                            sum[f]+=self.I[item,f]*eui*ru #Y更新中的部分eui*ru*I
                            self.U[user, f] += self.alpha * (self.I[item, f] * eui - self.λ * self.U[user, f])  # 更新U
                            self.I[item,f]+=self.alpha*(eui*(self.U[user,f]+Z[user,f])-self.λ*self.I[item,f])#更新I
                #更新Y
                for item in range(itemSum):
                    for f in range(self.F):
                        self.Y[item,f]+=self.alpha*(sum[f]-self.λ*self.Y[item,f])
            #self.alpha*=0.9

        predictRating = []#存放全部预测数据
        for user in range(userSum):
            userItemRating = []
            ru = 1 / math.sqrt(len(self.U[user][self.U[user, :] > 0]))  # 1/sqrt(Usum>0)用户评过分的项目个数
            for item in range(itemSum):
                pui = self.predict(user, item,ru)
                userItemRating.append(pui)
            predictRating.append(userItemRating)
        return np.round(np.array(predictRating), 0)

    #预测打分,用户的行与项目的列
    def predict(self,user,item,ru):
        z=np.zeros(self.F)
        for i in range(len(self.ratingMatrix[user])):
            if self.ratingMatrix[user,i]>0:
                for f in range(self.F):
                    z[f]+=self.Y[i,f]
        pui =0.
        for f in range(self.F):
            pui+=(self.U[user,f]+z[f]/ru)*self.I[item,f]
        pui+=self.meanV+self.bu[user]+self.bi[item]
        return pui

    # 预测误差训练,convergence:误差收敛,小于这个误差,则终止训练
    def convergence_train(self, convergence):
        userSum = len(self.ratingMatrix)  # 用户个数
        itemSum = len(self.ratingMatrix[0])  # 项目个数
        self.__initPQ(userSum, itemSum)  # 初始化U,I,Y,bu,bi
        Z = np.zeros((userSum, self.F))
        flag=True
        while flag:
            for user in range(userSum):
                Z[user] = self.U[user]
                ru = 1 / math.sqrt(len(self.U[user][self.U[user, :] > 0]))  # 1/sqrt(Usum>0)用户评过分的项目个数
                for item in range(itemSum):
                    if self.ratingMatrix[user, item] > 0:  # 未评分的项目不参与计算
                        for f in range(self.F):
                            Z[user, f] += self.Y[item, f] * ru  # I更新中的部分(1/sqrt(Usum))*self.Y
                sum = np.zeros(self.F)
                for item in range(itemSum):
                    if self.ratingMatrix[user, item] > 0:  # 未评分的项目不参与计算
                        eui = self.ratingMatrix[user, item] - self.predict(user, item, ru)  # 真实值减去预测的值
                        self.bu[user] += self.alpha * (eui - self.λ * self.bu[user])  # 更新bu
                        self.bi[item] += self.alpha * (eui - self.λ * self.bi[item])  # 更新bi
                        for f in range(self.F):
                            sum[f] += self.I[item, f] * eui * ru  # Y更新中的部分eui*ru*I
                            self.U[user, f] += self.alpha * (self.I[item, f] * eui - self.λ * self.U[user, f])  # 更新U
                            self.I[item, f] += self.alpha * (
                            eui * (self.U[user, f] + Z[user, f]) - self.λ * self.I[item, f])  # 更新I
                # 更新Y
                for item in range(itemSum):
                    for f in range(self.F):
                        self.Y[item, f] += self.alpha * (sum[f] - self.λ * self.Y[item, f])

            cost = 0  # 误差
            for user in range(userSum):
                ru = 1 / math.sqrt(len(self.U[user][self.U[user, :] > 0]))  # 1/sqrt(Usum>0)用户评过分的项目个数
                for item in range(itemSum):
                    if self.ratingMatrix[user, item] > 0:
                        cost += (1 / 2) * math.pow(self.ratingMatrix[user, item] - self.predict(user, item,ru), 2)
                        cost += (1 / 2) * self.λ * (math.pow(self.bu[user], 2) + math.pow(self.bi[item], 2))
                        for f in range(self.F):
                            cost += (1 / 2) * self.λ * (math.pow(self.U[user, f], 2) + math.pow(self.I[item, f], 2)+math.pow(self.Y[item,f],2))
            if cost < convergence:
                flag = False

        predictRating = []  # 存放全部预测数据
        for user in range(userSum):
            userItemRating = []
            ru = 1 / math.sqrt(len(self.U[user][self.U[user, :] > 0]))  # 1/sqrt(Usum>0)用户评过分的项目个数
            for item in range(itemSum):
                pui = self.predict(user, item, ru)
                userItemRating.append(pui)
            predictRating.append(userItemRating)
        return np.round(np.array(predictRating), 0)

原文地址:https://www.cnblogs.com/little-horse/p/12499671.html

时间: 2024-10-11 15:57:21

SVD++分解的相关文章

机器学习中的矩阵方法04:SVD 分解

机器学习中的矩阵方法04:SVD 分解 前面我们讲了 QR 分解有一些优良的特性,但是 QR 分解仅仅是对矩阵的行进行操作(左乘一个酉矩阵),可以得到列空间.这一小节的 SVD 分解则是将行与列同等看待,既左乘酉矩阵,又右乘酉矩阵,可以得出更有意思的信息.奇异值分解( SVD, Singular Value Decomposition ) 在计算矩阵的伪逆( pseudoinverse ),最小二乘法最优解,矩阵近似,确定矩阵的列向量空间,秩以及线性系统的解集空间都有应用. 1. SVD 的形式

矩阵的SVD分解

转自 http://blog.csdn.net/zhongkejingwang/article/details/43053513(实在受不了CSDN的广告) 在网上看到有很多文章介绍SVD的,讲的也都不错,但是感觉还是有需要补充的,特别是关于矩阵和映射之间的对应关系.前段时间看了国外的一篇文章,叫A Singularly Valuable Decomposition The SVD of a Matrix,觉得分析的特别好,把矩阵和空间关系对应了起来.本文就参考了该文并结合矩阵的相关知识把SVD

机器学习Python实现 SVD 分解

这篇文章主要是结合机器学习实战将推荐算法和SVD进行相应的结合 任何一个矩阵都可以分解为SVD的形式 其实SVD意义就是利用特征空间的转换进行数据的映射,后面将专门介绍SVD的基础概念,先给出python,这里先给出一个简单的矩阵,表示用户和物品之间的关系 这里我自己有个疑惑? 对这样一个DATA = U(Z)Vt 这里的U和V真正的几何含义  :  书上的含义是U将物品映射到了新的特征空间, V的转置  将 用户映射到了新的特征空间 下面是代码实现,同时SVD还可以用于降维,降维的操作就是通过

SVD分解的理解

对称阵A 相应的,其对应的映射也分解为三个映射.现在假设有x向量,用A将其变换到A的列空间中,那么首先由U'先对x做变换: 由于正交阵" U的逆=U' ",对于两个空间来讲,新空间下的" 基E' 坐标 x' ,原空间E 坐标x "有如下关系 EX=E'X' ===> X=E'X' ===> X'=(E'的逆)x ==> x向量在新的"基"下的新坐标  (E的转置)X: 1.那么对于上式UTx先可以理解为:将x用A的所有特征向量表

SVD分解 求解超定方程组

做平差的时候,需要解误差方程组,而 有的书本上说解线性的误差方程组,并不需要初值. 在查阅了测量平差书本之后,书里描述,一般是需要参数的初始值的. 这就产生了疑问. 因为非线性方程的线性化之后,舍掉了二次项之后的值,会造成平差模型的弱化.因此在进行非线性方程的平差过程中,一般是对改正值进行一个迭代计算,使其精化. 而线性化之后的各参数的系数中,包含了其他的未知参数,因此在计算的过程之中,必须使用初值. 原本就是线性方程组的平差模型,也可以直接使用SVD分解来解误差方程组. 1.解最小二乘超定方程

Mathmatica SVD分解

mathmathica初识. Mathmatica 进行SVD分解,利用Help帮助获取SVD分解的函数SingularValueDecomposition[] 导入数据:G= Import["D:\\mathmatica\17.txt","Table"],此时以二维数组格式将数据储存之G数组中. 进行SVD分解: [U,S,Vt] = SingularValueDecomposition[G]; 以矩阵格式输出数组: MatirxForm[U]; MatrixFo

SVD分解

正奇异值:设$A=A_{m \times n}, rank(A)=p>0$,则$\lambda ({A^H}A)$与$\lambda (A{A^H})$恰有p个正特征根,${\lambda _1} > 0,{\lambda _2} > 0,...,{\lambda _p} > 0$ $\lambda ({A^H}A) = \{ {\lambda _1},{\lambda _2},...,{\lambda _p},0,...,0\} $  n-p个0 $\lambda (A{A^H}

(转)机器学习之SVD分解

一.SVD奇异值分解的定义 假设是一个的矩阵,如果存在一个分解: 其中为的酉矩阵,为的半正定对角矩阵,为的共轭转置矩阵,且为的酉矩阵.这样的分解称为的奇异值分解,对角线上的元素称为奇异值,称为左奇异矩阵,称为右奇异矩阵. 二.SVD奇异值分解与特征值分解的关系 特征值分解与SVD奇异值分解的目的都是提取一个矩阵最重要的特征.然而,特征值分解只适用于方阵,而SVD奇异值分解适用于任意的矩阵,不一定是方阵. 这里,和是方阵,和为单位矩阵,为的特征向量,为的特征向量.和的特征值为的奇异值的平方. 三.

Python中怎样实现奇异值SVD分解

1 >>> from numpy import *; 2 >>> U,Sigma,VT=linalg.svd([[1,1],[]7,7]) 3 SyntaxError: invalid syntax 4 >>> U,Sigma,VT=linalg.svd([[1,1],[7,7]]) 5 >>> U 6 array([[-0.14142136, -0.98994949], 7 [-0.98994949, 0.14142136]]) 8