Author: srowen
Date: Thu Sep 16 08:22:17 2010
New Revision: 997638

URL: http://svn.apache.org/viewvc?rev=997638&view=rev
Log:
Add count of NaN cases

Modified:
    
mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/AbstractDifferenceRecommenderEvaluator.java

Modified: 
mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/AbstractDifferenceRecommenderEvaluator.java
URL: 
http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/AbstractDifferenceRecommenderEvaluator.java?rev=997638&r1=997637&r2=997638&view=diff
==============================================================================
--- 
mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/AbstractDifferenceRecommenderEvaluator.java
 (original)
+++ 
mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/AbstractDifferenceRecommenderEvaluator.java
 Thu Sep 16 08:22:17 2010
@@ -27,6 +27,7 @@ import java.util.concurrent.ExecutionExc
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.mahout.cf.taste.common.NoSuchItemException;
 import org.apache.mahout.cf.taste.common.NoSuchUserException;
@@ -175,20 +176,21 @@ abstract class AbstractDifferenceRecomme
   }
   
   private double getEvaluation(FastByIDMap<PreferenceArray> testUserPrefs, 
Recommender recommender)
-      throws TasteException {
+    throws TasteException {
     reset();
     Collection<Callable<Void>> estimateCallables = new 
ArrayList<Callable<Void>>();
+    AtomicInteger noEstimateCounter = new AtomicInteger();
     for (Map.Entry<Long,PreferenceArray> entry : testUserPrefs.entrySet()) {
-      estimateCallables.add(new PreferenceEstimateCallable(recommender, 
entry.getKey(), entry.getValue()));
+      estimateCallables.add(
+          new PreferenceEstimateCallable(recommender, entry.getKey(), 
entry.getValue(), noEstimateCounter));
     }
-    log.info("Beginning evaluation of {} users", estimateCallables
-        .size());
-    execute(estimateCallables);
+    log.info("Beginning evaluation of {} users", estimateCallables.size());
+    execute(estimateCallables, noEstimateCounter);
     return computeFinalEvaluation();
   }
   
-  static void execute(Collection<Callable<Void>> callables) throws 
TasteException {
-    callables = wrapWithStatsCallables(callables);
+  static void execute(Collection<Callable<Void>> callables, AtomicInteger 
noEstimateCounter) throws TasteException {
+    callables = wrapWithStatsCallables(callables, noEstimateCounter);
     int numProcessors = Runtime.getRuntime().availableProcessors();
     ExecutorService executor = Executors.newFixedThreadPool(numProcessors);
     log.info("Starting timing of {} tasks in {} threads", callables
@@ -209,14 +211,15 @@ abstract class AbstractDifferenceRecomme
     executor.shutdown();
   }
   
-  private static Collection<Callable<Void>> 
wrapWithStatsCallables(Collection<Callable<Void>> callables) {
+  private static Collection<Callable<Void>> 
wrapWithStatsCallables(Collection<Callable<Void>> callables,
+                                                                   
AtomicInteger noEstimateCounter) {
     int size = callables.size();
     Collection<Callable<Void>> wrapped = new ArrayList<Callable<Void>>(size);
     int count = 0;
     RunningAverageAndStdDev timing = new FullRunningAverageAndStdDev();
     for (Callable<Void> callable : callables) {
       boolean logStats = count++ % 1000 == 0; // log every 100 or so iterations
-      wrapped.add(new StatsCallable(callable, logStats, timing));
+      wrapped.add(new StatsCallable(callable, logStats, timing, 
noEstimateCounter));
     }
     return wrapped;
   }
@@ -232,11 +235,16 @@ abstract class AbstractDifferenceRecomme
     private final Recommender recommender;
     private final long testUserID;
     private final PreferenceArray prefs;
+    private final AtomicInteger noEstimateCounter;
     
-    private PreferenceEstimateCallable(Recommender recommender, long 
testUserID, PreferenceArray prefs) {
+    private PreferenceEstimateCallable(Recommender recommender,
+                                       long testUserID,
+                                       PreferenceArray prefs,
+                                       AtomicInteger noEstimateCounter) {
       this.recommender = recommender;
       this.testUserID = testUserID;
       this.prefs = prefs;
+      this.noEstimateCounter = noEstimateCounter;
     }
     
     @Override
@@ -248,13 +256,13 @@ abstract class AbstractDifferenceRecomme
         } catch (NoSuchUserException nsue) {
           // It's possible that an item exists in the test data but not 
training data in which case
           // NSEE will be thrown. Just ignore it and move on.
-          log.info(
-            "User exists in test data but not training data: {}", testUserID);
+          log.info("User exists in test data but not training data: {}", 
testUserID);
         } catch (NoSuchItemException nsie) {
-          log.info(
-            "Item exists in test data but not training data: {}", 
realPref.getItemID());
+          log.info("Item exists in test data but not training data: {}", 
realPref.getItemID());
         }
-        if (!Float.isNaN(estimatedPreference)) {
+        if (Float.isNaN(estimatedPreference)) {
+          noEstimateCounter.incrementAndGet();
+        } else {
           estimatedPreference = capEstimatedPreference(estimatedPreference);
           processOneEstimate(estimatedPreference, realPref);
         }
@@ -269,11 +277,16 @@ abstract class AbstractDifferenceRecomme
     private final Callable<Void> delegate;
     private final boolean logStats;
     private final RunningAverageAndStdDev timing;
+    private final AtomicInteger noEstimateCounter;
     
-    private StatsCallable(Callable<Void> delegate, boolean logStats, 
RunningAverageAndStdDev timing) {
+    private StatsCallable(Callable<Void> delegate,
+                          boolean logStats,
+                          RunningAverageAndStdDev timing,
+                          AtomicInteger noEstimateCounter) {
       this.delegate = delegate;
       this.logStats = logStats;
       this.timing = timing;
+      this.noEstimateCounter = noEstimateCounter;
     }
     
     @Override
@@ -288,8 +301,8 @@ abstract class AbstractDifferenceRecomme
         log.info("Average time per recommendation: {}ms", average);
         long totalMemory = runtime.totalMemory();
         long memory = totalMemory - runtime.freeMemory();
-        log.info("Approximate memory used: {}MB / {}MB",
-          memory / 1000000L, totalMemory / 1000000L);
+        log.info("Approximate memory used: {}MB / {}MB", memory / 1000000L, 
totalMemory / 1000000L);
+        log.info("Unable to recommend in {} cases", noEstimateCounter.get());
       }
       return null;
     }


Reply via email to