/** * Add all items from a map to the accumulator. * @param map The map. */ default void putAll(Long2DoubleMap map) { for (Long2DoubleMap.Entry e: Long2DoubleMaps.fastIterable(map)) { put(e.getLongKey(), e.getDoubleValue()); } }
@Override public BiConsumer<Long2ObjectMap<Long2DoubleAccumulator>, IdBox<Long2DoubleMap>> accumulator() { return (acc, row) -> { long i1 = row.getId(); for (Long2DoubleMap.Entry e: Long2DoubleMaps.fastIterable(row.getValue())) { long i2 = e.getLongKey(); double sim = e.getDoubleValue(); acc.computeIfAbsent(i1, i -> newAccumulator()) .put(i2, sim); acc.computeIfAbsent(i2, i -> newAccumulator()) .put(i1, sim); } }; }
@Test public void testAccumMapLimit() { accum.put(7, 1.0); accum.put(5, 4.2); accum.put(3, 2.9); accum.put(2, 9.8); accum.put(8, 2.1); Long2DoubleMap out = accum.finishMap(); assertThat(out.size(), equalTo(3)); assertThat(out, hasEntry(2L, 9.8)); assertThat(out, hasEntry(5L, 4.2)); assertThat(out, hasEntry(3L, 2.9)); }
protected void scoreItem(Long2DoubleMap userData, long item, ItemItemScoreAccumulator accum) { // find the usable neighbors Long2DoubleSortedArrayMap allNeighbors = Long2DoubleSortedArrayMap.create(model.getNeighbors(item)); Long2DoubleMap neighborhood = allNeighbors.subMap(userData.keySet()); if (neighborhoodSize > 0) { if (logger.isTraceEnabled()) { logger.trace("truncating {} neighbors to {}", neighborhood.size(), neighborhoodSize); } Long2DoubleAccumulator acc = new TopNLong2DoubleAccumulator(neighborhoodSize); for (Long2DoubleMap.Entry e: neighborhood.long2DoubleEntrySet()) { acc.put(e.getLongKey(), e.getDoubleValue()); } neighborhood = acc.finishMap(); } assert neighborhoodSize <= 0 || neighborhood.size() <= neighborhoodSize; if (neighborhood.size() < minNeighbors) { return; } if (logger.isTraceEnabled()) { logger.trace("scoring item {} with {} of {} neighbors", item, neighborhood.size(), allNeighbors.size()); } scorer.score(item, neighborhood, userData, accum); } }
/** * Implement recommendation by calling {@link ItemScorer#score(long, Collection)} and sorting * the results by score. This method uses {@link #getDefaultExcludes(long)} to get the default * exclude set for the user, if none is provided. */ @Override protected List<Long> recommend(long user, int n, LongSet candidates, LongSet exclude) { candidates = getEffectiveCandidates(user, candidates, exclude); logger.debug("Computing {} recommendations for user {} from {} candidates", n, user, candidates.size()); Map<Long, Double> scores = scorer.score(user, candidates); Long2DoubleAccumulator accum; if (n >= 0) { accum = new TopNLong2DoubleAccumulator(n); } else { accum = new UnlimitedLong2DoubleAccumulator(); } Long2DoubleMap map = LongUtils.asLong2DoubleMap(scores); for (Long2DoubleMap.Entry e: Vectors.fastEntries(map)) { accum.put(e.getLongKey(), e.getDoubleValue()); } return accum.finishList(); }
@Override public BinaryOperator<Long2ObjectMap<Long2DoubleAccumulator>> combiner() { return (am1, am2) -> { for (Long2ObjectMap.Entry<Long2DoubleAccumulator> e: Long2ObjectMaps.fastIterable(am2)) { long item = e.getLongKey(); Long2DoubleAccumulator a2 = e.getValue(); Long2DoubleAccumulator a1 = am1.get(item); if (a1 == null) { am1.put(item, a2); } else { for (Long2DoubleMap.Entry ae: Long2DoubleMaps.fastIterable(a2.finishMap())) { a1.put(ae.getLongKey(), ae.getDoubleValue()); } } } return am1; }; }
/** * Score a single item into an accumulator. * @param scores The reference scores. * @param item The item to score. * @param accum The accumulator. */ protected void scoreItem(Long2DoubleMap scores, long item, ItemItemScoreAccumulator accum) { Long2DoubleMap allNeighbors = model.getNeighbors(item); Long2DoubleAccumulator acc; if (neighborhoodSize > 0) { // FIXME Abstract accumulator selection logic acc = new TopNLong2DoubleAccumulator(neighborhoodSize); } else { acc = new UnlimitedLong2DoubleAccumulator(); } for (Long2DoubleMap.Entry nbr: allNeighbors.long2DoubleEntrySet()) { if (scores.containsKey(nbr.getLongKey())) { acc.put(nbr.getLongKey(), nbr.getDoubleValue()); } } Long2DoubleMap neighborhood = acc.finishMap(); scorer.score(item, neighborhood, scores, accum); } }
/** * Add all items from a map to the accumulator. * @param map The map. */ default void putAll(Long2DoubleMap map) { for (Long2DoubleMap.Entry e: Long2DoubleMaps.fastIterable(map)) { put(e.getLongKey(), e.getDoubleValue()); } }
@Override public BiConsumer<Long2ObjectMap<Long2DoubleAccumulator>, IdBox<Long2DoubleMap>> accumulator() { return (acc, row) -> { long i1 = row.getId(); for (Long2DoubleMap.Entry e: Long2DoubleMaps.fastIterable(row.getValue())) { long i2 = e.getLongKey(); double sim = e.getDoubleValue(); acc.computeIfAbsent(i1, i -> newAccumulator()) .put(i2, sim); acc.computeIfAbsent(i2, i -> newAccumulator()) .put(i1, sim); } }; }
protected void scoreItem(Long2DoubleMap userData, long item, ItemItemScoreAccumulator accum) { // find the usable neighbors Long2DoubleSortedArrayMap allNeighbors = Long2DoubleSortedArrayMap.create(model.getNeighbors(item)); Long2DoubleMap neighborhood = allNeighbors.subMap(userData.keySet()); if (neighborhoodSize > 0) { if (logger.isTraceEnabled()) { logger.trace("truncating {} neighbors to {}", neighborhood.size(), neighborhoodSize); } Long2DoubleAccumulator acc = new TopNLong2DoubleAccumulator(neighborhoodSize); for (Long2DoubleMap.Entry e: neighborhood.long2DoubleEntrySet()) { acc.put(e.getLongKey(), e.getDoubleValue()); } neighborhood = acc.finishMap(); } assert neighborhoodSize <= 0 || neighborhood.size() <= neighborhoodSize; if (neighborhood.size() < minNeighbors) { return; } if (logger.isTraceEnabled()) { logger.trace("scoring item {} with {} of {} neighbors", item, neighborhood.size(), allNeighbors.size()); } scorer.score(item, neighborhood, userData, accum); } }
/** * Implement recommendation by calling {@link ItemScorer#score(long, Collection)} and sorting * the results by score. This method uses {@link #getDefaultExcludes(long)} to get the default * exclude set for the user, if none is provided. */ @Override protected List<Long> recommend(long user, int n, LongSet candidates, LongSet exclude) { candidates = getEffectiveCandidates(user, candidates, exclude); logger.debug("Computing {} recommendations for user {} from {} candidates", n, user, candidates.size()); Map<Long, Double> scores = scorer.score(user, candidates); Long2DoubleAccumulator accum; if (n >= 0) { accum = new TopNLong2DoubleAccumulator(n); } else { accum = new UnlimitedLong2DoubleAccumulator(); } Long2DoubleMap map = LongUtils.asLong2DoubleMap(scores); for (Long2DoubleMap.Entry e: Vectors.fastEntries(map)) { accum.put(e.getLongKey(), e.getDoubleValue()); } return accum.finishList(); }
@Override public BinaryOperator<Long2ObjectMap<Long2DoubleAccumulator>> combiner() { return (am1, am2) -> { for (Long2ObjectMap.Entry<Long2DoubleAccumulator> e: Long2ObjectMaps.fastIterable(am2)) { long item = e.getLongKey(); Long2DoubleAccumulator a2 = e.getValue(); Long2DoubleAccumulator a1 = am1.get(item); if (a1 == null) { am1.put(item, a2); } else { for (Long2DoubleMap.Entry ae: Long2DoubleMaps.fastIterable(a2.finishMap())) { a1.put(ae.getLongKey(), ae.getDoubleValue()); } } } return am1; }; }
/** * Score a single item into an accumulator. * @param scores The reference scores. * @param item The item to score. * @param accum The accumulator. */ protected void scoreItem(Long2DoubleMap scores, long item, ItemItemScoreAccumulator accum) { Long2DoubleMap allNeighbors = model.getNeighbors(item); Long2DoubleAccumulator acc; if (neighborhoodSize > 0) { // FIXME Abstract accumulator selection logic acc = new TopNLong2DoubleAccumulator(neighborhoodSize); } else { acc = new UnlimitedLong2DoubleAccumulator(); } for (Long2DoubleMap.Entry nbr: allNeighbors.long2DoubleEntrySet()) { if (scores.containsKey(nbr.getLongKey())) { acc.put(nbr.getLongKey(), nbr.getDoubleValue()); } } Long2DoubleMap neighborhood = acc.finishMap(); scorer.score(item, neighborhood, scores, accum); } }