/** Why buildingModel2 that follows the paper instructions does not work? */ protected void buildModel2() { for (int iter = 1; iter <= numIters; iter++) { // Step 1: update W by fixing H DenseMatrix trH = H.transpose(); // V * trH DenseMatrix V_trH = DenseMatrix.mult(V, trH); // W * H * trH DenseMatrix W_H_trH = W.mult(H.mult(trH)); // update: W_ij = W_ij * (V_trH)_ij / (W_H_trH)_ij for (int i = 0; i < W.numRows(); i++) for (int j = 0; j < W.numColumns(); j++) { double denorm = W_H_trH.get(i, j) + 1e-9; W.set(i, j, W.get(i, j) * (V_trH.get(i, j) / denorm)); } // Step 2: update H by fixing W DenseMatrix trW = W.transpose(); // trW * V DenseMatrix trW_V = trW.mult(V); // trW * W * H DenseMatrix trW_W_H = trW.mult(W).mult(H); // update: H_ij = H_ij * (trW_V)_ij / (trW_W_H)_ij for (int i = 0; i < H.numRows(); i++) for (int j = 0; j < H.numColumns(); j++) { double denorm = trW_W_H.get(i, j) + 1e-9; H.set(i, j, H.get(i, j) * (trW_V.get(i, j) / denorm)); } // compute errors loss = 0; errs = 0; for (MatrixEntry me : V) { int u = me.row(); int j = me.column(); double ruj = me.get(); if (ruj > 0) { double pred = predict(u, j); double euj = pred - ruj; errs += euj * euj; loss += euj * euj; } } errs *= 0.5; loss *= 0.5; if (isConverged(iter)) break; } }
/** * Randomly sample a matrix from Wishart Distribution with the given parameters. * * @param scale scale parameter for Wishart Distribution. * @param df degree of freedom for Wishart Distribution. * @return the sample randomly drawn from the given distribution. */ protected DenseMatrix wishart(DenseMatrix scale, double df) { DenseMatrix A = scale.cholesky(); if (A == null) return null; int p = scale.numRows(); DenseMatrix z = new DenseMatrix(p, p); for (int i = 0; i < p; i++) { for (int j = 0; j < p; j++) { z.set(i, j, Randoms.gaussian(0, 1)); } } SparseVector y = new SparseVector(p); for (int i = 0; i < p; i++) y.set(i, Randoms.gamma((df - (i + 1)) / 2, 2)); DenseMatrix B = new DenseMatrix(p, p); B.set(0, 0, y.get(0)); if (p > 1) { // rest of diagonal: for (int j = 1; j < p; j++) { SparseVector zz = new SparseVector(j); for (int k = 0; k < j; k++) zz.set(k, z.get(k, j)); B.set(j, j, y.get(j) + zz.inner(zz)); } // first row and column: for (int j = 1; j < p; j++) { B.set(0, j, z.get(0, j) * Math.sqrt(y.get(0))); B.set(j, 0, B.get(0, j)); // mirror } } if (p > 2) { for (int j = 2; j < p; j++) { for (int i = 1; i <= j - 1; i++) { SparseVector zki = new SparseVector(i); SparseVector zkj = new SparseVector(i); for (int k = 0; k <= i - 1; k++) { zki.set(k, z.get(k, i)); zkj.set(k, z.get(k, j)); } B.set(i, j, z.get(i, j) * Math.sqrt(y.get(i)) + zki.inner(zkj)); B.set(j, i, B.get(i, j)); // mirror } } } return A.transpose().mult(B).mult(A); }
@Override protected void buildModel() throws Exception { for (int iter = 1; iter <= numIters; iter++) { // update W by fixing H for (int u = 0; u < W.numRows(); u++) { SparseVector uv = V.row(u); if (uv.getCount() > 0) { SparseVector euv = new SparseVector(V.numColumns()); for (int j : uv.getIndex()) euv.set(j, predict(u, j)); for (int f = 0; f < W.numColumns(); f++) { DenseVector fv = H.row(f, false); double real = fv.inner(uv); double estm = fv.inner(euv) + 1e-9; W.set(u, f, W.get(u, f) * (real / estm)); } } } // update H by fixing W DenseMatrix trW = W.transpose(); for (int j = 0; j < H.numColumns(); j++) { SparseVector jv = V.column(j); if (jv.getCount() > 0) { SparseVector ejv = new SparseVector(V.numRows()); for (int u : jv.getIndex()) ejv.set(u, predict(u, j)); for (int f = 0; f < H.numRows(); f++) { DenseVector fv = trW.row(f, false); double real = fv.inner(jv); double estm = fv.inner(ejv) + 1e-9; H.set(f, j, H.get(f, j) * (real / estm)); } } } // compute errors loss = 0; errs = 0; for (MatrixEntry me : V) { int u = me.row(); int j = me.column(); double ruj = me.get(); if (ruj > 0) { double euj = predict(u, j) - ruj; errs += euj * euj; loss += euj * euj; } } errs *= 0.5; loss *= 0.5; if (isConverged(iter)) break; } }