Author: srowen
Date: Fri Oct 31 12:02:53 2008
New Revision: 709534
URL: http://svn.apache.org/viewvc?rev=709534&view=rev
Log:
Allow CachingRecommender to cache rescored entries as long as the Rescorer does
not change
Modified:
lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/CachingRecommender.java
lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/CachingRecommenderTest.java
Modified:
lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/CachingRecommender.java
URL:
http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/CachingRecommender.java?rev=709534&r1=709533&r2=709534&view=diff
==============================================================================
---
lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/CachingRecommender.java
(original)
+++
lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/CachingRecommender.java
Fri Oct 31 12:02:53 2008
@@ -52,6 +52,7 @@
private final Cache<Object, Recommendations> recommendationCache;
private final Cache<Pair<?, ?>, Double> estimatedPrefCache;
private final RefreshHelper refreshHelper;
+ private Rescorer<Item> currentRescorer;
public CachingRecommender(Recommender recommender) throws TasteException {
if (recommender == null) {
@@ -62,9 +63,7 @@
// Use "num users" as an upper limit on cache size. Rough guess.
int numUsers = recommender.getDataModel().getNumUsers();
this.recommendationCache =
- new Cache<Object, Recommendations>(
- new RecommendationRetriever(this.recommender,
this.maxHowMany),
- numUsers);
+ new Cache<Object, Recommendations>(new
RecommendationRetriever(this.recommender), numUsers);
this.estimatedPrefCache =
new Cache<Pair<?, ?>, Double>(new
EstimatedPrefRetriever(this.recommender), numUsers);
this.refreshHelper = new RefreshHelper(new Callable<Object>() {
@@ -76,9 +75,28 @@
this.refreshHelper.addDependency(recommender);
}
+ private synchronized void setCurrentRescorer(Rescorer<Item> rescorer) {
+ if (rescorer == null) {
+ if (currentRescorer != null) {
+ currentRescorer = null;
+ clear();
+ }
+ } else {
+ if (!rescorer.equals(currentRescorer)) {
+ currentRescorer = rescorer;
+ clear();
+ }
+ }
+ }
+
public List<RecommendedItem> recommend(Object userID, int howMany) throws
TasteException {
+ return recommend(userID, howMany, null);
+ }
+
+ public List<RecommendedItem> recommend(Object userID, int howMany,
Rescorer<Item> rescorer)
+ throws TasteException {
if (userID == null) {
- throw new IllegalArgumentException("user ID is null");
+ throw new IllegalArgumentException("userID is null");
}
if (howMany < 1) {
throw new IllegalArgumentException("howMany must be at least 1");
@@ -90,6 +108,8 @@
}
}
+ setCurrentRescorer(rescorer);
+
Recommendations recommendations = recommendationCache.get(userID);
if (recommendations.getItems().size() < howMany &&
!recommendations.noMoreRecommendableItems) {
clear(userID);
@@ -104,12 +124,6 @@
recommendations.getItems();
}
- public List<RecommendedItem> recommend(Object userID, int howMany,
Rescorer<Item> rescorer)
- throws TasteException {
- // Hmm, hard to recommendationCache this since the rescorer may change
- return recommender.recommend(userID, howMany, rescorer);
- }
-
public double estimatePreference(Object userID, Object itemID) throws
TasteException {
return estimatedPrefCache.get(new Pair<Object, Object>(userID, itemID));
}
@@ -155,19 +169,18 @@
return "CachingRecommender[recommender:" + recommender + ']';
}
- private static final class RecommendationRetriever implements
Retriever<Object, Recommendations> {
+ private final class RecommendationRetriever implements Retriever<Object,
Recommendations> {
private final Recommender recommender;
- private final AtomicInteger maxHowMany;
- private RecommendationRetriever(Recommender recommender, AtomicInteger
maxHowMany) {
+ private RecommendationRetriever(Recommender recommender) {
this.recommender = recommender;
- this.maxHowMany = maxHowMany;
}
public Recommendations get(Object key) throws TasteException {
log.debug("Retrieving new recommendations for user ID '{}'", key);
- return new
Recommendations(Collections.unmodifiableList(recommender.recommend(key,
maxHowMany.get())));
+ return new Recommendations(
+ Collections.unmodifiableList(recommender.recommend(key,
maxHowMany.get(), currentRescorer)));
}
}
Modified:
lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/CachingRecommenderTest.java
URL:
http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/CachingRecommenderTest.java?rev=709534&r1=709533&r2=709534&view=diff
==============================================================================
---
lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/CachingRecommenderTest.java
(original)
+++
lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/CachingRecommenderTest.java
Fri Oct 31 12:02:53 2008
@@ -50,7 +50,7 @@
cachingRecommender.recommend("3", 1);
assertEquals(5, recommendCount.get());
- // Results from this recommend() method can't be cached:
+ // Results from this recommend() method can be cached...
Rescorer<Item> rescorer = NullRescorer.getItemInstance();
cachingRecommender.refresh(null);
cachingRecommender.recommend("1", 1, rescorer);
@@ -58,8 +58,14 @@
cachingRecommender.recommend("2", 1, rescorer);
assertEquals(7, recommendCount.get());
cachingRecommender.recommend("1", 1, rescorer);
- assertEquals(8, recommendCount.get());
+ assertEquals(7, recommendCount.get());
cachingRecommender.recommend("2", 1, rescorer);
+ assertEquals(7, recommendCount.get());
+
+ // until you switch Rescorers
+ cachingRecommender.recommend("1", 1, null);
+ assertEquals(8, recommendCount.get());
+ cachingRecommender.recommend("2", 1, null);
assertEquals(9, recommendCount.get());
cachingRecommender.refresh(null);