}
@Override
public Factorization factorize() throws TasteException {
log.info("starting to compute the factorization...");
final AlternateLeastSquaresSolver solver = new AlternateLeastSquaresSolver();
final Features features = new Features(this);
for (int iteration = 0; iteration < numIterations; iteration++) {
log.info("iteration {}", iteration);
/* fix M - compute U */
ExecutorService queue = createQueue();
LongPrimitiveIterator userIDsIterator = dataModel.getUserIDs();
try {
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 = new ArrayList<Vector>();
while (itemIDsFromUser.hasNext()) {
long itemID = itemIDsFromUser.nextLong();
featureVectors.add(features.getItemFeatureColumn(itemIndex(itemID)));
}
Vector userFeatures = solver.solve(featureVectors, ratingVector(userPrefs), lambda, numFeatures);
features.setFeatureColumnInU(userIndex(userID), userFeatures);
}
});
}
} finally {
queue.shutdown();
try {
queue.awaitTermination(dataModel.getNumUsers(), TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new IllegalStateException("Error when computing user features", e);
}
}
/* fix U - compute M */
queue = createQueue();
LongPrimitiveIterator itemIDsIterator = dataModel.getItemIDs();
try {
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 = new ArrayList<Vector>();
for (Preference pref : itemPrefs) {
long userID = pref.getUserID();
featureVectors.add(features.getUserFeatureColumn(userIndex(userID)));
}
Vector itemFeatures = solver.solve(featureVectors, ratingVector(itemPrefs), lambda, numFeatures);
features.setFeatureColumnInM(itemIndex(itemID), itemFeatures);
}
});
}
} finally {