`
zangwenyang
  • 浏览: 126829 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

NMF(非负矩阵分解)的SGD(随机梯度下降)实现

 
阅读更多

NMF把一个矩阵分解为两个矩阵的乘积,可以用来解决很多问题,例如:用户聚类、item聚类、预测(补全)用户对item的评分、个性化推荐等问题。NMF的过程可以转化为最小化损失函数(即误差函数)的过程,其实整个问题也就是一个最优化的问题。详细实现过程如下:(其中,输入矩阵很多时候会比较稀疏,即很多元素都是缺失项,故数据存储采用的是libsvm的格式,这个类在此忽略)

 

 

[java] view plaincopy
 
  1. package NMF_danji;  
  2.   
  3. import java.io.File;  
  4. import java.util.ArrayList;  
  5.   
  6. /** 
  7.  * @author 玉心sober: http://weibo.com/karensober 
  8.  * @date 2013-05-19 
  9.  *  
  10.  * */  
  11. public class NMF {  
  12.     private Dataset dataset = null;  
  13.     private int M = -1// 行数  
  14.     private int V = -1// 列数  
  15.     private int K = -1// 隐含主题数  
  16.     double[][] P;  
  17.     double[][] Q;  
  18.   
  19.     public NMF(String datafileName, int topics) {  
  20.         File datafile = new File(datafileName);  
  21.         if (datafile.exists()) {  
  22.             if ((this.dataset = new Dataset(datafile)) == null) {  
  23.                 System.out.println(datafileName + " is null");  
  24.             }  
  25.             this.M = this.dataset.size();  
  26.             this.V = this.dataset.getFeatureNum();  
  27.             this.K = topics;  
  28.         } else {  
  29.             System.out.println(datafileName + " doesn't exist");  
  30.         }  
  31.     }  
  32.   
  33.     public void initPQ() {  
  34.         P = new double[this.M][this.K];  
  35.         Q = new double[this.K][this.V];  
  36.   
  37.         for (int k = 0; k < K; k++) {  
  38.             for (int i = 0; i < M; i++) {  
  39.                 P[i][k] = Math.random();  
  40.             }  
  41.             for (int j = 0; j < V; j++) {  
  42.                 Q[k][j] = Math.random();  
  43.             }  
  44.         }  
  45.     }  
  46.   
  47.     // 随机梯度下降,更新参数  
  48.     public void updatePQ(double alpha, double beta) {  
  49.         for (int i = 0; i < M; i++) {  
  50.             ArrayList<Feature> Ri = this.dataset.getDataAt(i).getAllFeature();  
  51.             for (Feature Rij : Ri) {  
  52.                 // eij=Rij.weight-PQ for updating P and Q  
  53.                 double PQ = 0;  
  54.                 for (int k = 0; k < K; k++) {  
  55.                     PQ += P[i][k] * Q[k][Rij.dim];  
  56.                 }  
  57.                 double eij = Rij.weight - PQ;  
  58.   
  59.                 // update Pik and Qkj  
  60.                 for (int k = 0; k < K; k++) {  
  61.                     double oldPik = P[i][k];  
  62.                     P[i][k] += alpha  
  63.                             * (2 * eij * Q[k][Rij.dim] - beta * P[i][k]);  
  64.                     Q[k][Rij.dim] += alpha  
  65.                             * (2 * eij * oldPik - beta * Q[k][Rij.dim]);  
  66.                 }  
  67.             }  
  68.         }  
  69.     }  
  70.   
  71.     // 每步迭代后计算SSE  
  72.     public double getSSE(double beta) {  
  73.         double sse = 0;  
  74.         for (int i = 0; i < M; i++) {  
  75.             ArrayList<Feature> Ri = this.dataset.getDataAt(i).getAllFeature();  
  76.             for (Feature Rij : Ri) {  
  77.                 double PQ = 0;  
  78.                 for (int k = 0; k < K; k++) {  
  79.                     PQ += P[i][k] * Q[k][Rij.dim];  
  80.                 }  
  81.                 sse += Math.pow((Rij.weight - PQ), 2);  
  82.             }  
  83.         }  
  84.   
  85.         for (int i = 0; i < M; i++) {  
  86.             for (int k = 0; k < K; k++) {  
  87.                 sse += ((beta / 2) * (Math.pow(P[i][k], 2)));  
  88.             }  
  89.         }  
  90.   
  91.         for (int i = 0; i < V; i++) {  
  92.             for (int k = 0; k < K; k++) {  
  93.                 sse += ((beta / 2) * (Math.pow(Q[k][i], 2)));  
  94.             }  
  95.         }  
  96.   
  97.         return sse;  
  98.     }  
  99.   
  100.     // 采用随机梯度下降方法迭代求解参数,即求解最终分解后的矩阵  
  101.     public boolean doNMF(int iters, double alpha, double beta) {  
  102.         for (int step = 0; step < iters; step++) {  
  103.             updatePQ(alpha, beta);  
  104.             double sse = getSSE(beta);  
  105.             if (step % 100 == 0)  
  106.                 System.out.println("step " + step + " SSE = " + sse);  
  107.         }  
  108.         return true;  
  109.     }  
  110.   
  111.     public void printMatrix() {  
  112.         System.out.println("===========原始矩阵==============");  
  113.         for (int i = 0; i < this.dataset.size(); i++) {  
  114.             for (Feature feature : this.dataset.getDataAt(i).getAllFeature()) {  
  115.                 System.out.print(feature.dim + ":" + feature.weight + " ");  
  116.             }  
  117.             System.out.println();  
  118.         }  
  119.     }  
  120.   
  121.     public void printFacMatrxi() {  
  122.         System.out.println("===========分解矩阵==============");  
  123.         for (int i = 0; i < P.length; i++) {  
  124.             for (int j = 0; j < Q[0].length; j++) {  
  125.                 double cell = 0;  
  126.                 for (int k = 0; k < K; k++) {  
  127.                     cell += P[i][k] * Q[k][j];  
  128.                 }  
  129.                 System.out.print(baoliu(cell, 3) + " ");  
  130.             }  
  131.             System.out.println();  
  132.         }  
  133.     }  
  134.   
  135.     // 为double类型变量保留有效数字  
  136.     public static double baoliu(double d, int n) {  
  137.         double p = Math.pow(10, n);  
  138.         return Math.round(d * p) / p;  
  139.     }  
  140.   
  141.     public static void main(String[] args) {  
  142.         double alpha = 0.002;  
  143.         double beta = 0.02;  
  144.   
  145.         NMF nmf = new NMF("D:\\myEclipse\\graphModel\\data\\nmfinput.txt"10);  
  146.         nmf.initPQ();  
  147.         nmf.doNMF(3000, alpha, beta);  
  148.   
  149.         // 输出原始矩阵  
  150.         nmf.printMatrix();  
  151.   
  152.         // 输出分解后矩阵  
  153.         nmf.printFacMatrxi();  
  154.     }  
  155. }  

结果:
...

 

step 2900 SSE = 0.5878774074369989
===========原始矩阵==============
0:9.0 1:2.0 2:1.0 3:1.0 4:1.0 
0:8.0 1:3.0 2:2.0 3:1.0 
0:3.0 3:1.0 4:2.0 5:8.0 
1:1.0 3:2.0 4:4.0 5:7.0 
0:2.0 1:1.0 2:1.0 4:1.0 5:3.0 
===========分解矩阵==============
8.959 2.007 1.007 0.996 1.007 6.293 
7.981 2.972 1.989 1.005 2.046 7.076 
3.01 1.601 1.773 1.003 2.005 7.968 
4.821 1.009 2.209 1.984 3.968 6.988 
2.0 0.991 0.984 0.51 1.0 2.994 

分享到:
评论

相关推荐

    NMF 非负矩阵分解

    这是著名的科学杂志《Nature》于1999年刊登了两位科学家D.D.Lee和H.S.Seung对数学中非负矩阵研究的突出成果的论文。该文提出了一种新的矩阵分解思想――非负矩阵分解(Non-negative Matrix Factorization,NMF)算法。

    GNMF_GNMF_非负矩阵分解_梯度下降_

    在NMF中,梯度下降法被用来更新两个非负矩阵的元素,即分解后的W和H矩阵,目标是使原始矩阵V与WH的差异最小化。通常,NMF的损失函数选择 Frobenius 范数或者Kullback-Leibler散度。在每次迭代中,梯度下降会沿着损失...

    nmf非负矩阵分解算法高维遥感图像维度压缩

    nmf非负矩阵分解算法高维遥感图像维度压缩,主要进行nmf非负矩阵分解算法的数据降维。可任意降维。使用Python写成。

    NMF 非负矩阵分解 图像重构

    非负矩阵分解(NMF,Non-negative Matrix Factorization)是一种数据挖掘和机器学习技术,它将非负的大矩阵分解为两个非负的小矩阵的乘积。在这个场景中,NMF被应用于图像处理,特别是图像重构,这是一个在计算机...

    NMF 非负矩阵分解 相关资料 程序 PPT

    NMF 非负矩阵分解 相关资料 程序 PPT A new nonnegative matrix factorization for independent component analysis Blind Image Separation Using Nonnegative Matrix Factorization with Gibbs Smoothing ...

    非负矩阵分解matlab代码(全)

    非负矩阵分解(Non-negative Matrix Factorization, NMF)是一种广泛应用的数据分析方法,它通过将一个非负的矩阵分解为两个非负矩阵的乘积,从而揭示数据的潜在结构和特征。在MATLAB中实现NMF,可以帮助研究人员和...

    非负矩阵分解算法的代码

    子空间分析法是一种有效的特征抽取方法,而本文所研究讨论的非负矩阵分解(Non-negative Matrix Factorization, NMF)具有一些独特的优点,成为构建特征子空间的一种有效的方法。 非负矩阵分解是一种新的矩阵分解方法...

    稀疏非负矩阵分解及模式识别

    非负矩阵分解(Non-negative Matrix Factorization, NMF)是将一个非负的输入矩阵W分解为两个非负矩阵H和V的乘积,即W ≈ VH。这种分解方法能够捕获数据中的潜在结构和特征,尤其是在处理高维非负数据时,如图像像素...

    matlab程序非负矩阵分解NMF

    非负矩阵分解(NMF,Nonnegtive Matrix Factorization),NMF,非负矩阵分解,将大矩阵分解成两个小矩阵,且这两个小矩阵都不包含负值。 代码来自Chih-Jen Lin

    非负矩阵分解_nmf_工具箱_matlab

    资源名:非负矩阵分解_nmf_工具箱_matlab 资源类型:matlab项目全套源码 源码说明: 全部项目源码都是经过测试校正后百分百成功运行的,如果您下载后不能运行可联系我进行指导或者更换。 适合人群:新手及有一定经验...

    一种受限非负矩阵分解方法

    传统的NMF方法将一个非负矩阵分解为两个非负因子矩阵的乘积形式,能够有效提取数据中的潜在结构。然而,由于传统NMF缺乏额外的约束条件,所得到的潜在结构可能不够理想。为此,本文介绍了一种改进的方法——受限非负...

    非负矩阵分解及其应用探讨

    非负矩阵分解(Non-negative Matrix Factorization, NMF)是一种矩阵分解方法,其核心在于将一个非负矩阵分解为两个较小的非负矩阵的乘积。这一分解过程在数据挖掘、图像处理、文本分析等多个领域具有广泛的应用前景。...

    NMF非负矩阵的分解

    将一个非负矩阵分解得到两个非负的矩阵,可以实现数据的降维

    nmf非负矩阵分解资源包

    非负矩阵分解(Non-negative Matrix Factorization,简称NMF)是一种在数据挖掘、机器学习和信号处理领域广泛应用的数学技术。它通过将一个非负的矩阵分解为两个非负矩阵的乘积,从而揭示数据的内在结构和潜在特征。...

    dynamic-nmf, 非负矩阵分解的动态话题建模.zip

    dynamic-nmf, 非负矩阵分解的动态话题建模 基于动态主题模型的动态非摘要标准主题建模方法假设文档顺序不重要,使它们不适合时间戳语料库。 相反,动态主题建模方法跟踪语言的变化和主题随着时间的推移而变化。 通过...

    用于社区检测的类深度自动编码器非负矩阵分解——中南大学彭汪祺--论文研读笔记11

    【用于社区检测的类深度自动编码器非负矩阵分解】这篇论文主要探讨的是如何利用深度学习的方法改进非负矩阵分解(NMF)技术,以更好地应用于社区检测。社区检测是网络分析的重要部分,旨在识别网络中具有紧密内部...

    NMF程序_编程实现NMF_nmf_matlab_非负矩阵分解_NMF程序_

    非负矩阵分解的学习案例,用matlab编程实现

Global site tag (gtag.js) - Google Analytics