double n = 0; for (RatingMatrixEntry r : ratings) { sum += r.getValue(); n += 1; double sse = 0; for (RatingMatrixEntry r : ratings) { final int uidx = r.getUserIndex(); final int iidx = r.getItemIndex(); final double p = mean + uoff[uidx] + ioff[iidx]; final double err = r.getValue() - p; uoff[uidx] += learningRate * (err - regularizationFactor * Math.abs(uoff[uidx])); ioff[iidx] += learningRate * (err - regularizationFactor * Math.abs(ioff[iidx]));
/** * Update the current estimates with trained values for a new feature. * @param ufvs The user feature values. * @param ifvs The item feature values. */ public void update(RealVector ufvs, RealVector ifvs) { for (RatingMatrixEntry r : ratings) { int idx = r.getIndex(); double est = estimates[idx]; est += ufvs.getEntry(r.getUserIndex()) * ifvs.getEntry(r.getItemIndex()); if (domain != null) { est = domain.clampValue(est); } estimates[idx] = est; } } }
/** * Initialize the training estimator. * @param snap The getEntry snapshot. * @param baseline The baseline predictor. * @param dom The getEntry domain (for clamping). */ TrainingEstimator(RatingMatrix snap, BiasModel baseline, PreferenceDomain dom) { ratings = snap.getRatings(); domain = dom; estimates = new double[ratings.size()]; final LongCollection userIds = snap.getUserIds(); LongIterator userIter = userIds.iterator(); double global = baseline.getIntercept(); for (RatingMatrixEntry r: snap.getRatings()) { double userBias = baseline.getUserBias(r.getUserId()); double itemBias = baseline.getItemBias(r.getItemId()); estimates[r.getIndex()] = global + userBias + itemBias; } }
@Test public void testAddPreference() { int idx = bld.add(10, 39, 3.5); assertThat(idx, equalTo(0)); assertThat(bld.size(), equalTo(1)); PackedRatingData data = bld.build(); assertThat(data.size(), equalTo(1)); RatingMatrixEntry p2 = data.getEntry(0); assertThat(p2.getIndex(), equalTo(0)); assertThat(p2.getUserIndex(), equalTo(0)); assertThat(p2.getItemIndex(), equalTo(0)); assertThat(p2.getUserId(), equalTo(10L)); assertThat(p2.getItemId(), equalTo(39L)); assertThat(p2.getValue(), equalTo(3.5)); }
@Override public synchronized Long2DoubleMap getUserRatingVector(long userId) { // FIXME Don't make this so locky if (cache == null) { cache = new Long2ObjectOpenHashMap<>(); } Long2DoubleMap data = cache.get(userId); if (data != null) { return data; } else { Collection<RatingMatrixEntry> prefs = this.getUserRatings(userId); Long2DoubleMap map = new Long2DoubleOpenHashMap(); for (RatingMatrixEntry e: prefs) { map.put(e.getItemId(), e.getValue()); } data = new Long2DoubleSortedArrayMap(map); cache.put(userId, data); return data; } }
@Override @Nonnull public List<Collection<RatingMatrixEntry>> get() { int nusers = data.getUserIndex().size(); ArrayList<IntArrayList> userLists = new ArrayList<>(nusers); for (int i = 0; i < nusers; i++) { userLists.add(new IntArrayList()); } for (RatingMatrixEntry pref : getRatings()) { final int uidx = pref.getUserIndex(); final int idx = pref.getIndex(); userLists.get(uidx).add(idx); } ArrayList<Collection<RatingMatrixEntry>> users = new ArrayList<>(nusers); for (IntArrayList list: userLists) { list.trim(); users.add(new PackedRatingCollection(data, list)); } return users; } }
/** * Get the estimate for a getEntry. * @param pref The getEntry. * @return The estimate. */ public double get(RatingMatrixEntry pref) { return estimates[pref.getIndex()]; }
@Test public void testGetRatings() throws Exception { RandomDataSplitStrategyProvider splitData = new RandomDataSplitStrategyProvider(snapshot, new Random(), 0, 0.2); DataSplitStrategy splitStrategy = splitData.get(); KeyIndex userIndex = splitStrategy.getUserIndex(); KeyIndex itemIndex = splitStrategy.getItemIndex(); List<RatingMatrixEntry> validations = splitStrategy.getValidationRatings(); List<RatingMatrixEntry> trainingRatings = splitStrategy.getTrainRatings(); for (RatingMatrixEntry re : trainingRatings) { int user = re.getUserIndex(); int item = re.getItemIndex(); long userId = userIndex.getKey(user); long itemId = itemIndex.getKey(item); double rating = re.getValue(); assertThat(rating, equalTo(snapshot.getUserRatingVector(userId).get(itemId))); assertThat(rating, equalTo(data.get(itemId).get(userId))); } for (RatingMatrixEntry re : validations) { long userId = re.getUserId(); long itemId = re.getItemId(); double rating = re.getValue(); assertThat(rating, equalTo(snapshot.getUserRatingVector(userId).get(itemId))); assertThat(rating, equalTo(data.get(itemId).get(userId))); } }
/** * Initialize the training estimator. * @param snap The getEntry snapshot. * @param baseline The baseline predictor. * @param dom The getEntry domain (for clamping). */ TrainingEstimator(RatingMatrix snap, BiasModel baseline, PreferenceDomain dom) { ratings = snap.getRatings(); domain = dom; estimates = new double[ratings.size()]; final LongCollection userIds = snap.getUserIds(); LongIterator userIter = userIds.iterator(); double global = baseline.getIntercept(); for (RatingMatrixEntry r: snap.getRatings()) { double userBias = baseline.getUserBias(r.getUserId()); double itemBias = baseline.getItemBias(r.getItemId()); estimates[r.getIndex()] = global + userBias + itemBias; } }
/** * Update the current estimates with trained values for a new feature. * @param ufvs The user feature values. * @param ifvs The item feature values. */ public void update(RealVector ufvs, RealVector ifvs) { for (RatingMatrixEntry r : ratings) { int idx = r.getIndex(); double est = estimates[idx]; est += ufvs.getEntry(r.getUserIndex()) * ifvs.getEntry(r.getItemIndex()); if (domain != null) { est = domain.clampValue(est); } estimates[idx] = est; } } }
@Override public synchronized Long2DoubleMap getUserRatingVector(long userId) { // FIXME Don't make this so locky if (cache == null) { cache = new Long2ObjectOpenHashMap<>(); } Long2DoubleMap data = cache.get(userId); if (data != null) { return data; } else { Collection<RatingMatrixEntry> prefs = this.getUserRatings(userId); Long2DoubleMap map = new Long2DoubleOpenHashMap(); for (RatingMatrixEntry e: prefs) { map.put(e.getItemId(), e.getValue()); } data = new Long2DoubleSortedArrayMap(map); cache.put(userId, data); return data; } }
@Override @Nonnull public List<Collection<RatingMatrixEntry>> get() { int nusers = data.getUserIndex().size(); ArrayList<IntArrayList> userLists = new ArrayList<>(nusers); for (int i = 0; i < nusers; i++) { userLists.add(new IntArrayList()); } for (RatingMatrixEntry pref : getRatings()) { final int uidx = pref.getUserIndex(); final int idx = pref.getIndex(); userLists.get(uidx).add(idx); } ArrayList<Collection<RatingMatrixEntry>> users = new ArrayList<>(nusers); for (IntArrayList list: userLists) { list.trim(); users.add(new PackedRatingCollection(data, list)); } return users; } }
/** * Get the estimate for a getEntry. * @param pref The getEntry. * @return The estimate. */ public double get(RatingMatrixEntry pref) { return estimates[pref.getIndex()]; }
int user = re.getUserIndex(); int item = re.getItemIndex(); long userId = re.getUserId(); long itemId = re.getItemId(); assertThat(user, equalTo(userIndex.tryGetIndex(userId))); assertThat(item, equalTo(itemIndex.tryGetIndex(itemId))); KeyIndex snapshotItemIndex = snapshot.itemIndex(); for (RatingMatrixEntry re : trainingRatings) { int user = re.getUserIndex(); int item = re.getItemIndex(); long userId = userIndex.getKey(user); long itemId = itemIndex.getKey(item);
final int uidx = r.getUserIndex(); final int iidx = r.getItemIndex(); updater.prepare(0, r.getValue(), estimates.get(r), userFeatureVector.getEntry(uidx), itemFeatureVector.getEntry(iidx), trail);
@Test public void testGetRatings() { List<RatingMatrixEntry> ratings = snap.getRatings(); assertEquals(20, ratings.size()); for (int i = 0; i < 20; i++) { RatingMatrixEntry entry = ratings.get(i); assertThat(entry.getIndex(), equalTo(i)); assertThat(ratingList, Matchers.<List<Rating>>anyOf(hasItem(rating(entry.getUserId(), entry.getItemId(), entry.getValue(), 1)), hasItem(rating(entry.getUserId(), entry.getItemId(), entry.getValue(), 2)))); } }
final int item = ratings.get(0).getItemIndex(); final double itemWeightShpPrior = hyperParameters.getItemWeightShpPrior(); final double itemActivityShpPrior = hyperParameters.getItemActivityShpPrior(); while (itemRatings.hasNext()) { RatingMatrixEntry entry = itemRatings.next(); int user = entry.getUserIndex(); double rating = entry.getValue(); if (rating <= 0) { continue;
final int user = ratings.get(0).getUserIndex(); final double userWeightShpPrior = hyperParameters.getUserWeightShpPrior(); final double userActivityShpPrior = hyperParameters.getUserActivityShpPrior(); while (userRatings.hasNext()) { RatingMatrixEntry entry = userRatings.next(); int item = entry.getItemIndex(); double rating = entry.getValue(); if (rating <= 0) { continue;