for (int iteration = 0; iteration < numIterations; iteration++) {
log.info("iteration {}", iteration);
/* fix M - compute U */
ExecutorService queue = createQueue();
LongPrimitiveIterator userIDsIterator = dataModel.getUserIDs();
try {
final ImplicitFeedbackAlternatingLeastSquaresSolver implicitFeedbackSolver = usesImplicitFeedback
? new ImplicitFeedbackAlternatingLeastSquaresSolver(numFeatures, lambda, alpha, itemY) : null;
while (userIDsIterator.hasNext()) {
final long userID = userIDsIterator.nextLong();
final LongPrimitiveIterator itemIDsFromUser = dataModel.getItemIDsFromUser(userID).iterator();
final PreferenceArray userPrefs = dataModel.getPreferencesFromUser(userID);
queue.execute(new Runnable() {
@Override
public void run() {
List<Vector> featureVectors = Lists.newArrayList();
while (itemIDsFromUser.hasNext()) {
long itemID = itemIDsFromUser.nextLong();
featureVectors.add(features.getItemFeatureColumn(itemIndex(itemID)));
}
Vector userFeatures = usesImplicitFeedback
? implicitFeedbackSolver.solve(sparseUserRatingVector(userPrefs))
: AlternatingLeastSquaresSolver.solve(featureVectors, ratingVector(userPrefs), lambda, numFeatures);
features.setFeatureColumnInU(userIndex(userID), userFeatures);
}
});
}
} finally {
queue.shutdown();
try {
queue.awaitTermination(dataModel.getNumUsers(), TimeUnit.SECONDS);
} catch (InterruptedException e) {
log.warn("Error when computing user features", e);
}
}
/* fix U - compute M */
queue = createQueue();
LongPrimitiveIterator itemIDsIterator = dataModel.getItemIDs();
try {
final ImplicitFeedbackAlternatingLeastSquaresSolver implicitFeedbackSolver = usesImplicitFeedback
? new ImplicitFeedbackAlternatingLeastSquaresSolver(numFeatures, lambda, alpha, userY) : null;
while (itemIDsIterator.hasNext()) {
final long itemID = itemIDsIterator.nextLong();
final PreferenceArray itemPrefs = dataModel.getPreferencesForItem(itemID);
queue.execute(new Runnable() {
@Override
public void run() {
List<Vector> featureVectors = Lists.newArrayList();