@Override public void predict(long uid, @Nonnull MutableSparseVector predictions) { logger.debug("predicting {} items for {}", predictions.keyDomain().size(), uid); OrdRecModel params = new OrdRecModel(quantizer); SparseVector ratings = makeUserVector(uid, userEventDao); LongSet keySet = LongUtils.setUnion(ratings.keySet(), predictions.keyDomain()); MutableSparseVector scores = MutableSparseVector.create(keySet); itemScorer.score(uid, scores); params.train(ratings, scores); logger.debug("trained parameters for {}: {}", uid, params); Vector probabilities = Vector.createLength(params.getLevelCount()); Long2ObjectMap<IVector> distChannel = null; if (reportDistribution) { distChannel = predictions.addChannel(RATING_PROBABILITY_CHANNEL); } for (VectorEntry e : predictions.fast(VectorEntry.State.EITHER)) { long iid = e.getKey(); double score = scores.get(iid); params.getProbDistribution(score, probabilities); int mlIdx = probabilities.maxElementIndex(); predictions.set(e, quantizer.getIndexValue(mlIdx)); if (distChannel != null) { distChannel.put(e.getKey(), probabilities.immutable()); } } }
@Test public void testCreateFromArray() { INDArray[] as = new INDArray[2]; as[0] = Vector.of(1, 2); as[1] = Vector.of(3, 4); INDArray a = Arrayz.create((Object) as); assertTrue(a instanceof AMatrix); }
/** * Get the probability distribution according to score and thresholds * * @param score The score * @param vec The MutableVec to be filled in. */ public void getProbDistribution(double score, Vector vec) { double pre = getProbLE(score, 0); vec.set(0, pre); for (int i = 1; i < getLevelCount(); i++) { double pro = getProbLE(score, i); vec.set(i, pro - pre); pre = pro; } }
@Test public void testZeroPaddedReshape() { assertTrue(Vector0.INSTANCE.reshape(1, 1).asVector().isZero()); assertTrue(Matrix.create(1, 1).reshape(1, 2, 3).asVector().isZero()); assertEquals(Vector.of(2, 0, 0), Scalar.create(2).reshape(3)); assertEquals(Vector.of(1, 2), Vector.of(1, 2, 3, 4).reshape(2)); assertEquals(Scalar.create(2), Vector.of(2, 3, 4).reshape()); assertEquals(Vector0.INSTANCE, Array.newArray(2, 3, 4, 5).reshape(0)); }
@Override public void transform(Vector source, Vector dest) { int rc = rowCount(); int cc = rc; if (source.length() != cc) throw new IllegalArgumentException(ErrorMessages.wrongSourceLength(source)); if (dest.length() != rc) throw new IllegalArgumentException(ErrorMessages.wrongDestLength(dest)); double[] sdata = source.getArray(); double[] ddata = dest.getArray(); for (int row = 0; row < rc; row++) { ddata[row] = sdata[row] * unsafeGetDiagonalValue(row); } }
/** The train function of OrdRec. Get all parameters after learning process. */ @SuppressWarnings("ConstantConditions") private void train(SparseVector ratings, MutableSparseVector scores) { Vector dbeta = Vector.createLength(beta.length()); double dt1; // n is the number of iteration; for (int j = 0; j < iterationCount; j++) { for (VectorEntry rating : ratings.fast()) { long iid = rating.getKey(); double score = scores.get(iid); int r = quantizer.index(rating.getValue()); double probEqualR = getProbEQ(score, r); double probLessR = getProbLE(score, r); double probLessR_1 = getProbLE(score, r - 1); dt1 = learningRate / probEqualR * (probLessR * (1 - probLessR) * derivateOfBeta(r, 0, t1) - probLessR_1 * (1 - probLessR_1) * derivateOfBeta(r - 1, 0, t1) - regTerm * t1); double dbetaK; for (int k = 0; k < beta.length(); k++) { dbetaK = learningRate / probEqualR * (probLessR * (1 - probLessR) * derivateOfBeta(r, k + 1, beta.get(k)) - probLessR_1 * (1 - probLessR_1) * derivateOfBeta(r - 1, k + 1, beta.get(k)) - regTerm * beta.get(k)); dbeta.set(k, dbetaK); } t1 = t1 + dt1; beta.add(dbeta); } } }
/** * The constructor of OrdRecParameter. It use the quantized values of rating to initialize t1 * and beta. Each threshold is initialized as the mean of two contiguous rating values. Since * the index of quantizer is always an successive non-negative integer begin from 0, so t1 will * initialize as 0.5, and the interval between two thresholds will be 1. * * @param qtz The quantizer for ratings */ private OrdRecModel(Quantizer qtz) { qtzValues = qtz.getValues(); levelCount = qtzValues.length(); t1 = (qtzValues.get(0) + qtzValues.get(1)) / 2; beta = Vector.createLength(levelCount - 2); double tr = t1; for (int i = 1; i <= beta.length(); i++) { double trnext = (qtzValues.get(i) + qtzValues.get(i + 1)) * 0.5; beta.set(i - 1, Math.log(trnext - tr)); tr = trnext; } }
@Test public void testCholesky() { AMatrix m = Matrixx.create(Vector.of(4, 12, -16), Vector.of(12, 37, -43), Vector.of(-16, -43, 98)); Matrix L = Cholesky.decompose(m); assertEquals((Matrixx.create(Vector.of(2, 0, 0), Vector.of(6, 1, 0), Vector.of(-8, 5, 3))), L); }
@Test public void testParse() { assertEquals(Vector.of(4, 5), Arrayz.parse("[[1, 2], [4, 5], [7, 8]]").slice(1)); }
@Test public void testDoubleSlice() { assertEquals(new Double(2.0), Array.create(Vector.of(1, 2, 3)).getSlices().get(1)); assertEquals(new Double(2.0), SliceArray.create(Vector.of(1, 2, 3)).getSlices().get(1)); }