for (Pair<Long,FastByIDFloatMap> work : workUnit) {
// Row (column) in original R matrix containing total association value. For simplicity we will
// talk about users and rows only in the comments and variables. It's symmetric for columns / items.
// This is Ru:
FastByIDFloatMap ru = work.getSecond();
// Start computing Wu = (YT*Cu*Y + lambda*I) = (YT*Y + YT*(Cu-I)*Y + lambda*I),
// by first starting with a copy of YT * Y. Or, a variant on YT * Y, if LOSS_IGNORES_UNSPECIFIED is set
RealMatrix Wu =
LOSS_IGNORES_UNSPECIFIED ?
partialTransposeTimesSelf(Y, YTY.getRowDimension(), ru.keySetIterator()) :
YTY.copy();
double[][] WuData = MatrixUtils.accessMatrixDataDirectly(Wu);
double[] YTCupu = new double[features];
for (FastByIDFloatMap.MapEntry entry : ru.entrySet()) {
double xu = entry.getValue();
float[] vector = Y.get(entry.getKey());
if (vector == null) {
log.warn("No vector for {}. This should not happen. Continuing...", entry.getKey());
continue;
}
// Wu and YTCupu
if (RECONSTRUCT_R_MATRIX) {
for (int row = 0; row < features; row++) {
YTCupu[row] += xu * vector[row];
}
} else {
double cu = 1.0 + alpha * FastMath.abs(xu);
for (int row = 0; row < features; row++) {
float vectorAtRow = vector[row];
double rowValue = vectorAtRow * (cu - 1.0);
double[] WuDataRow = WuData[row];
for (int col = 0; col < features; col++) {
WuDataRow[col] += rowValue * vector[col];
//Wu.addToEntry(row, col, rowValue * vector[col]);
}
if (xu > 0.0) {
YTCupu[row] += vectorAtRow * cu;
}
}
}
}
double lambdaTimesCount = lambda * ru.size();
for (int x = 0; x < features; x++) {
WuData[x][x] += lambdaTimesCount;
//Wu.addToEntry(x, x, lambdaTimesCount);
}