1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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
83
84
85
86 Uprime[i][k] += learningRate * (error * vTemp);
87 Vprime[j][k] += learningRate * (error * uTemp);
88
89
90
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
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
138
139
140
141
142 gdsvd.SM.print(5, 5);
143
144
145
146
147
148
149
150 }
151 }