目录

前言

一、例子

二、步骤

1.构造Loss函数

2.求偏导

3.矩阵乘法

4.梯度下降

5.正则化

6.代码如下




前言

矩阵分解可以用来求预测值等等,十分重要,所以接下来我将整理矩阵分解的过程及涉及的相关知识。

一、例子

 有如下R(5,4)的打分矩阵:(“-”表示用户没有打分)

其中打分矩阵R(n,m)是n行和m列,n表示user个数,m行表示item个数

怎么用成分得分矩阵计算权重_后端

那么,如何根据目前的矩阵R(5,4)如何对未打分的商品进行评分的预测(如何得到分值为0的用户的打分值)? 

二、步骤

1.构造Loss函数

损失函数为经典的构造函数,很重要。

损失函数:使用原始的评分矩阵

怎么用成分得分矩阵计算权重_开发语言_02

与重新构建的评分矩阵

怎么用成分得分矩阵计算权重_损失函数_03

之间的误差的平方作为损失函数,即:

      如果R(i,j)已知,则R(i,j)的误差平方和为:

怎么用成分得分矩阵计算权重_开发语言_04

  最终,需要求解所有的非“-”项的损失之和的最小值:

怎么用成分得分矩阵计算权重_python_05

2.求偏导

3.矩阵乘法

A矩阵和B矩阵可以做乘法运算必须满足A矩阵的列的数量等于B矩阵的行的数量

运算规则:A的每一行中的数字对应乘以B的每一列的数字把结果相加起来

怎么用成分得分矩阵计算权重_怎么用成分得分矩阵计算权重_06

   

怎么用成分得分矩阵计算权重_损失函数_07

矩阵乘法的结果为行与列的关系为:行数量为A的行数量, 列数量为B的列数量

2. 因为每一次都是A的行与B的列,所以最外层的两层循环可以使用A的行的数量的变化,B的列的数量进行变化

因此,对于这个例子:

矩阵R可以近似表示为P与Q的乘积:R(n,m)≈ P(n,K)*Q(K,m)

矩阵分解的过程中,将原始的评分矩阵

怎么用成分得分矩阵计算权重_开发语言_08

分解成两个矩阵

怎么用成分得分矩阵计算权重_开发语言_09

怎么用成分得分矩阵计算权重_损失函数_10

的乘积: 

怎么用成分得分矩阵计算权重_怎么用成分得分矩阵计算权重_11

4.梯度下降

通过梯度下降法来一步步的迭代求解,得到最小化的损失函数。

梯度下降相关概念:

1.步长:步长决定了在梯度下降迭代过程中,每一步沿梯度负方向前进的长度。

2.特征:指的是样本中输入部分,比如2个单特征的样本(x0,y0),(x1,y1),则第一个样本特征为x0,第一个样本输出为y0.

3.假设函数:为了拟合输入文本,而使用假设函数

4.损失函数:用于度量拟合的程度

此例子梯度下降:

使用梯度下降法获得修正的p和q分量:

  •   求解损失函数的负梯度:

     

怎么用成分得分矩阵计算权重_怎么用成分得分矩阵计算权重_12

  •        根据负梯度的方向更新变量:

     

怎么用成分得分矩阵计算权重_python_13

 不停迭代直到算法最终收敛(直到sum(e^2) <=阈值)

5.正则化

调节模型允许存储的信息量,或对模型允许存储的信息加以约束。如果一个网络只能记住几个模式,那么优化过程会迫使模型集中学习最重要的模式,这样更可能得到良好的泛化。

正则化可按策略分为三类

经验正则化:通过工程上的技巧来实现更低的泛化误差方法,比如:提前终止法、模型集成、Dropout等;
参数正则化:直接提供正则化约束,比如:L1/L2正则化法等;
隐式正则化:不直接提供约束,比如:数据有关的操作,包括归一化、数据增强、扰乱标签等。

该例子加入正则化项的损失函数求解:

1.  首先令

怎么用成分得分矩阵计算权重_后端_14

 2.  通常在求解的过程中,为了能够有较好的泛化能力,会在损失函数中加入正则项,以对参数进行约束,加入

怎么用成分得分矩阵计算权重_损失函数_15

正则的损失函数为:

   

怎么用成分得分矩阵计算权重_损失函数_16

也即:

       

怎么用成分得分矩阵计算权重_python_17

 3.  使用梯度下降法获得修正的p和q分量:

  •   求解损失函数的负梯度:

        

怎么用成分得分矩阵计算权重_后端_18

  •   根据负梯度的方向更新变量:

      

怎么用成分得分矩阵计算权重_怎么用成分得分矩阵计算权重_19

 不停迭代直到算法最终收敛(直到sum(e^2) <=阈值)

【预测】利用上述的过程,我们可以得到矩阵

怎么用成分得分矩阵计算权重_后端_20

怎么用成分得分矩阵计算权重_损失函数_21

,这样便可以为用户 i 对商品  j 进行打分:

                 

怎么用成分得分矩阵计算权重_怎么用成分得分矩阵计算权重_22

6.代码如下

# !/usr/bin/env python
# encoding: utf-8
__author__ = 'Scarlett'
#矩阵分解在打分预估系统中得到了成熟的发展和应用
# from pylab import *
import matplotlib.pyplot as plt
from math import pow
import numpy


def matrix_factorization(R,P,Q,K,steps=5000,alpha=0.0002,beta=0.02):
    Q=Q.T  # .T操作表示矩阵的转置
    result=[]
    for step in range(steps):
        for i in range(len(R)):
            for j in range(len(R[i])):
                if R[i][j]>0:
                    eij=R[i][j]-numpy.dot(P[i,:],Q[:,j]) # .dot(P,Q) 表示矩阵内积
                    for k in range(K):
                        P[i][k]=P[i][k]+alpha*(2*eij*Q[k][j]-beta*P[i][k])
                        Q[k][j]=Q[k][j]+alpha*(2*eij*P[i][k]-beta*Q[k][j])
        eR=numpy.dot(P,Q)
        e=0
        for i in range(len(R)):
            for j in range(len(R[i])):
                if R[i][j]>0:
                    e=e+pow(R[i][j]-numpy.dot(P[i,:],Q[:,j]),2)
                    for k in range(K):
                        e=e+(beta/2)*(pow(P[i][k],2)+pow(Q[k][j],2))
        result.append(e)
        if e<0.001:
            break
    return P,Q.T,result

if __name__ == '__main__':
    R=[
        [5,3,0,1],
        [4,0,0,1],
        [1,1,0,5],
        [1,0,0,4],
        [0,1,5,4]
    ]

    R=numpy.array(R)

    N=len(R)
    M=len(R[0])
    K=2

    P=numpy.random.rand(N,K) #随机生成一个 N行 K列的矩阵
    Q=numpy.random.rand(M,K) #随机生成一个 M行 K列的矩阵

    nP,nQ,result=matrix_factorization(R,P,Q,K)
    print("原始的评分矩阵R为:\n",R)
    R_MF=numpy.dot(nP,nQ.T)
    print("经过MF算法填充0处评分值后的评分矩阵R_MF为:\n",R_MF)

#-------------损失函数的收敛曲线图---------------

    n=len(result)
    x=range(n)
    plt.plot(x,result,color='r',linewidth=3)
    plt.title("Convergence curve")
    plt.xlabel("generation")
    plt.ylabel("loss")
    plt.show()

运行结果:

怎么用成分得分矩阵计算权重_后端_23

怎么用成分得分矩阵计算权重_损失函数_24