@Nullable private Long2DoubleMap getUserRatingVector(long user) { Long2DoubleMap ratings = rvDAO.userRatingVector(user); return ratings.isEmpty() ? null : ratings; }
@Override public Iterable<Neighbor> getCandidateNeighbors(final long user, LongSet items) { Long2DoubleMap ratings = rvDAO.userRatingVector(user); if (ratings.isEmpty()) { return Collections.emptyList(); } final Long2DoubleMap nratings = similarityNormalizer.makeTransformation(user, ratings) .apply(ratings); final LongSet candidates = findCandidateNeighbors(user, nratings.keySet(), items); logger.debug("found {} candidate neighbors for {}", candidates.size(), user); return new Iterable<Neighbor>() { @Override public Iterator<Neighbor> iterator() { return new NeighborIterator(user, nratings, candidates); } }; }
/** * Score all items into an accumulator. * @param user The user. * @param items The items to score. * @param accum The accumulator. */ private void scoreItems(long user, @Nonnull Collection<Long> items, ItemItemScoreAccumulator accum) { Long2DoubleMap ratings = Long2DoubleSortedArrayMap.create(rvDAO.userRatingVector(user)); logger.trace("user has {} ratings", ratings.size()); InvertibleFunction<Long2DoubleMap, Long2DoubleMap> transform = normalizer.makeTransformation(user, ratings); Long2DoubleMap itemScores = transform.apply(ratings); LongIterator iter = LongIterators.asLongIterator(items.iterator()); while (iter.hasNext()) { final long item = iter.nextLong(); scoreItem(itemScores, item, accum); } accum.applyReversedTransform(transform); }
@Nonnull @Override public ResultMap scoreWithDetails(long user, @Nonnull Collection<Long> items) { Long2DoubleMap ratings = dao.userRatingVector(user);
@Nonnull @Override public ResultMap scoreWithDetails(long user, @Nonnull Collection<Long> items) { Long2DoubleMap ratings = dao.userRatingVector(user);
@Nonnull @Override public ResultMap scoreWithDetails(long user, @Nonnull Collection<Long> items) { Long2DoubleMap history = dao.userRatingVector(user);
@Override public double getUserBias(long user) { Long2DoubleMap vec = dao.userRatingVector(user); if (vec.isEmpty()) { return 0; } else { double sum = 0; double mean = getIntercept(); for (Long2DoubleMap.Entry e: vec.long2DoubleEntrySet()) { sum += e.getDoubleValue() - mean - getItemBias(e.getLongKey()); } return sum / vec.size(); } }
@Test public void testNoUser() { EntityCollectionDAO dao = EntityCollectionDAO.create(); RatingVectorPDAO source = new EntityCountRatingVectorPDAO(dao, LIKE); assertThat(source.userRatingVector(42).entrySet(), hasSize(0)); }
@Test public void testNoUser() { EntityCollectionDAO dao = EntityCollectionDAO.create(); RatingVectorPDAO source = new StandardRatingVectorPDAO(dao); assertThat(source.userRatingVector(42).entrySet(), hasSize(0)); }
@Test public void testNoUser() { EntityCollectionDAO dao = EntityCollectionDAO.create(); RatingVectorPDAO source = new CountSumRatingVectorPDAO(dao, LIKE); assertThat(source.userRatingVector(42).entrySet(), hasSize(0)); }
@Nonnull @Override public ResultMap scoreWithDetails(long user, @Nonnull Collection<Long> items) { Long2DoubleMap userRatings = rvDAO.userRatingVector(user); if (userRatings.isEmpty()) { Map<Long, Double> scores = baseline.score(user, items); return Results.newResultMap(Iterables.transform(scores.entrySet(), Results.fromEntryFunction())); } else { // score everything, both rated and not, for offsets LongSet allItems = new LongOpenHashSet(userRatings.keySet()); allItems.addAll(items); Map<Long, Double> baseScores = baseline.score(user, allItems); Long2DoubleMap offsets = new Long2DoubleOpenHashMap(); // subtract scores from ratings, yielding offsets Long2DoubleFunction bsf = LongUtils.asLong2DoubleMap(baseScores); for (Long2DoubleMap.Entry e: userRatings.long2DoubleEntrySet()) { double base = bsf.get(e.getLongKey()); offsets.put(e.getLongKey(), e.getDoubleValue() - base); } double meanOffset = Vectors.sum(offsets) / (offsets.size() + damping); // to score: fill with baselines, add user mean offset List<Result> results = new ArrayList<>(items.size()); LongIterator iter = LongIterators.asLongIterator(items.iterator()); while (iter.hasNext()) { long item = iter.nextLong(); results.add(Results.create(item, bsf.get(item) + meanOffset)); } return Results.newResultMap(results); } }
@Override public Iterable<Neighbor> getCandidateNeighbors(final long user, LongSet items) { Long2DoubleMap urs = rvDAO.userRatingVector(user); if (urs.isEmpty()) { return Collections.emptyList(); } final Long2DoubleMap normed = similarityNormalizer.makeTransformation(user, urs) .apply(urs); assert normed != null; LongCollection qset = items; if (normed.size() < qset.size()) { qset = normed.keySet(); } final LongSet candidates = new LongOpenHashSet(); for (LongIterator iter = qset.iterator(); iter.hasNext();) { final long item = iter.nextLong(); LongSet users = snapshot.getItemUsers(item); if (users != null) { candidates.addAll(users); } } candidates.remove(user); logger.debug("Found {} candidate neighbors for user {}", candidates.size(), user); return new Iterable<Neighbor>() { @Override public Iterator<Neighbor> iterator() { return new NeighborIterator(user, normed, candidates); } }; }
@Test public void testGetRating() { EntityCollectionDAO dao = EntityCollectionDAO.create(factory.rating(42, 39, 2.5)); RatingVectorPDAO source = new StandardRatingVectorPDAO(dao); assertThat(source.userRatingVector(42), hasEntry(39L, 2.5)); }
@Test public void testGetsOnlyRating() { EntityCollectionDAO dao = EntityCollectionDAO.create(factory.rating(42, 39, 2.5), factory.rating(42, 20, 3.5), factory.rating(17, 39, 1.5)); RatingVectorPDAO source = new StandardRatingVectorPDAO(dao); Long2DoubleMap vec = source.userRatingVector(42); assertThat(vec.entrySet(), hasSize(2)); assertThat(vec, hasEntry(39L, 2.5)); assertThat(vec, hasEntry(20L, 3.5)); } }
@Nullable private Long2DoubleMap getUserRatingVector(long user) { Long2DoubleMap ratings = rvDAO.userRatingVector(user); return ratings.isEmpty() ? null : ratings; }
@Test public void testGetLike() { EntityCollectionDAO dao = EntityCollectionDAO.create(Entities.newBuilder(LIKE) .setId(1) .setAttribute(CommonAttributes.USER_ID, 42L) .setAttribute(CommonAttributes.ITEM_ID, 39L) .build()); RatingVectorPDAO source = new EntityCountRatingVectorPDAO(dao, LIKE); assertThat(source.userRatingVector(42), hasEntry(39L, 1.0)); }
@Test public void testGetLike() { EntityCollectionDAO dao = EntityCollectionDAO.create(Entities.newBuilder(LIKE) .setId(1) .setAttribute(CommonAttributes.USER_ID, 42L) .setAttribute(CommonAttributes.ITEM_ID, 39L) .setAttribute(CommonAttributes.COUNT, 5) .build()); RatingVectorPDAO source = new CountSumRatingVectorPDAO(dao, LIKE); assertThat(source.userRatingVector(42), hasEntry(39L, 5.0)); }
RatingVectorPDAO source = new EntityCountRatingVectorPDAO(dao, LIKE); Long2DoubleMap vec = source.userRatingVector(42); assertThat(vec.entrySet(), hasSize(2)); assertThat(vec, hasEntry(39L, 2.0));
RatingVectorPDAO source = new CountSumRatingVectorPDAO(dao, LIKE); Long2DoubleMap vec = source.userRatingVector(42); assertThat(vec.entrySet(), hasSize(2)); assertThat(vec, hasEntry(39L, 6.0));
@Override public double getUserBias(long user) { Long2DoubleMap vec = dao.userRatingVector(user); if (vec.isEmpty()) { return 0; } else { double sum = 0; double mean = getIntercept(); for (Long2DoubleMap.Entry e: vec.long2DoubleEntrySet()) { sum += e.getDoubleValue() - mean - getItemBias(e.getLongKey()); } return sum / vec.size(); } }