基于矩阵分解的推荐算法(java代码实现)

目前推荐系统中用的最多的就是矩阵分解方法,在Netflix Prize推荐系统大赛中取得突出效果。以用户-项目评分矩阵为例,矩阵分解就是预测出评分矩阵中的缺失值,然后根据预测值以某种方式向用户推荐。常见的矩阵分解方法有基本矩阵分解(basic MF),正则化矩阵分解)(Regularized MF),基于概率的矩阵分解(PMF)等。今天以“用户-项目评分矩阵R(N×M)”说明三种分解方式的原理以及应用。
基于矩阵分解的推荐算法(java代码实现)_第1张图片
用户-项目评分矩阵
Basic MF:
Basic MF是最基础的分解方式,将评分矩阵R分解为用户矩阵U和项目矩阵S, 通过不断的迭代训练使得U和S的乘积越来越接近真实矩阵,矩阵分解过程如图:
矩阵分解过程
基于矩阵分解的推荐算法(java代码实现)_第2张图片
预测值接近真实值就是使其差最小,这是我们的目标函数,然后采用梯度下降的方式迭代计算U和S,它们收敛时就是分解出来的矩阵。我们用损失函数来表示误差(等价于目标函数):
损失函数 公式1
基于矩阵分解的推荐算法(java代码实现)_第3张图片
公式1中R_ij是评分矩阵中已打分的值,U_i和S_j相当于未知变量。为求得公式1的最小值,相当于求关于U和S二元函数的最小值(极小值或许更贴切)。通常采用梯度下降的方法:
梯度下降
这里写图片描述
学习速率是学习速率,表示迭代的步长。其值为1.5时,通常以震荡形式接近极值点;若<1迭代单调趋向极值点;若>2围绕极值逐渐发散,不会收敛到极值点。具体取什么值要根据实验经验。

Regularized MF

正则化矩阵分解是Basic MF的优化,解决MF造成的过拟合问题。其不是直接最小化损失函数,而是在损失函数基础上增加规范化因子,将整体作为损失函数。
基于矩阵分解的推荐算法(java代码实现)_第4张图片

红线表示正则化因子,在求解U和S时,仍然采用梯度下降法,此时迭代公式变为:(图片截取自相关论文,S和V等价)
梯度下降
基于矩阵分解的推荐算法(java代码实现)_第5张图片
梯度下降结束条件:f(x)的真实值和预测值小于自己设定的阈值(很小的值,之前一直理解为是变量U和V的迭代值差小于阈值就行)

Java代码实现矩阵分解

public class Test {
     private static int N=5;//用户的数目
     private static int M=4;//产品的数目
     private static int K=2;//特征的数目
     private static DecimalFormat df=new DecimalFormat("###.000");
     public static void main(String[] args) {
         double[] R=new double[N*M];
         double[] P=new double[N*K];
         double[] Q=new double[N*M];
         R[0]=5;
         R[1]=3;
         R[2]=0;
         R[3]=1;
         R[4]=4;
         R[5]=0;
         R[6]=0;
         R[7]=1;
         R[8]=1;
         R[9]=1; 
         R[10]=0;
         R[11]=5;
         R[12]=1;
         R[13]=0;
         R[14]=0;
         R[15]=4;
         R[16]=0;
         R[17]=1;
         R[18]=5;
         R[19]=4;
         System.out.println("R矩阵");
         for(int i=0;ifor(int j=0;jout.print(R[i*M+j]+",");
          }
          System.out.println();
         } 
        //初始化P,Q矩阵,这里简化了,通常也可以对服从正态分布的数据进行随机数生成 
         for(int i=0;ifor(int j=0;j9;
             }
         }
         for(int i=0;ifor(int j=0;j9;
             }
         }           
         System.out.println("矩阵分解开始");
         matrix_factorization(R,P,Q,N,M,K);  
         System.out.println("重构出来的R矩阵");
         for(int i=0;ifor(int j=0;jdouble temp=0; 
           for (int k=0;kout.print(df.format(temp)+","); 
          } 
          System.out.println();
         }
     }
     public static void matrix_factorization(double[] R,double[] P,double[] Q,int N,int M,int K){
        int steps=5000;
        double alpha=0.0002;
        double beta=0.02;
        for(int step =0;stepfor(int i=0;ifor(int j=0;jif(R[i*M+j]>0){
                        double eij = R[i*M+j];
                        for(int k=0;kfor(int k=0;k2 * eij * Q[k*M+j] - beta * P[i*K+k]);
                            Q[k*M+j] +=alpha * (2 * eij * P[i*K+k] - beta *  Q[k*M+j]);
                        } 
                        } 
                    }
                }
            double loss=0;
            for(int i=0;ifor(int j=0;jif(R[i*M+j]>0){
                         double eij =0;
                            for(int k=0;k2); 
                             for(int k=0;k2) * (Math.pow(P[i*K+k],2) + Math.pow(Q[k*M+j],2)); 
                             }  
                     }
                 }
            } 
            if(loss<0.001){
                break;
            } 
            if (step%1000==0){
                System.out.println("loss:"+loss);
            }
        }
    }
}

你可能感兴趣的:(数据挖掘)