void setup(LongSet universe, Recommender rec, TestUser user) { allItems = LongUtils.packedSet(universe); testUser = user; recommender = rec; }
@Nonnull @Override public ResultMap scoreWithDetails(long user, @Nonnull Collection<Long> items) { if(cachedId == user && cachedScores != null) { LongSet cachedItems = LongUtils.asLongSet(cachedScores.keySet()); if (!cachedItems.containsAll(LongUtils.asLongCollection(items))) { LongSet reqItems = LongUtils.packedSet(items); LongSortedSet diffItems = LongUtils.setDifference(reqItems, cachedItems); ResultMap newCache = scorer.scoreWithDetails(user, diffItems); cachedScores = Results.newResultMap(Iterables.concat(cachedScores, newCache)); } } else { cachedScores = scorer.scoreWithDetails(user, items); cachedId = user; } return cachedScores; }
@Override public Long2DoubleMap truncate(Long2DoubleMap v) { return LongUtils.frozenMap(v); } }
/** * Pick a random subset of a set of items. * @param items The set of items to pick from. * @param n the number of items to select. * @return A random subset of `items` of size at most `n`. */ public LongSet pickRandom(Set<Long> items, int n) { return LongUtils.randomSubset(LongUtils.asLongSet(items), n, random); }
@Override public ResultList recommendRelatedItemsWithDetails(Set<Long> basket, int n, @Nullable Set<Long> candidates, @Nullable Set<Long> exclude) { if (candidates == null) { candidates = dao.getEntityIds(CommonTypes.ITEM); } if (exclude == null) { exclude = getDefaultExcludes(LongUtils.asLongSet(basket)); } if (!exclude.isEmpty()) { candidates = LongUtils.setDifference(LongUtils.asLongSet(candidates), LongUtils.asLongSet(exclude)); } ResultMap scores = scorer.scoreRelatedItemsWithDetails(basket, candidates); return recommend(n, scores); }
/** * Compute the intersection of two sets. * * @param a The first set. * @param b The second set. * @return The elements present in both sets. */ public static LongSortedSet setIntersect(LongSet a, LongSet b) { if (a instanceof LongSortedSet && b instanceof LongSortedSet) { return setIntersect((LongSortedSet) a, (LongSortedSet) b); } else if (a.size() <= b.size()) { LongArrayList longs = new LongArrayList(Math.min(a.size(), b.size())); LongIterator iter = a.iterator(); while (iter.hasNext()) { long key = iter.nextLong(); if (b.contains(key)) { longs.add(key); } } return LongUtils.packedSet(longs); } else { return setIntersect(b, a); } }
@Override public LongSet keySet() { return LongUtils.asLongSet(map.keySet()); }
@Test public void testIntersectSizePackedSets() { assertThat(intersectSize(packedSet(1L, 3L, 5L, 7L), packedSet(2L, 3L, 4L, 5L, 6L)), equalTo(2)); }
@Nonnull @Override public MetricResult measureUser(TestUser user, ResultMap predictions, Mean context) { if (predictions == null || predictions.isEmpty()) { return MetricResult.empty(); } Long2DoubleMap ratings = user.getTestRatings(); long[] ideal = ratings.keySet().toLongArray(); LongArrays.quickSort(ideal, LongComparators.oppositeComparator(LongUtils.keyValueComparator(ratings))); long[] actual = LongUtils.asLongSet(predictions.keySet()).toLongArray(); LongArrays.quickSort(actual, LongComparators.oppositeComparator( LongUtils.keyValueComparator( LongUtils.asLong2DoubleMap(predictions.scoreMap())))); double idealGain = computeDCG(ideal, ratings); double gain = computeDCG(actual, ratings); logger.debug("user {} has gain of {} (ideal {})", user.getUserId(), gain, idealGain); double score = gain / idealGain; synchronized (context) { context.increment(score); } ImmutableMap.Builder<String,Double> results = ImmutableMap.builder(); return MetricResult.fromMap(results.put(columnName, score) .put(columnName + ".Raw", gain) .build()); }
@Nonnull @Override public MetricResult measureUser(TestUser user, ResultMap predictions, MeanAccumulator context) { if (predictions == null || predictions.isEmpty()) { return MetricResult.empty(); } Long2DoubleMap ratings = user.getTestRatings(); long[] ideal = ratings.keySet().toLongArray(); LongArrays.quickSort(ideal, LongComparators.oppositeComparator(LongUtils.keyValueComparator(ratings))); long[] actual = LongUtils.asLongSet(predictions.keySet()).toLongArray(); LongArrays.quickSort(actual, LongComparators.oppositeComparator( LongUtils.keyValueComparator( LongUtils.asLong2DoubleFunction(predictions.scoreMap())))); double idealGain = computeDCG(ideal, ratings); double gain = computeDCG(actual, ratings); logger.debug("user {} has gain of {} (ideal {})", user.getUserId(), gain, idealGain); double score = gain / idealGain; context.add(score); ImmutableMap.Builder<String,Double> results = ImmutableMap.builder(); return MetricResult.fromMap(results.put(columnName, score) .put(columnName + ".Raw", gain) .build()); }
private Long2DoubleSortedArrayMap slowSubMap(LongSet toKeep) { LongSortedSet kept = LongUtils.setIntersect(keySet(), toKeep); double[] nvs = new double[kept.size()]; int i = keys.getLowerBound(); int j = 0; LongIterator iter = kept.iterator(); while (iter.hasNext()) { long key = iter.nextLong(); while (keys.getKey(i) < key) { i++; } nvs[j] = values[i]; j++; i++; } return wrap(SortedKeyIndex.fromCollection(kept), nvs); }
@Test public void testRandomMaps() { for (Map<Long,Double> map: someMaps(longs(), doubles())) { Long2DoubleSortedArrayMap vec = Long2DoubleSortedArrayMap.create(map); Set<Long> picked = sets(map.keySet()).next(); Set<Long> extra = sets(longs()).next(); LongSortedSet wanted = LongUtils.setUnion(LongUtils.asLongSet(picked), LongUtils.asLongSet(extra)); Long2DoubleSortedMap sv = vec.subMap(wanted); assertThat(sv.keySet(), everyItem(isIn(wanted))); assertThat(sv.keySet(), containsInAnyOrder(picked.toArray())); assertThat(sv.entrySet(), everyItem(isIn(map.entrySet()))); } }
/** * Create a long-to-double function from a map, casting if appropriate. Useful to allow unboxed access to maps that * are really fastutil maps. * @param map The map. * @return A function backed by {@code map}, or {@code map} if it is a Fastutil map. * @deprecated see {@link #asLong2DoubleMap(Map)} */ @Deprecated public static Long2DoubleMap asLong2DoubleFunction(final Map<Long,Double> map) { return asLong2DoubleMap(map); }
/** * Create a new map with existing data. * @param data Use {@link #create(Map)} instead, as it can avoid copying maps that are already packed. */ @Deprecated public Long2DoubleSortedArrayMap(Map<Long,Double> data) { Long2DoubleFunction vf = LongUtils.asLong2DoubleFunction(data); keys = SortedKeyIndex.fromCollection(data.keySet()); int size = keys.size(); values = new double[size]; for (int i = 0; i < size; i++) { values[i] = vf.get(keys.getKey(i)); } }
@Nonnull @Override public MetricResult measureUser(TestUser user, ResultList recommendations, MeanAccumulator context) { if (recommendations == null) { return MetricResult.empty(); } Long2DoubleMap ratings = user.getTestRatings(); long[] ideal = ratings.keySet().toLongArray(); LongArrays.quickSort(ideal, LongComparators.oppositeComparator(LongUtils.keyValueComparator(ratings))); double idealGain = computeDCG(ideal, ratings); long[] actual = LongUtils.asLongCollection(recommendations.idList()).toLongArray(); double gain = computeDCG(actual, ratings); double score = gain / idealGain; context.add(score); return MetricResult.singleton(columnName, score); }