View Javadoc

1   /**
2    * Copyright (c) 2011, The University of Southampton and the individual contributors.
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without modification,
6    * are permitted provided that the following conditions are met:
7    *
8    *   * 	Redistributions of source code must retain the above copyright notice,
9    * 	this list of conditions and the following disclaimer.
10   *
11   *   *	Redistributions in binary form must reproduce the above copyright notice,
12   * 	this list of conditions and the following disclaimer in the documentation
13   * 	and/or other materials provided with the distribution.
14   *
15   *   *	Neither the name of the University of Southampton nor the names of its
16   * 	contributors may be used to endorse or promote products derived from this
17   * 	software without specific prior written permission.
18   *
19   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
23   * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26   * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29   */
30  package org.openimaj.workinprogress;
31  
32  import java.util.Random;
33  
34  import Jama.Matrix;
35  
36  public class GD_SVD {
37  	private static final int maxEpochs = 300;
38  	private static final double initialLearningRate = 0.01;
39  	private static final double annealingRate = maxEpochs * 0.1;
40  
41  	Matrix UprimeM;
42  	Matrix VprimeM;
43  	private Matrix UM;
44  	private Matrix VM;
45  	private Matrix SM;
46  
47  	public GD_SVD(Matrix MM, int maxOrder) {
48  		final Random random = new Random(0);
49  		final double initValue = 1 / Math.sqrt(maxOrder);
50  
51  		final int m = MM.getRowDimension();
52  		final int n = MM.getColumnDimension();
53  
54  		UprimeM = new Matrix(m, maxOrder);
55  		VprimeM = new Matrix(n, maxOrder);
56  		final double[][] Uprime = UprimeM.getArray();
57  		final double[][] Vprime = VprimeM.getArray();
58  		final double[][] M = MM.getArray();
59  
60  		for (int k = 0; k < maxOrder; k++) {
61  			for (int i = 0; i < m; i++)
62  				Uprime[i][k] = random.nextGaussian() * initValue;
63  			for (int j = 0; j < n; j++)
64  				Vprime[j][k] = random.nextGaussian() * initValue;
65  
66  			double lastError = Double.MAX_VALUE;
67  			for (int epoch = 0; epoch < maxEpochs; epoch++) {
68  				final double learningRate = initialLearningRate / (1 + epoch / annealingRate);
69  
70  				double sq = 0;
71  				for (int i = 0; i < m; i++) {
72  					for (int j = 0; j < n; j++) {
73  						double pred = 0;
74  						for (int kk = 0; kk <= k; kk++)
75  							pred += Uprime[i][kk] * Vprime[j][kk];
76  
77  						final double error = M[i][j] - pred;
78  						System.out.println("Error: " + error + " " + M[i][j]);
79  						sq += error * error;
80  						final double uTemp = Uprime[i][k];
81  						final double vTemp = Vprime[j][k];
82  						// Uprime[i][k] += learningRate[epoch] * ( error * vTemp
83  						// - regularization * uTemp );
84  						// Vprime[j][k] += learningRate[epoch] * ( error * uTemp
85  						// - regularization * vTemp );
86  						Uprime[i][k] += learningRate * (error * vTemp);
87  						Vprime[j][k] += learningRate * (error * uTemp);
88  
89  						// System.out.println(i + " " + learningRate * (error *
90  						// vTemp));
91  					}
92  				}
93  
94  				if (lastError - sq < 0.000001)
95  					break;
96  
97  				lastError = sq;
98  			}
99  		}
100 
101 		UM = new Matrix(m, maxOrder);
102 		final double[][] U = UM.getArray();
103 		SM = new Matrix(maxOrder, maxOrder);
104 		final double[][] S = SM.getArray();
105 		VM = new Matrix(maxOrder, n);
106 		final double[][] V = VM.getArray();
107 		for (int i = 0; i < maxOrder; i++) {
108 			double un = 0;
109 			double vn = 0;
110 			for (int j = 0; j < m; j++) {
111 				un += (Uprime[j][i] * Uprime[j][i]);
112 			}
113 			for (int j = 0; j < n; j++) {
114 				vn += (Vprime[j][i] * Vprime[j][i]);
115 			}
116 
117 			un = Math.sqrt(un);
118 			vn = Math.sqrt(vn);
119 
120 			for (int j = 0; j < m; j++) {
121 				U[j][i] = Uprime[j][i] / un;
122 			}
123 			for (int j = 0; j < n; j++) {
124 				V[i][j] = Vprime[j][i] / vn;
125 			}
126 
127 			S[i][i] = un * vn;
128 		}
129 	}
130 
131 	public static void main(String[] args) {
132 		// final Matrix m = Matrix.random(10, 10);
133 		final Matrix m = new Matrix(new double[][] { { 0.5, 0.4 }, { 0.1, 0.7 } });
134 
135 		final GD_SVD gdsvd = new GD_SVD(m, 2);
136 
137 		// m.print(5, 5);
138 		// gdsvd.UprimeM.print(5, 5);
139 		// gdsvd.UprimeM.times(gdsvd.VprimeM.transpose()).print(5, 5);
140 		// gdsvd.UM.times(gdsvd.SM.times(gdsvd.VM)).print(5, 5);
141 		// gdsvd.UM.print(5, 5);
142 		gdsvd.SM.print(5, 5);
143 		// gdsvd.VM.print(5, 5);
144 
145 		// final ThinSingularValueDecomposition tsvd = new
146 		// ThinSingularValueDecomposition(m, 2);
147 		// tsvd.U.print(5, 5);
148 		// System.out.println(Arrays.toString(tsvd.S));
149 
150 	}
151 }