You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mahout.apache.org by ro...@apache.org on 2010/02/13 21:54:31 UTC
svn commit: r909912 [4/10] - in
/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste: common/
eval/ hadoop/ hadoop/cooccurence/ hadoop/item/ hadoop/pseudo/
hadoop/slopeone/ impl/common/ impl/common/jdbc/ impl/eval/ impl/model/
impl/model/...
Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/AbstractDifferenceRecommenderEvaluator.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/AbstractDifferenceRecommenderEvaluator.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/AbstractDifferenceRecommenderEvaluator.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/AbstractDifferenceRecommenderEvaluator.java Sat Feb 13 20:54:05 2010
@@ -17,6 +17,17 @@
package org.apache.mahout.cf.taste.impl.eval;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
import org.apache.mahout.cf.taste.common.NoSuchItemException;
import org.apache.mahout.cf.taste.common.NoSuchUserException;
import org.apache.mahout.cf.taste.common.TasteException;
@@ -38,82 +49,72 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-
/**
* Abstract superclass of a couple implementations, providing shared functionality.
*/
abstract class AbstractDifferenceRecommenderEvaluator implements RecommenderEvaluator {
-
+
private static final Logger log = LoggerFactory.getLogger(AbstractDifferenceRecommenderEvaluator.class);
-
+
private final Random random;
private float maxPreference;
private float minPreference;
-
+
AbstractDifferenceRecommenderEvaluator() {
random = RandomUtils.getRandom();
maxPreference = Float.NaN;
minPreference = Float.NaN;
}
-
+
@Override
public final float getMaxPreference() {
return maxPreference;
}
-
+
@Override
public final void setMaxPreference(float maxPreference) {
this.maxPreference = maxPreference;
}
-
+
@Override
public final float getMinPreference() {
return minPreference;
}
-
+
@Override
public final void setMinPreference(float minPreference) {
this.minPreference = minPreference;
}
-
+
@Override
public final double evaluate(RecommenderBuilder recommenderBuilder,
DataModelBuilder dataModelBuilder,
DataModel dataModel,
double trainingPercentage,
double evaluationPercentage) throws TasteException {
-
+
if (recommenderBuilder == null) {
throw new IllegalArgumentException("recommenderBuilder is null");
}
if (dataModel == null) {
throw new IllegalArgumentException("dataModel is null");
}
- if (Double.isNaN(trainingPercentage) || trainingPercentage <= 0.0 || trainingPercentage >= 1.0) {
+ if (Double.isNaN(trainingPercentage) || (trainingPercentage <= 0.0) || (trainingPercentage >= 1.0)) {
throw new IllegalArgumentException("Invalid trainingPercentage: " + trainingPercentage);
}
- if (Double.isNaN(evaluationPercentage) || evaluationPercentage <= 0.0 || evaluationPercentage > 1.0) {
+ if (Double.isNaN(evaluationPercentage) || (evaluationPercentage <= 0.0) || (evaluationPercentage > 1.0)) {
throw new IllegalArgumentException("Invalid evaluationPercentage: " + evaluationPercentage);
}
-
- log.info("Beginning evaluation using {} of {}", trainingPercentage, dataModel);
-
+
+ AbstractDifferenceRecommenderEvaluator.log.info("Beginning evaluation using {} of {}",
+ trainingPercentage, dataModel);
+
int numUsers = dataModel.getNumUsers();
- FastByIDMap<PreferenceArray> trainingUsers =
- new FastByIDMap<PreferenceArray>(1 + (int) (evaluationPercentage * (double) numUsers));
- FastByIDMap<PreferenceArray> testUserPrefs =
- new FastByIDMap<PreferenceArray>(1 + (int) (evaluationPercentage * (double) numUsers));
-
+ FastByIDMap<PreferenceArray> trainingUsers = new FastByIDMap<PreferenceArray>(
+ 1 + (int) (evaluationPercentage * numUsers));
+ FastByIDMap<PreferenceArray> testUserPrefs = new FastByIDMap<PreferenceArray>(
+ 1 + (int) (evaluationPercentage * numUsers));
+
LongPrimitiveIterator it = dataModel.getUserIDs();
while (it.hasNext()) {
long userID = it.nextLong();
@@ -121,18 +122,17 @@
processOneUser(trainingPercentage, trainingUsers, testUserPrefs, userID, dataModel);
}
}
-
- DataModel trainingModel = dataModelBuilder == null ?
- new GenericDataModel(trainingUsers) :
- dataModelBuilder.buildDataModel(trainingUsers);
-
+
+ DataModel trainingModel = dataModelBuilder == null ? new GenericDataModel(trainingUsers)
+ : dataModelBuilder.buildDataModel(trainingUsers);
+
Recommender recommender = recommenderBuilder.buildRecommender(trainingModel);
-
+
double result = getEvaluation(testUserPrefs, recommender);
- log.info("Evaluation result: {}", result);
+ AbstractDifferenceRecommenderEvaluator.log.info("Evaluation result: {}", result);
return result;
}
-
+
private void processOneUser(double trainingPercentage,
FastByIDMap<PreferenceArray> trainingUsers,
FastByIDMap<PreferenceArray> testUserPrefs,
@@ -163,7 +163,7 @@
}
}
}
-
+
private float capEstimatedPreference(float estimate) {
if (estimate > maxPreference) {
return maxPreference;
@@ -173,24 +173,25 @@
}
return estimate;
}
-
- private double getEvaluation(FastByIDMap<PreferenceArray> testUserPrefs, Recommender recommender)
- throws TasteException {
+
+ private double getEvaluation(FastByIDMap<PreferenceArray> testUserPrefs, Recommender recommender) throws TasteException {
reset();
Collection<Callable<Void>> estimateCallables = new ArrayList<Callable<Void>>();
- for (Map.Entry<Long, PreferenceArray> entry : testUserPrefs.entrySet()) {
+ for (Map.Entry<Long,PreferenceArray> entry : testUserPrefs.entrySet()) {
estimateCallables.add(new PreferenceEstimateCallable(recommender, entry.getKey(), entry.getValue()));
}
- log.info("Beginning evaluation of {} users", estimateCallables.size());
- execute(estimateCallables);
+ AbstractDifferenceRecommenderEvaluator.log.info("Beginning evaluation of {} users", estimateCallables
+ .size());
+ AbstractDifferenceRecommenderEvaluator.execute(estimateCallables);
return computeFinalEvaluation();
}
-
+
static void execute(Collection<Callable<Void>> callables) throws TasteException {
- callables = wrapWithStatsCallables(callables);
+ callables = AbstractDifferenceRecommenderEvaluator.wrapWithStatsCallables(callables);
int numProcessors = Runtime.getRuntime().availableProcessors();
ExecutorService executor = Executors.newFixedThreadPool(numProcessors);
- log.info("Starting timing of {} tasks in {} threads", callables.size(), numProcessors);
+ AbstractDifferenceRecommenderEvaluator.log.info("Starting timing of {} tasks in {} threads", callables
+ .size(), numProcessors);
try {
List<Future<Void>> futures = executor.invokeAll(callables);
// Go look for exceptions here, really
@@ -206,7 +207,7 @@
}
executor.shutdown();
}
-
+
private static Collection<Callable<Void>> wrapWithStatsCallables(Collection<Callable<Void>> callables) {
int size = callables.size();
Collection<Callable<Void>> wrapped = new ArrayList<Callable<Void>>(size);
@@ -218,28 +219,25 @@
}
return wrapped;
}
-
+
abstract void reset();
-
+
abstract void processOneEstimate(float estimatedPreference, Preference realPref);
-
+
abstract double computeFinalEvaluation();
-
-
+
private class PreferenceEstimateCallable implements Callable<Void> {
-
+
private final Recommender recommender;
private final long testUserID;
private final PreferenceArray prefs;
-
- private PreferenceEstimateCallable(Recommender recommender,
- long testUserID,
- PreferenceArray prefs) {
+
+ private PreferenceEstimateCallable(Recommender recommender, long testUserID, PreferenceArray prefs) {
this.recommender = recommender;
this.testUserID = testUserID;
this.prefs = prefs;
}
-
+
@Override
public Void call() throws TasteException {
for (Preference realPref : prefs) {
@@ -249,9 +247,11 @@
} 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);
+ AbstractDifferenceRecommenderEvaluator.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());
+ AbstractDifferenceRecommenderEvaluator.log.info(
+ "Item exists in test data but not training data: {}", realPref.getItemID());
}
if (!Float.isNaN(estimatedPreference)) {
estimatedPreference = capEstimatedPreference(estimatedPreference);
@@ -260,21 +260,21 @@
}
return null;
}
-
+
}
-
+
private static class StatsCallable implements Callable<Void> {
-
+
private final Callable<Void> delegate;
private final boolean logStats;
private final RunningAverageAndStdDev timing;
-
+
private StatsCallable(Callable<Void> delegate, boolean logStats, RunningAverageAndStdDev timing) {
this.delegate = delegate;
this.logStats = logStats;
this.timing = timing;
}
-
+
@Override
public Void call() throws Exception {
long start = System.currentTimeMillis();
@@ -284,13 +284,14 @@
if (logStats) {
Runtime runtime = Runtime.getRuntime();
int average = (int) timing.getAverage();
- log.info("Average time per recommendation: {}ms", average);
+ AbstractDifferenceRecommenderEvaluator.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);
+ AbstractDifferenceRecommenderEvaluator.log.info("Approximate memory used: {}MB / {}MB",
+ memory / 1000000L, totalMemory / 1000000L);
}
return null;
}
}
-
+
}
Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/AverageAbsoluteDifferenceRecommenderEvaluator.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/AverageAbsoluteDifferenceRecommenderEvaluator.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/AverageAbsoluteDifferenceRecommenderEvaluator.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/AverageAbsoluteDifferenceRecommenderEvaluator.java Sat Feb 13 20:54:05 2010
@@ -22,33 +22,38 @@
import org.apache.mahout.cf.taste.model.Preference;
/**
- * <p>A {@link org.apache.mahout.cf.taste.eval.RecommenderEvaluator} which computes the average absolute difference
- * between predicted and actual ratings for users.</p>
- *
- * <p>This algorithm is also called "mean average error".</p>
+ * <p>
+ * A {@link org.apache.mahout.cf.taste.eval.RecommenderEvaluator} which computes the average absolute
+ * difference between predicted and actual ratings for users.
+ * </p>
+ *
+ * <p>
+ * This algorithm is also called "mean average error".
+ * </p>
*/
-public final class AverageAbsoluteDifferenceRecommenderEvaluator extends AbstractDifferenceRecommenderEvaluator {
-
+public final class AverageAbsoluteDifferenceRecommenderEvaluator extends
+ AbstractDifferenceRecommenderEvaluator {
+
private RunningAverage average;
-
+
@Override
void reset() {
average = new FullRunningAverage();
}
-
+
@Override
void processOneEstimate(float estimatedPreference, Preference realPref) {
average.addDatum(Math.abs(realPref.getValue() - estimatedPreference));
}
-
+
@Override
double computeFinalEvaluation() {
return average.getAverage();
}
-
+
@Override
public String toString() {
return "AverageAbsoluteDifferenceRecommenderEvaluator";
}
-
+
}
Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/GenericRecommenderIRStatsEvaluator.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/GenericRecommenderIRStatsEvaluator.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/GenericRecommenderIRStatsEvaluator.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/GenericRecommenderIRStatsEvaluator.java Sat Feb 13 20:54:05 2010
@@ -17,6 +17,11 @@
package org.apache.mahout.cf.taste.impl.eval;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Random;
+
import org.apache.mahout.cf.taste.common.NoSuchUserException;
import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.eval.DataModelBuilder;
@@ -28,8 +33,6 @@
import org.apache.mahout.cf.taste.impl.common.FullRunningAverage;
import org.apache.mahout.cf.taste.impl.common.FullRunningAverageAndStdDev;
import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;
-import org.apache.mahout.cf.taste.recommender.IDRescorer;
-import org.apache.mahout.common.RandomUtils;
import org.apache.mahout.cf.taste.impl.common.RunningAverage;
import org.apache.mahout.cf.taste.impl.common.RunningAverageAndStdDev;
import org.apache.mahout.cf.taste.impl.model.GenericDataModel;
@@ -37,40 +40,39 @@
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.model.Preference;
import org.apache.mahout.cf.taste.model.PreferenceArray;
+import org.apache.mahout.cf.taste.recommender.IDRescorer;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.Recommender;
+import org.apache.mahout.common.RandomUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Random;
-
/**
- * <p>For each user, these implementation determine the top <code>n</code> preferences, then evaluate the IR
- * statistics based on a {@link DataModel} that does not have these values. This number <code>n</code> is the "at"
- * value, as in "precision at 5". For example, this would mean precision evaluated by removing the top 5 preferences for
- * a user and then finding the percentage of those 5 items included in the top 5 recommendations for
- * that user.</p>
+ * <p>
+ * For each user, these implementation determine the top <code>n</code> preferences, then evaluate the IR
+ * statistics based on a {@link DataModel} that does not have these values. This number <code>n</code> is the
+ * "at" value, as in "precision at 5". For example, this would mean precision evaluated by removing the top 5
+ * preferences for a user and then finding the percentage of those 5 items included in the top 5
+ * recommendations for that user.
+ * </p>
*/
public final class GenericRecommenderIRStatsEvaluator implements RecommenderIRStatsEvaluator {
-
+
private static final Logger log = LoggerFactory.getLogger(GenericRecommenderIRStatsEvaluator.class);
-
+
/**
* Pass as "relevanceThreshold" argument to
- * {@link #evaluate(RecommenderBuilder, DataModelBuilder, DataModel, IDRescorer, int, double, double)}
- * to have it attempt to compute a reasonable threshold. Note that this will impact performance.
+ * {@link #evaluate(RecommenderBuilder, DataModelBuilder, DataModel, IDRescorer, int, double, double)} to
+ * have it attempt to compute a reasonable threshold. Note that this will impact performance.
*/
public static final double CHOOSE_THRESHOLD = Double.NaN;
-
+
private final Random random;
-
+
public GenericRecommenderIRStatsEvaluator() {
random = RandomUtils.getRandom();
}
-
+
@Override
public IRStatistics evaluate(RecommenderBuilder recommenderBuilder,
DataModelBuilder dataModelBuilder,
@@ -79,7 +81,7 @@
int at,
double relevanceThreshold,
double evaluationPercentage) throws TasteException {
-
+
if (recommenderBuilder == null) {
throw new IllegalArgumentException("recommenderBuilder is null");
}
@@ -89,10 +91,10 @@
if (at < 1) {
throw new IllegalArgumentException("at must be at least 1");
}
- if (Double.isNaN(evaluationPercentage) || evaluationPercentage <= 0.0 || evaluationPercentage > 1.0) {
+ if (Double.isNaN(evaluationPercentage) || (evaluationPercentage <= 0.0) || (evaluationPercentage > 1.0)) {
throw new IllegalArgumentException("Invalid evaluationPercentage: " + evaluationPercentage);
}
-
+
int numItems = dataModel.getNumItems();
RunningAverage precision = new FullRunningAverage();
RunningAverage recall = new FullRunningAverage();
@@ -109,35 +111,36 @@
// Really not enough prefs to meaningfully evaluate this user
continue;
}
-
+
// List some most-preferred items that would count as (most) "relevant" results
- double theRelevanceThreshold = Double.isNaN(relevanceThreshold) ? computeThreshold(prefs) : relevanceThreshold;
+ double theRelevanceThreshold = Double.isNaN(relevanceThreshold) ? GenericRecommenderIRStatsEvaluator
+ .computeThreshold(prefs) : relevanceThreshold;
prefs.sortByValueReversed();
- for (int i = 0; i < size && relevantItemIDs.size() < at; i++) {
+ for (int i = 0; (i < size) && (relevantItemIDs.size() < at); i++) {
if (prefs.getValue(i) >= theRelevanceThreshold) {
relevantItemIDs.add(prefs.getItemID(i));
}
}
int numRelevantItems = relevantItemIDs.size();
if (numRelevantItems > 0) {
- FastByIDMap<PreferenceArray> trainingUsers =
- new FastByIDMap<PreferenceArray>(dataModel.getNumUsers());
+ FastByIDMap<PreferenceArray> trainingUsers = new FastByIDMap<PreferenceArray>(dataModel
+ .getNumUsers());
LongPrimitiveIterator it2 = dataModel.getUserIDs();
while (it2.hasNext()) {
- processOtherUser(userID, relevantItemIDs, trainingUsers, it2.nextLong(), dataModel);
+ GenericRecommenderIRStatsEvaluator.processOtherUser(userID, relevantItemIDs, trainingUsers, it2
+ .nextLong(), dataModel);
}
-
- DataModel trainingModel = dataModelBuilder == null ?
- new GenericDataModel(trainingUsers) :
- dataModelBuilder.buildDataModel(trainingUsers);
+
+ DataModel trainingModel = dataModelBuilder == null ? new GenericDataModel(trainingUsers)
+ : dataModelBuilder.buildDataModel(trainingUsers);
Recommender recommender = recommenderBuilder.buildRecommender(trainingModel);
-
+
try {
trainingModel.getPreferencesFromUser(userID);
} catch (NoSuchUserException nsee) {
continue; // Oops we excluded all prefs for the user -- just move on
}
-
+
int intersectionSize = 0;
List<RecommendedItem> recommendedItems = recommender.recommend(userID, at, rescorer);
for (RecommendedItem recommendedItem : recommendedItems) {
@@ -151,22 +154,22 @@
}
recall.addDatum((double) intersectionSize / (double) numRelevantItems);
if (numRelevantItems < size) {
- fallOut.addDatum((double) (numRecommendedItems - intersectionSize) /
- (double) (numItems - numRelevantItems));
+ fallOut.addDatum((double) (numRecommendedItems - intersectionSize)
+ / (double) (numItems - numRelevantItems));
}
-
+
long end = System.currentTimeMillis();
- log.info("Evaluated with user {} in {}ms", userID, (end-start));
- log.info("Precision/recall/fall-out: {} / {} / {}", new Object[]{
- precision.getAverage(), recall.getAverage(), fallOut.getAverage()
- });
+ GenericRecommenderIRStatsEvaluator.log
+ .info("Evaluated with user {} in {}ms", userID, (end - start));
+ GenericRecommenderIRStatsEvaluator.log.info("Precision/recall/fall-out: {} / {} / {}",
+ new Object[] {precision.getAverage(), recall.getAverage(), fallOut.getAverage()});
}
}
}
-
+
return new IRStatisticsImpl(precision.getAverage(), recall.getAverage(), fallOut.getAverage());
}
-
+
private static void processOtherUser(long id,
FastIDSet relevantItemIDs,
FastByIDMap<PreferenceArray> trainingUsers,
@@ -185,13 +188,13 @@
}
}
if (!prefs2.isEmpty()) {
- trainingUsers.put(userID2, new GenericUserPreferenceArray(prefs2));
+ trainingUsers.put(userID2, new GenericUserPreferenceArray(prefs2));
}
} else {
trainingUsers.put(userID2, prefs2Array);
}
}
-
+
private static double computeThreshold(PreferenceArray prefs) {
if (prefs.length() < 2) {
// Not enough data points -- return a threshold that allows everything
@@ -204,5 +207,5 @@
}
return stdDev.getAverage() + stdDev.getStandardDeviation();
}
-
+
}
Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/IRStatisticsImpl.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/IRStatisticsImpl.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/IRStatisticsImpl.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/IRStatisticsImpl.java Sat Feb 13 20:54:05 2010
@@ -17,60 +17,60 @@
package org.apache.mahout.cf.taste.impl.eval;
-import org.apache.mahout.cf.taste.eval.IRStatistics;
-
import java.io.Serializable;
-public final class IRStatisticsImpl implements IRStatistics, Serializable {
+import org.apache.mahout.cf.taste.eval.IRStatistics;
+public final class IRStatisticsImpl implements IRStatistics, Serializable {
+
private final double precision;
private final double recall;
private final double fallOut;
-
+
IRStatisticsImpl(double precision, double recall, double fallOut) {
- if (precision < 0.0 || precision > 1.0) {
+ if ((precision < 0.0) || (precision > 1.0)) {
throw new IllegalArgumentException("Illegal precision: " + precision);
}
- if (recall < 0.0 || recall > 1.0) {
+ if ((recall < 0.0) || (recall > 1.0)) {
throw new IllegalArgumentException("Illegal recall: " + recall);
}
- if (fallOut < 0.0 || fallOut > 1.0) {
+ if ((fallOut < 0.0) || (fallOut > 1.0)) {
throw new IllegalArgumentException("Illegal fallOut: " + fallOut);
}
this.precision = precision;
this.recall = recall;
this.fallOut = fallOut;
}
-
+
@Override
public double getPrecision() {
return precision;
}
-
+
@Override
public double getRecall() {
return recall;
}
-
+
@Override
public double getFallOut() {
return fallOut;
}
-
+
@Override
public double getF1Measure() {
return getFNMeasure(1.0);
}
-
+
@Override
public double getFNMeasure(double n) {
double sum = n * precision + recall;
return sum == 0.0 ? Double.NaN : (1.0 + n) * precision * recall / sum;
}
-
+
@Override
public String toString() {
return "IRStatisticsImpl[precision:" + precision + ",recall:" + recall + ",fallOut:" + fallOut + ']';
}
-
+
}
\ No newline at end of file
Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/LoadEvaluator.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/LoadEvaluator.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/LoadEvaluator.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/LoadEvaluator.java Sat Feb 13 20:54:05 2010
@@ -17,30 +17,29 @@
package org.apache.mahout.cf.taste.impl.eval;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.concurrent.Callable;
+
import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;
import org.apache.mahout.cf.taste.impl.common.SamplingLongPrimitiveIterator;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.recommender.Recommender;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.concurrent.Callable;
-
/**
* Simple helper class for running load on a Recommender.
*/
public final class LoadEvaluator {
-
- private LoadEvaluator() {
- }
-
+
+ private LoadEvaluator() { }
+
public static void runLoad(Recommender recommender) throws TasteException {
DataModel dataModel = recommender.getDataModel();
int numUsers = dataModel.getNumUsers();
double sampleRate = 1000.0 / numUsers;
- LongPrimitiveIterator userSampler =
- SamplingLongPrimitiveIterator.maybeWrapIterator(dataModel.getUserIDs(), sampleRate);
+ LongPrimitiveIterator userSampler = SamplingLongPrimitiveIterator.maybeWrapIterator(dataModel
+ .getUserIDs(), sampleRate);
recommender.recommend(userSampler.next(), 10); // Warm up
Collection<Callable<Void>> callables = new ArrayList<Callable<Void>>();
while (userSampler.hasNext()) {
@@ -48,22 +47,22 @@
}
AbstractDifferenceRecommenderEvaluator.execute(callables);
}
-
+
private static class LoadCallable implements Callable<Void> {
-
+
private final Recommender recommender;
private final long userID;
-
+
private LoadCallable(Recommender recommender, long userID) {
this.recommender = recommender;
this.userID = userID;
}
-
+
@Override
public Void call() throws Exception {
recommender.recommend(userID, 10);
return null;
}
}
-
+
}
\ No newline at end of file
Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/RMSRecommenderEvaluator.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/RMSRecommenderEvaluator.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/RMSRecommenderEvaluator.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/RMSRecommenderEvaluator.java Sat Feb 13 20:54:05 2010
@@ -22,33 +22,35 @@
import org.apache.mahout.cf.taste.model.Preference;
/**
- * <p>A {@link org.apache.mahout.cf.taste.eval.RecommenderEvaluator} which computes the "root mean squared" difference
- * between predicted and actual ratings for users. This is the square root of the average of this difference,
- * squared.</p>
+ * <p>
+ * A {@link org.apache.mahout.cf.taste.eval.RecommenderEvaluator} which computes the "root mean squared"
+ * difference between predicted and actual ratings for users. This is the square root of the average of this
+ * difference, squared.
+ * </p>
*/
public final class RMSRecommenderEvaluator extends AbstractDifferenceRecommenderEvaluator {
-
+
private RunningAverage average;
-
+
@Override
void reset() {
average = new FullRunningAverage();
}
-
+
@Override
void processOneEstimate(float estimatedPreference, Preference realPref) {
double diff = realPref.getValue() - estimatedPreference;
average.addDatum(diff * diff);
}
-
+
@Override
double computeFinalEvaluation() {
return Math.sqrt(average.getAverage());
}
-
+
@Override
public String toString() {
return "RMSRecommenderEvaluator";
}
-
+
}
Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/AbstractIDMigrator.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/AbstractIDMigrator.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/AbstractIDMigrator.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/AbstractIDMigrator.java Sat Feb 13 20:54:05 2010
@@ -17,19 +17,19 @@
package org.apache.mahout.cf.taste.impl.model;
-import org.apache.mahout.cf.taste.common.TasteException;
-import org.apache.mahout.cf.taste.model.IDMigrator;
-
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
-public abstract class AbstractIDMigrator implements IDMigrator {
+import org.apache.mahout.cf.taste.common.TasteException;
+import org.apache.mahout.cf.taste.model.IDMigrator;
+public abstract class AbstractIDMigrator implements IDMigrator {
+
private static final Charset UTF8_CHARSET = Charset.forName("UTF8");
-
+
private final MessageDigest md5Digest;
-
+
protected AbstractIDMigrator() {
try {
md5Digest = MessageDigest.getInstance("MD5");
@@ -38,33 +38,33 @@
throw new IllegalStateException(nsae);
}
}
-
+
/**
* @return most significant 8 bytes of the MD5 hash of the string, as a long
*/
protected final long hash(String value) {
byte[] md5hash;
synchronized (md5Digest) {
- md5hash = md5Digest.digest(value.getBytes(UTF8_CHARSET));
+ md5hash = md5Digest.digest(value.getBytes(AbstractIDMigrator.UTF8_CHARSET));
md5Digest.reset();
}
long hash = 0L;
for (int i = 0; i < 8; i++) {
- hash = (hash << 8) | (md5hash[i] & 0x00000000000000FFL);
+ hash = hash << 8 | md5hash[i] & 0x00000000000000FFL;
}
return hash;
}
-
+
@Override
public long toLongID(String stringID) {
return hash(stringID);
}
-
+
@Override
public void initialize(Iterable<String> stringIDs) throws TasteException {
for (String stringID : stringIDs) {
storeMapping(toLongID(stringID), stringID);
}
}
-
+
}
\ No newline at end of file
Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/AbstractJDBCIDMigrator.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/AbstractJDBCIDMigrator.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/AbstractJDBCIDMigrator.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/AbstractJDBCIDMigrator.java Sat Feb 13 20:54:05 2010
@@ -17,45 +17,45 @@
package org.apache.mahout.cf.taste.impl.model;
-import org.apache.mahout.cf.taste.common.TasteException;
-import org.apache.mahout.common.IOUtils;
-
-import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import javax.sql.DataSource;
+
+import org.apache.mahout.cf.taste.common.TasteException;
+import org.apache.mahout.common.IOUtils;
+
/**
- * Implementation which stores the reverse long-to-String mapping
- * in a database. Subclasses can override and configure the class to
- * operate with particular databases by supplying appropriate SQL
- * statements to the constructor.
+ * Implementation which stores the reverse long-to-String mapping in a database. Subclasses can override and
+ * configure the class to operate with particular databases by supplying appropriate SQL statements to the
+ * constructor.
*/
public abstract class AbstractJDBCIDMigrator extends AbstractIDMigrator {
-
+
public static final String DEFAULT_MAPPING_TABLE = "taste_id_mapping";
public static final String DEFAULT_LONG_ID_COLUMN = "long_id";
public static final String DEFAULT_STRING_ID_COLUMN = "string_id";
-
+
private final DataSource dataSource;
private final String getStringIDSQL;
private final String storeMappingSQL;
-
+
/**
- * @param getStringIDSQL SQL statement which selects one column, the String ID, from a
- * mapping table. The statement should take one long parameter.
- * @param storeMappingSQL SQL statement which saves a mapping from long to String.
- * It should take two parameters, a long and a String.
+ * @param getStringIDSQL
+ * SQL statement which selects one column, the String ID, from a mapping table. The statement
+ * should take one long parameter.
+ * @param storeMappingSQL
+ * SQL statement which saves a mapping from long to String. It should take two parameters, a long
+ * and a String.
*/
- protected AbstractJDBCIDMigrator(DataSource dataSource,
- String getStringIDSQL,
- String storeMappingSQL) {
+ protected AbstractJDBCIDMigrator(DataSource dataSource, String getStringIDSQL, String storeMappingSQL) {
this.dataSource = dataSource;
this.getStringIDSQL = getStringIDSQL;
this.storeMappingSQL = storeMappingSQL;
}
-
+
@Override
public final void storeMapping(long longID, String stringID) throws TasteException {
Connection conn = null;
@@ -72,7 +72,7 @@
IOUtils.quietClose(null, stmt, conn);
}
}
-
+
@Override
public final String toStringID(long longID) throws TasteException {
Connection conn = null;
@@ -96,5 +96,5 @@
IOUtils.quietClose(rs, stmt, conn);
}
}
-
+
}
\ No newline at end of file
Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanItemPreferenceArray.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanItemPreferenceArray.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanItemPreferenceArray.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanItemPreferenceArray.java Sat Feb 13 20:54:05 2010
@@ -17,34 +17,36 @@
package org.apache.mahout.cf.taste.impl.model;
-import org.apache.mahout.cf.taste.model.Preference;
-import org.apache.mahout.cf.taste.model.PreferenceArray;
-
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
+import org.apache.mahout.cf.taste.model.Preference;
+import org.apache.mahout.cf.taste.model.PreferenceArray;
+
/**
- * <p>Like {@link BooleanUserPreferenceArray} but stores preferences for one item (all item IDs the same)
- * rather than one user.</p>
- *
+ * <p>
+ * Like {@link BooleanUserPreferenceArray} but stores preferences for one item (all item IDs the same) rather
+ * than one user.
+ * </p>
+ *
* @see BooleanPreference
* @see BooleanUserPreferenceArray
* @see GenericItemPreferenceArray
*/
public final class BooleanItemPreferenceArray implements PreferenceArray {
-
+
private final long[] IDs;
private long id;
-
+
public BooleanItemPreferenceArray(int size) {
if (size < 1) {
throw new IllegalArgumentException("size is less than 1");
}
this.IDs = new long[size];
}
-
+
public BooleanItemPreferenceArray(List<Preference> prefs, boolean forOneUser) {
this(prefs.size());
for (int i = 0; i < prefs.size(); i++) {
@@ -53,7 +55,7 @@
}
id = forOneUser ? prefs.get(0).getUserID() : prefs.get(0).getItemID();
}
-
+
/**
* This is a private copy constructor for clone().
*/
@@ -61,75 +63,72 @@
this.IDs = IDs;
this.id = id;
}
-
+
@Override
public int length() {
return IDs.length;
}
-
+
@Override
public Preference get(int i) {
return new PreferenceView(i);
}
-
+
@Override
public void set(int i, Preference pref) {
id = pref.getItemID();
IDs[i] = pref.getUserID();
}
-
+
@Override
public long getUserID(int i) {
return IDs[i];
}
-
+
@Override
public void setUserID(int i, long userID) {
IDs[i] = userID;
}
-
+
@Override
public long getItemID(int i) {
return id;
}
-
+
/**
* {@inheritDoc}
- *
+ *
* Note that this method will actually set the item ID for <em>all</em> preferences.
*/
@Override
public void setItemID(int i, long itemID) {
id = itemID;
}
-
+
@Override
public float getValue(int i) {
return 1.0f;
}
-
+
@Override
public void setValue(int i, float value) {
throw new UnsupportedOperationException();
}
-
+
@Override
public void sortByUser() {
Arrays.sort(IDs);
}
-
+
@Override
- public void sortByItem() {
- }
-
+ public void sortByItem() { }
+
@Override
- public void sortByValue() {
- }
-
+ public void sortByValue() { }
+
@Override
- public void sortByValueReversed() {
- }
-
+ public void sortByValueReversed() { }
+
@Override
public boolean hasPrefWithUserID(long userID) {
for (long id : IDs) {
@@ -139,28 +138,30 @@
}
return false;
}
-
+
@Override
public boolean hasPrefWithItemID(long itemID) {
return id == itemID;
}
-
+
@Override
public BooleanItemPreferenceArray clone() {
return new BooleanItemPreferenceArray(IDs.clone(), id);
}
-
+
@Override
public Iterator<Preference> iterator() {
return new PreferenceArrayIterator();
}
-
+
private final class PreferenceArrayIterator implements Iterator<Preference> {
private int i = 0;
+
@Override
public boolean hasNext() {
return i < length();
}
+
@Override
public Preference next() {
if (i >= length()) {
@@ -168,40 +169,41 @@
}
return new PreferenceView(i++);
}
+
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
-
+
private final class PreferenceView implements Preference {
-
+
private final int i;
-
+
private PreferenceView(int i) {
this.i = i;
}
-
+
@Override
public long getUserID() {
return BooleanItemPreferenceArray.this.getUserID(i);
}
-
+
@Override
public long getItemID() {
return BooleanItemPreferenceArray.this.getItemID(i);
}
-
+
@Override
public float getValue() {
return 1.0f;
}
-
+
@Override
public void setValue(float value) {
throw new UnsupportedOperationException();
}
-
+
}
-
+
}
\ No newline at end of file
Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanPreference.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanPreference.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanPreference.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanPreference.java Sat Feb 13 20:54:05 2010
@@ -17,48 +17,48 @@
package org.apache.mahout.cf.taste.impl.model;
-import org.apache.mahout.cf.taste.model.Preference;
-
import java.io.Serializable;
+import org.apache.mahout.cf.taste.model.Preference;
+
/**
- * Encapsulates a simple boolean "preference" for an item whose value does not matter (is fixed at 1.0). This is
- * appropriate in situations where users conceptually have only a general "yes" preference for items, rather than a
- * spectrum of preference values.
+ * Encapsulates a simple boolean "preference" for an item whose value does not matter (is fixed at 1.0). This
+ * is appropriate in situations where users conceptually have only a general "yes" preference for items,
+ * rather than a spectrum of preference values.
*/
public final class BooleanPreference implements Preference, Serializable {
-
+
private final long userID;
private final long itemID;
-
+
public BooleanPreference(long userID, long itemID) {
this.userID = userID;
this.itemID = itemID;
}
-
+
@Override
public long getUserID() {
return userID;
}
-
+
@Override
public long getItemID() {
return itemID;
}
-
+
@Override
public float getValue() {
return 1.0f;
}
-
+
@Override
public void setValue(float value) {
throw new UnsupportedOperationException();
}
-
+
@Override
public String toString() {
return "BooleanPreference[userID: " + userID + ", itemID:" + itemID + ']';
}
-
+
}
\ No newline at end of file
Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanUserPreferenceArray.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanUserPreferenceArray.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanUserPreferenceArray.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanUserPreferenceArray.java Sat Feb 13 20:54:05 2010
@@ -17,34 +17,36 @@
package org.apache.mahout.cf.taste.impl.model;
-import org.apache.mahout.cf.taste.model.Preference;
-import org.apache.mahout.cf.taste.model.PreferenceArray;
-
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
+import org.apache.mahout.cf.taste.model.Preference;
+import org.apache.mahout.cf.taste.model.PreferenceArray;
+
/**
- * <p>Like {@link GenericUserPreferenceArray} but stores, conceptually, {@link BooleanPreference} objects
- * which have no associated preference value.</p>
+ * <p>
+ * Like {@link GenericUserPreferenceArray} but stores, conceptually, {@link BooleanPreference} objects which
+ * have no associated preference value.
+ * </p>
*
* @see BooleanPreference
* @see BooleanItemPreferenceArray
* @see GenericUserPreferenceArray
*/
public final class BooleanUserPreferenceArray implements PreferenceArray {
-
+
private final long[] IDs;
private long id;
-
+
public BooleanUserPreferenceArray(int size) {
if (size < 1) {
throw new IllegalArgumentException("size is less than 1");
}
this.IDs = new long[size];
}
-
+
public BooleanUserPreferenceArray(List<Preference> prefs) {
this(prefs.size());
for (int i = 0; i < prefs.size(); i++) {
@@ -53,7 +55,7 @@
}
id = prefs.get(0).getUserID();
}
-
+
/**
* This is a private copy constructor for clone().
*/
@@ -61,80 +63,77 @@
this.IDs = IDs;
this.id = id;
}
-
+
@Override
public int length() {
return IDs.length;
}
-
+
@Override
public Preference get(int i) {
return new PreferenceView(i);
}
-
+
@Override
public void set(int i, Preference pref) {
id = pref.getUserID();
IDs[i] = pref.getItemID();
}
-
+
@Override
public long getUserID(int i) {
return id;
}
-
+
/**
* {@inheritDoc}
- *
+ *
* Note that this method will actually set the user ID for <em>all</em> preferences.
*/
@Override
public void setUserID(int i, long userID) {
id = userID;
}
-
+
@Override
public long getItemID(int i) {
return IDs[i];
}
-
+
@Override
public void setItemID(int i, long itemID) {
IDs[i] = itemID;
}
-
+
@Override
public float getValue(int i) {
return 1.0f;
}
-
+
@Override
public void setValue(int i, float value) {
throw new UnsupportedOperationException();
}
-
+
@Override
- public void sortByUser() {
- }
-
+ public void sortByUser() { }
+
@Override
public void sortByItem() {
Arrays.sort(IDs);
}
-
+
@Override
- public void sortByValue() {
- }
-
+ public void sortByValue() { }
+
@Override
- public void sortByValueReversed() {
- }
-
+ public void sortByValueReversed() { }
+
@Override
public boolean hasPrefWithUserID(long userID) {
return id == userID;
}
-
+
@Override
public boolean hasPrefWithItemID(long itemID) {
for (long id : IDs) {
@@ -144,23 +143,25 @@
}
return false;
}
-
+
@Override
public BooleanUserPreferenceArray clone() {
return new BooleanUserPreferenceArray(IDs.clone(), id);
}
-
+
@Override
public Iterator<Preference> iterator() {
return new PreferenceArrayIterator();
}
-
+
private final class PreferenceArrayIterator implements Iterator<Preference> {
private int i = 0;
+
@Override
public boolean hasNext() {
return i < length();
}
+
@Override
public Preference next() {
if (i >= length()) {
@@ -168,40 +169,41 @@
}
return new PreferenceView(i++);
}
+
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
-
+
private final class PreferenceView implements Preference {
-
+
private final int i;
-
+
private PreferenceView(int i) {
this.i = i;
}
-
+
@Override
public long getUserID() {
return BooleanUserPreferenceArray.this.getUserID(i);
}
-
+
@Override
public long getItemID() {
return BooleanUserPreferenceArray.this.getItemID(i);
}
-
+
@Override
public float getValue() {
return 1.0f;
}
-
+
@Override
public void setValue(float value) {
throw new UnsupportedOperationException();
}
-
+
}
-
+
}
\ No newline at end of file
Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericBooleanPrefDataModel.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericBooleanPrefDataModel.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericBooleanPrefDataModel.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericBooleanPrefDataModel.java Sat Feb 13 20:54:05 2010
@@ -17,6 +17,12 @@
package org.apache.mahout.cf.taste.impl.model;
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
import org.apache.mahout.cf.taste.common.NoSuchItemException;
import org.apache.mahout.cf.taste.common.NoSuchUserException;
import org.apache.mahout.cf.taste.common.Refreshable;
@@ -28,39 +34,37 @@
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.model.PreferenceArray;
-import java.io.Serializable;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
/**
- * <p>A simple {@link DataModel} which uses a given {@link List} of users as its data source. This
- * implementation is mostly useful for small experiments and is not recommended for contexts where performance is
- * important.</p>
+ * <p>
+ * A simple {@link DataModel} which uses a given {@link List} of users as its data source. This implementation
+ * is mostly useful for small experiments and is not recommended for contexts where performance is important.
+ * </p>
*/
public final class GenericBooleanPrefDataModel implements DataModel, Serializable {
-
+
private final long[] userIDs;
private final FastByIDMap<FastIDSet> preferenceFromUsers;
private final long[] itemIDs;
private final FastByIDMap<FastIDSet> preferenceForItems;
-
+
/**
- * <p>Creates a new {@link GenericDataModel} from the given users (and their preferences). This {@link
- * DataModel} retains all this information in memory and is effectively immutable.</p>
- *
- * @param userData users to include
+ * <p>
+ * Creates a new {@link GenericDataModel} from the given users (and their preferences). This
+ * {@link DataModel} retains all this information in memory and is effectively immutable.
+ * </p>
+ *
+ * @param userData
+ * users to include
*/
public GenericBooleanPrefDataModel(FastByIDMap<FastIDSet> userData) {
if (userData == null) {
throw new IllegalArgumentException("userData is null");
}
-
+
this.preferenceFromUsers = userData;
this.preferenceForItems = new FastByIDMap<FastIDSet>();
FastIDSet itemIDSet = new FastIDSet();
- for (Map.Entry<Long, FastIDSet> entry : preferenceFromUsers.entrySet()) {
+ for (Map.Entry<Long,FastIDSet> entry : preferenceFromUsers.entrySet()) {
long userID = entry.getKey();
FastIDSet itemIDs = entry.getValue();
itemIDSet.addAll(itemIDs);
@@ -75,11 +79,11 @@
userIDs.add(userID);
}
}
-
+
this.itemIDs = itemIDSet.toArray();
itemIDSet = null; // Might help GC -- this is big
Arrays.sort(itemIDs);
-
+
this.userIDs = new long[userData.size()];
int i = 0;
LongPrimitiveIterator it = userData.keySetIterator();
@@ -87,20 +91,24 @@
userIDs[i++] = it.next();
}
Arrays.sort(userIDs);
-
+
}
-
+
/**
- * <p>Creates a new {@link GenericDataModel} containing an immutable copy of the data from another given {@link
- * DataModel}.</p>
- *
- * @param dataModel {@link DataModel} to copy
- * @throws TasteException if an error occurs while retrieving the other {@link DataModel}'s users
+ * <p>
+ * Creates a new {@link GenericDataModel} containing an immutable copy of the data from another given
+ * {@link DataModel}.
+ * </p>
+ *
+ * @param dataModel
+ * {@link DataModel} to copy
+ * @throws TasteException
+ * if an error occurs while retrieving the other {@link DataModel}'s users
*/
public GenericBooleanPrefDataModel(DataModel dataModel) throws TasteException {
- this(toDataMap(dataModel));
+ this(GenericBooleanPrefDataModel.toDataMap(dataModel));
}
-
+
private static FastByIDMap<FastIDSet> toDataMap(DataModel dataModel) throws TasteException {
FastByIDMap<FastIDSet> data = new FastByIDMap<FastIDSet>(dataModel.getNumUsers());
LongPrimitiveIterator it = dataModel.getUserIDs();
@@ -110,9 +118,9 @@
}
return data;
}
-
+
public static FastByIDMap<FastIDSet> toDataMap(FastByIDMap<PreferenceArray> data) {
- for (Map.Entry<Long, Object> entry : ((FastByIDMap<Object>) (FastByIDMap<?>) data).entrySet()) {
+ for (Map.Entry<Long,Object> entry : ((FastByIDMap<Object>) (FastByIDMap<?>) data).entrySet()) {
PreferenceArray prefArray = (PreferenceArray) entry.getValue();
int size = prefArray.length();
FastIDSet itemIDs = new FastIDSet(size);
@@ -123,20 +131,23 @@
}
return (FastByIDMap<FastIDSet>) (FastByIDMap<?>) data;
}
-
+
/**
* This is used mostly internally to the framework, and shouldn't be relied upon otherwise.
*/
public FastByIDMap<FastIDSet> getRawUserData() {
return this.preferenceFromUsers;
}
-
+
@Override
public LongPrimitiveArrayIterator getUserIDs() {
return new LongPrimitiveArrayIterator(userIDs);
}
-
- /** @throws NoSuchUserException if there is no such user */
+
+ /**
+ * @throws NoSuchUserException
+ * if there is no such user
+ */
@Override
public PreferenceArray getPreferencesFromUser(long userID) throws NoSuchUserException {
FastIDSet itemIDs = preferenceFromUsers.get(userID);
@@ -153,7 +164,7 @@
}
return prefArray;
}
-
+
@Override
public FastIDSet getItemIDsFromUser(long userID) throws TasteException {
FastIDSet itemIDs = preferenceFromUsers.get(userID);
@@ -162,12 +173,12 @@
}
return itemIDs;
}
-
+
@Override
public LongPrimitiveArrayIterator getItemIDs() {
return new LongPrimitiveArrayIterator(itemIDs);
}
-
+
@Override
public PreferenceArray getPreferencesForItem(long itemID) throws NoSuchItemException {
FastIDSet userIDs = preferenceForItems.get(itemID);
@@ -184,7 +195,7 @@
}
return prefArray;
}
-
+
@Override
public Float getPreferenceValue(long userID, long itemID) throws NoSuchUserException {
FastIDSet itemIDs = preferenceFromUsers.get(userID);
@@ -196,17 +207,17 @@
}
return null;
}
-
+
@Override
public int getNumItems() {
return itemIDs.length;
}
-
+
@Override
public int getNumUsers() {
return userIDs.length;
}
-
+
@Override
public int getNumUsersWithPreferenceFor(long... itemIDs) throws NoSuchItemException {
if (itemIDs.length == 0) {
@@ -219,7 +230,7 @@
FastIDSet intersection = new FastIDSet(userIDs.size());
intersection.addAll(userIDs);
int i = 1;
- while (!intersection.isEmpty() && i < itemIDs.length) {
+ while (!intersection.isEmpty() && (i < itemIDs.length)) {
userIDs = preferenceForItems.get(itemIDs[i]);
if (userIDs == null) {
throw new NoSuchItemException();
@@ -229,22 +240,22 @@
}
return intersection.size();
}
-
+
@Override
public void removePreference(long userID, long itemID) {
throw new UnsupportedOperationException();
}
-
+
@Override
public void setPreference(long userID, long itemID, float value) {
throw new UnsupportedOperationException();
}
-
+
@Override
public void refresh(Collection<Refreshable> alreadyRefreshed) {
- // Does nothing
+ // Does nothing
}
-
+
@Override
public String toString() {
StringBuilder result = new StringBuilder(200);
@@ -261,5 +272,5 @@
result.append(']');
return result.toString();
}
-
+
}
Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericDataModel.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericDataModel.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericDataModel.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericDataModel.java Sat Feb 13 20:54:05 2010
@@ -17,6 +17,13 @@
package org.apache.mahout.cf.taste.impl.model;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
import org.apache.mahout.cf.taste.common.NoSuchItemException;
import org.apache.mahout.cf.taste.common.NoSuchUserException;
import org.apache.mahout.cf.taste.common.Refreshable;
@@ -31,44 +38,41 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
/**
- * <p>A simple {@link DataModel} which uses a given {@link List} of users as its data source. This
- * implementation is mostly useful for small experiments and is not recommended for contexts where performance is
- * important.</p>
+ * <p>
+ * A simple {@link DataModel} which uses a given {@link List} of users as its data source. This implementation
+ * is mostly useful for small experiments and is not recommended for contexts where performance is important.
+ * </p>
*/
public final class GenericDataModel implements DataModel, Serializable {
-
+
private static final Logger log = LoggerFactory.getLogger(GenericDataModel.class);
-
+
private final long[] userIDs;
private final FastByIDMap<PreferenceArray> preferenceFromUsers;
private final long[] itemIDs;
private final FastByIDMap<PreferenceArray> preferenceForItems;
-
+
/**
- * <p>Creates a new {@link GenericDataModel} from the given users (and their preferences). This {@link
- * DataModel} retains all this information in memory and is effectively immutable.</p>
- *
- * @param userData users to include in this {@link GenericDataModel}
- * (see also {@link #toDataMap(FastByIDMap, boolean)})
+ * <p>
+ * Creates a new {@link GenericDataModel} from the given users (and their preferences). This
+ * {@link DataModel} retains all this information in memory and is effectively immutable.
+ * </p>
+ *
+ * @param userData
+ * users to include in this {@link GenericDataModel} (see also
+ * {@link #toDataMap(FastByIDMap, boolean)})
*/
public GenericDataModel(FastByIDMap<PreferenceArray> userData) {
if (userData == null) {
throw new IllegalArgumentException("userData is null");
}
-
+
this.preferenceFromUsers = userData;
FastByIDMap<Collection<Preference>> prefsForItems = new FastByIDMap<Collection<Preference>>();
FastIDSet itemIDSet = new FastIDSet();
int currentCount = 0;
- for (Map.Entry<Long, PreferenceArray> entry : preferenceFromUsers.entrySet()) {
+ for (Map.Entry<Long,PreferenceArray> entry : preferenceFromUsers.entrySet()) {
PreferenceArray prefs = entry.getValue();
prefs.sortByItem();
for (Preference preference : prefs) {
@@ -82,21 +86,21 @@
prefsForItem.add(preference);
}
if (++currentCount % 10000 == 0) {
- log.info("Processed {} users", currentCount);
+ GenericDataModel.log.info("Processed {} users", currentCount);
}
}
- log.info("Processed {} users", currentCount);
-
+ GenericDataModel.log.info("Processed {} users", currentCount);
+
this.itemIDs = itemIDSet.toArray();
itemIDSet = null; // Might help GC -- this is big
Arrays.sort(itemIDs);
-
- this.preferenceForItems = toDataMap(prefsForItems, false);
-
- for (Map.Entry<Long, PreferenceArray> entry : preferenceForItems.entrySet()) {
+
+ this.preferenceForItems = GenericDataModel.toDataMap(prefsForItems, false);
+
+ for (Map.Entry<Long,PreferenceArray> entry : preferenceForItems.entrySet()) {
entry.getValue().sortByUser();
}
-
+
this.userIDs = new long[userData.size()];
int i = 0;
LongPrimitiveIterator it = userData.keySetIterator();
@@ -105,31 +109,37 @@
}
Arrays.sort(userIDs);
}
-
+
/**
- * <p>Creates a new {@link GenericDataModel} containing an immutable copy of the data from another given {@link
- * DataModel}.</p>
- *
- * @param dataModel {@link DataModel} to copy
- * @throws TasteException if an error occurs while retrieving the other {@link DataModel}'s users
+ * <p>
+ * Creates a new {@link GenericDataModel} containing an immutable copy of the data from another given
+ * {@link DataModel}.
+ * </p>
+ *
+ * @param dataModel
+ * {@link DataModel} to copy
+ * @throws TasteException
+ * if an error occurs while retrieving the other {@link DataModel}'s users
*/
public GenericDataModel(DataModel dataModel) throws TasteException {
- this(toDataMap(dataModel));
+ this(GenericDataModel.toDataMap(dataModel));
}
-
+
/**
- * Swaps, in-place, {@link List}s for arrays in {@link Map} values
- * .
+ * Swaps, in-place, {@link List}s for arrays in {@link Map} values .
+ *
* @return input value
*/
- public static FastByIDMap<PreferenceArray> toDataMap(FastByIDMap<Collection<Preference>> data, boolean byUser) {
- for (Map.Entry<Long, Object> entry : ((FastByIDMap<Object>) (FastByIDMap<?>) data).entrySet()) {
+ public static FastByIDMap<PreferenceArray> toDataMap(FastByIDMap<Collection<Preference>> data,
+ boolean byUser) {
+ for (Map.Entry<Long,Object> entry : ((FastByIDMap<Object>) (FastByIDMap<?>) data).entrySet()) {
List<Preference> prefList = (List<Preference>) entry.getValue();
- entry.setValue(byUser ? new GenericUserPreferenceArray(prefList) : new GenericItemPreferenceArray(prefList));
+ entry.setValue(byUser ? new GenericUserPreferenceArray(prefList) : new GenericItemPreferenceArray(
+ prefList));
}
return (FastByIDMap<PreferenceArray>) (FastByIDMap<?>) data;
}
-
+
private static FastByIDMap<PreferenceArray> toDataMap(DataModel dataModel) throws TasteException {
FastByIDMap<PreferenceArray> data = new FastByIDMap<PreferenceArray>(dataModel.getNumUsers());
LongPrimitiveIterator it = dataModel.getUserIDs();
@@ -139,20 +149,23 @@
}
return data;
}
-
+
/**
* This is used mostly internally to the framework, and shouldn't be relied upon otherwise.
*/
public FastByIDMap<PreferenceArray> getRawUserData() {
return this.preferenceFromUsers;
}
-
+
@Override
public LongPrimitiveArrayIterator getUserIDs() {
return new LongPrimitiveArrayIterator(userIDs);
}
-
- /** @throws NoSuchUserException if there is no such user */
+
+ /**
+ * @throws NoSuchUserException
+ * if there is no such user
+ */
@Override
public PreferenceArray getPreferencesFromUser(long userID) throws NoSuchUserException {
PreferenceArray prefs = preferenceFromUsers.get(userID);
@@ -161,7 +174,7 @@
}
return prefs;
}
-
+
@Override
public FastIDSet getItemIDsFromUser(long userID) throws TasteException {
PreferenceArray prefs = getPreferencesFromUser(userID);
@@ -172,12 +185,12 @@
}
return result;
}
-
+
@Override
public LongPrimitiveArrayIterator getItemIDs() {
return new LongPrimitiveArrayIterator(itemIDs);
}
-
+
@Override
public PreferenceArray getPreferencesForItem(long itemID) throws NoSuchItemException {
PreferenceArray prefs = preferenceForItems.get(itemID);
@@ -186,7 +199,7 @@
}
return prefs;
}
-
+
@Override
public Float getPreferenceValue(long userID, long itemID) throws TasteException {
PreferenceArray prefs = getPreferencesFromUser(userID);
@@ -198,24 +211,24 @@
}
return null;
}
-
+
@Override
public int getNumItems() {
return itemIDs.length;
}
-
+
@Override
public int getNumUsers() {
return userIDs.length;
}
-
+
@Override
public int getNumUsersWithPreferenceFor(long... itemIDs) {
if (itemIDs == null) {
throw new IllegalArgumentException("itemIDs is null");
}
int length = itemIDs.length;
- if (length == 0 || length > 2) {
+ if ((length == 0) || (length > 2)) {
throw new IllegalArgumentException("Illegal number of item IDs: " + length);
}
if (length == 1) {
@@ -224,7 +237,7 @@
} else {
PreferenceArray prefs1 = preferenceForItems.get(itemIDs[0]);
PreferenceArray prefs2 = preferenceForItems.get(itemIDs[1]);
- if (prefs1 == null || prefs2 == null) {
+ if ((prefs1 == null) || (prefs2 == null)) {
return 0;
}
FastIDSet users1 = new FastIDSet(prefs1.length());
@@ -241,22 +254,22 @@
return users1.size();
}
}
-
+
@Override
public void removePreference(long userID, long itemID) {
throw new UnsupportedOperationException();
}
-
+
@Override
public void setPreference(long userID, long itemID, float value) {
throw new UnsupportedOperationException();
}
-
+
@Override
public void refresh(Collection<Refreshable> alreadyRefreshed) {
- // Does nothing
+ // Does nothing
}
-
+
@Override
public String toString() {
StringBuilder result = new StringBuilder(200);
@@ -273,5 +286,5 @@
result.append(']');
return result.toString();
}
-
+
}
Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericItemPreferenceArray.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericItemPreferenceArray.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericItemPreferenceArray.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericItemPreferenceArray.java Sat Feb 13 20:54:05 2010
@@ -17,31 +17,33 @@
package org.apache.mahout.cf.taste.impl.model;
-import org.apache.mahout.cf.taste.model.Preference;
-import org.apache.mahout.cf.taste.model.PreferenceArray;
-
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
+import org.apache.mahout.cf.taste.model.Preference;
+import org.apache.mahout.cf.taste.model.PreferenceArray;
+
/**
- * <p>Like {@link GenericUserPreferenceArray} but stores preferences for one item (all item IDs the same)
- * rather than one user.</p>
- *
+ * <p>
+ * Like {@link GenericUserPreferenceArray} but stores preferences for one item (all item IDs the same) rather
+ * than one user.
+ * </p>
+ *
* @see BooleanItemPreferenceArray
* @see GenericUserPreferenceArray
* @see GenericPreference
*/
public final class GenericItemPreferenceArray implements PreferenceArray {
-
+
private static final int USER = 0;
private static final int VALUE = 2;
private static final int VALUE_REVERSED = 3;
-
+
private final long[] IDs;
private long id;
private final float[] values;
-
+
public GenericItemPreferenceArray(int size) {
if (size < 1) {
throw new IllegalArgumentException("size is less than 1");
@@ -49,7 +51,7 @@
this.IDs = new long[size];
values = new float[size];
}
-
+
public GenericItemPreferenceArray(List<Preference> prefs) {
this(prefs.size());
for (int i = 0; i < prefs.size(); i++) {
@@ -59,7 +61,7 @@
}
id = prefs.get(0).getItemID();
}
-
+
/**
* This is a private copy constructor for clone().
*/
@@ -68,78 +70,77 @@
this.id = id;
this.values = values;
}
-
+
@Override
public int length() {
return IDs.length;
}
-
+
@Override
public Preference get(int i) {
return new PreferenceView(i);
}
-
+
@Override
public void set(int i, Preference pref) {
id = pref.getItemID();
IDs[i] = pref.getUserID();
values[i] = pref.getValue();
}
-
+
@Override
public long getUserID(int i) {
return IDs[i];
}
-
+
@Override
public void setUserID(int i, long userID) {
IDs[i] = userID;
}
-
+
@Override
public long getItemID(int i) {
return id;
}
-
+
/**
* {@inheritDoc}
- *
+ *
* Note that this method will actually set the item ID for <em>all</em> preferences.
*/
@Override
public void setItemID(int i, long itemID) {
id = itemID;
}
-
+
@Override
public float getValue(int i) {
return values[i];
}
-
+
@Override
public void setValue(int i, float value) {
values[i] = value;
}
-
+
@Override
public void sortByUser() {
- selectionSort(USER);
+ selectionSort(GenericItemPreferenceArray.USER);
}
-
+
+ @Override
+ public void sortByItem() { }
+
@Override
- public void sortByItem() {
- }
-
- @Override
public void sortByValue() {
- selectionSort(VALUE);
+ selectionSort(GenericItemPreferenceArray.VALUE);
}
-
+
@Override
public void sortByValueReversed() {
- selectionSort(VALUE_REVERSED);
+ selectionSort(GenericItemPreferenceArray.VALUE_REVERSED);
}
-
+
@Override
public boolean hasPrefWithUserID(long userID) {
for (long id : IDs) {
@@ -149,18 +150,18 @@
}
return false;
}
-
+
@Override
public boolean hasPrefWithItemID(long itemID) {
return id == itemID;
}
-
+
private void selectionSort(int type) {
// I think this sort will prove to be too dumb, but, it's in place and OK for tiny, mostly sorted data
int max = length();
boolean sorted = true;
for (int i = 1; i < max; i++) {
- if (isLess(i, i-1, type)) {
+ if (isLess(i, i - 1, type)) {
sorted = false;
break;
}
@@ -180,7 +181,7 @@
}
}
}
-
+
private boolean isLess(int i, int j, int type) {
switch (type) {
case USER:
@@ -193,7 +194,7 @@
throw new IllegalStateException();
}
}
-
+
private void swap(int i, int j) {
long temp1 = IDs[i];
float temp2 = values[i];
@@ -202,23 +203,25 @@
IDs[j] = temp1;
values[j] = temp2;
}
-
+
@Override
public GenericItemPreferenceArray clone() {
return new GenericItemPreferenceArray(IDs.clone(), id, values.clone());
}
-
+
@Override
public Iterator<Preference> iterator() {
return new PreferenceArrayIterator();
}
-
+
private final class PreferenceArrayIterator implements Iterator<Preference> {
private int i = 0;
+
@Override
public boolean hasNext() {
return i < length();
}
+
@Override
public Preference next() {
if (i >= length()) {
@@ -226,40 +229,41 @@
}
return new PreferenceView(i++);
}
+
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
-
+
private final class PreferenceView implements Preference {
-
+
private final int i;
-
+
private PreferenceView(int i) {
this.i = i;
}
-
+
@Override
public long getUserID() {
return GenericItemPreferenceArray.this.getUserID(i);
}
-
+
@Override
public long getItemID() {
return GenericItemPreferenceArray.this.getItemID(i);
}
-
+
@Override
public float getValue() {
return values[i];
}
-
+
@Override
public void setValue(float value) {
values[i] = value;
}
-
+
}
-
+
}
Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericPreference.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericPreference.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericPreference.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericPreference.java Sat Feb 13 20:54:05 2010
@@ -17,17 +17,21 @@
package org.apache.mahout.cf.taste.impl.model;
-import org.apache.mahout.cf.taste.model.Preference;
-
import java.io.Serializable;
-/** <p>A simple {@link Preference} encapsulating an item and preference value.</p> */
-public class GenericPreference implements Preference, Serializable {
+import org.apache.mahout.cf.taste.model.Preference;
+/**
+ * <p>
+ * A simple {@link Preference} encapsulating an item and preference value.
+ * </p>
+ */
+public class GenericPreference implements Preference, Serializable {
+
private final long userID;
private final long itemID;
private float value;
-
+
public GenericPreference(long userID, long itemID, float value) {
if (Float.isNaN(value)) {
throw new IllegalArgumentException("Invalid value: " + value);
@@ -36,22 +40,22 @@
this.itemID = itemID;
this.value = value;
}
-
+
@Override
public long getUserID() {
return userID;
}
-
+
@Override
public long getItemID() {
return itemID;
}
-
+
@Override
public float getValue() {
return value;
}
-
+
@Override
public void setValue(float value) {
if (Float.isNaN(value)) {
@@ -59,10 +63,10 @@
}
this.value = value;
}
-
+
@Override
public String toString() {
return "GenericPreference[userID: " + userID + ", itemID:" + itemID + ", value:" + value + ']';
}
-
+
}
Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericUserPreferenceArray.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericUserPreferenceArray.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericUserPreferenceArray.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericUserPreferenceArray.java Sat Feb 13 20:54:05 2010
@@ -17,32 +17,34 @@
package org.apache.mahout.cf.taste.impl.model;
-import org.apache.mahout.cf.taste.model.Preference;
-import org.apache.mahout.cf.taste.model.PreferenceArray;
-
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
+import org.apache.mahout.cf.taste.model.Preference;
+import org.apache.mahout.cf.taste.model.PreferenceArray;
+
/**
- * <p>This implementation maintains two parallel arrays, of user IDs and values. The idea is to save
- * allocating {@link Preference} objects themselves. This saves the overhead of {@link Preference} objects
- * but also duplicating the user ID value.</p>
- *
+ * <p>
+ * This implementation maintains two parallel arrays, of user IDs and values. The idea is to save allocating
+ * {@link Preference} objects themselves. This saves the overhead of {@link Preference} objects but also
+ * duplicating the user ID value.
+ * </p>
+ *
* @see BooleanUserPreferenceArray
* @see GenericItemPreferenceArray
* @see GenericPreference
*/
public final class GenericUserPreferenceArray implements PreferenceArray {
-
+
private static final int ITEM = 1;
private static final int VALUE = 2;
private static final int VALUE_REVERSED = 3;
-
+
private final long[] IDs;
private long id;
private final float[] values;
-
+
public GenericUserPreferenceArray(int size) {
if (size < 1) {
throw new IllegalArgumentException("size is less than 1");
@@ -50,7 +52,7 @@
this.IDs = new long[size];
values = new float[size];
}
-
+
public GenericUserPreferenceArray(List<Preference> prefs) {
this(prefs.size());
for (int i = 0; i < prefs.size(); i++) {
@@ -60,7 +62,7 @@
}
id = prefs.get(0).getUserID();
}
-
+
/**
* This is a private copy constructor for clone().
*/
@@ -69,83 +71,82 @@
this.id = id;
this.values = values;
}
-
+
@Override
public int length() {
return IDs.length;
}
-
+
@Override
public Preference get(int i) {
return new PreferenceView(i);
}
-
+
@Override
public void set(int i, Preference pref) {
id = pref.getUserID();
IDs[i] = pref.getItemID();
values[i] = pref.getValue();
}
-
+
@Override
public long getUserID(int i) {
return id;
}
-
+
/**
* {@inheritDoc}
- *
+ *
* Note that this method will actually set the user ID for <em>all</em> preferences.
*/
@Override
public void setUserID(int i, long userID) {
id = userID;
}
-
+
@Override
public long getItemID(int i) {
return IDs[i];
}
-
+
@Override
public void setItemID(int i, long itemID) {
IDs[i] = itemID;
}
-
+
@Override
public float getValue(int i) {
return values[i];
}
-
+
@Override
public void setValue(int i, float value) {
values[i] = value;
}
-
+
@Override
- public void sortByUser() {
- }
-
+ public void sortByUser() { }
+
@Override
public void sortByItem() {
- selectionSort(ITEM);
+ selectionSort(GenericUserPreferenceArray.ITEM);
}
-
+
@Override
public void sortByValue() {
- selectionSort(VALUE);
+ selectionSort(GenericUserPreferenceArray.VALUE);
}
-
+
@Override
public void sortByValueReversed() {
- selectionSort(VALUE_REVERSED);
+ selectionSort(GenericUserPreferenceArray.VALUE_REVERSED);
}
-
+
@Override
public boolean hasPrefWithUserID(long userID) {
return id == userID;
}
-
+
@Override
public boolean hasPrefWithItemID(long itemID) {
for (long id : IDs) {
@@ -155,13 +156,13 @@
}
return false;
}
-
+
private void selectionSort(int type) {
// I think this sort will prove to be too dumb, but, it's in place and OK for tiny, mostly sorted data
int max = length();
boolean sorted = true;
for (int i = 1; i < max; i++) {
- if (isLess(i, i-1, type)) {
+ if (isLess(i, i - 1, type)) {
sorted = false;
break;
}
@@ -181,7 +182,7 @@
}
}
}
-
+
private boolean isLess(int i, int j, int type) {
switch (type) {
case ITEM:
@@ -194,7 +195,7 @@
throw new IllegalStateException();
}
}
-
+
private void swap(int i, int j) {
long temp1 = IDs[i];
float temp2 = values[i];
@@ -203,23 +204,25 @@
IDs[j] = temp1;
values[j] = temp2;
}
-
+
@Override
public GenericUserPreferenceArray clone() {
return new GenericUserPreferenceArray(IDs.clone(), id, values.clone());
}
-
+
@Override
public Iterator<Preference> iterator() {
return new PreferenceArrayIterator();
}
-
+
private final class PreferenceArrayIterator implements Iterator<Preference> {
private int i = 0;
+
@Override
public boolean hasNext() {
return i < length();
}
+
@Override
public Preference next() {
if (i >= length()) {
@@ -227,40 +230,41 @@
}
return new PreferenceView(i++);
}
+
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
-
+
private final class PreferenceView implements Preference {
-
+
private final int i;
-
+
private PreferenceView(int i) {
this.i = i;
}
-
+
@Override
public long getUserID() {
return GenericUserPreferenceArray.this.getUserID(i);
}
-
+
@Override
public long getItemID() {
return GenericUserPreferenceArray.this.getItemID(i);
}
-
+
@Override
public float getValue() {
return values[i];
}
-
+
@Override
public void setValue(float value) {
values[i] = value;
}
-
+
}
-
+
}
\ No newline at end of file
Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/MemoryIDMigrator.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/MemoryIDMigrator.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/MemoryIDMigrator.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/MemoryIDMigrator.java Sat Feb 13 20:54:05 2010
@@ -20,29 +20,28 @@
import org.apache.mahout.cf.taste.impl.common.FastByIDMap;
/**
- * Implementation which stores the reverse long-to-String mapping
- * in memory.
+ * Implementation which stores the reverse long-to-String mapping in memory.
*/
public final class MemoryIDMigrator extends AbstractIDMigrator {
-
+
private final FastByIDMap<String> longToString;
-
+
public MemoryIDMigrator() {
this.longToString = new FastByIDMap<String>(100);
}
-
+
@Override
public void storeMapping(long longID, String stringID) {
synchronized (longToString) {
longToString.put(longID, stringID);
}
}
-
+
@Override
public String toStringID(long longID) {
synchronized (longToString) {
return longToString.get(longID);
}
}
-
+
}
\ No newline at end of file
Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/MySQLJDBCIDMigrator.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/MySQLJDBCIDMigrator.java?rev=909912&r1=909911&r2=909912&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/MySQLJDBCIDMigrator.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/MySQLJDBCIDMigrator.java Sat Feb 13 20:54:05 2010
@@ -20,39 +20,48 @@
import javax.sql.DataSource;
/**
- * <p>An implementation for MySQL. The following statement would create a table suitable for use with
- * this class:</p>
+ * <p>
+ * An implementation for MySQL. The following statement would create a table suitable for use with this class:
+ * </p>
*
- * <p><pre>
+ * <p>
+ *
+ * <pre>
* CREATE TABLE taste_id_migration (
* long_id BIGINT NOT NULL,
* string_id VARCHAR(255) NOT NULL,
* PRIMARY KEY (long_id)
* )
- * </pre></p>
- *
- * <p>Separately, note that in a MySQL database, the following function calls will convert a string value into
- * a numeric value in the same way that the standard implementations in this package do. This may
- * be useful in writing SQL statements for use with
+ * </pre>
+ *
+ * </p>
+ *
+ * <p>
+ * Separately, note that in a MySQL database, the following function calls will convert a string value into a
+ * numeric value in the same way that the standard implementations in this package do. This may be useful in
+ * writing SQL statements for use with
* {@link org.apache.mahout.cf.taste.impl.model.jdbc.AbstractJDBCDataModel} subclasses which convert string
- * column values to appropriate numeric values -- though this should be viewed as a temporary
- * arrangement since it will impact performance:</p>
- *
- * <p><code>cast(conv(substring(md5([column name]),1,16),16,10) as signed)</code></p>
+ * column values to appropriate numeric values -- though this should be viewed as a temporary arrangement
+ * since it will impact performance:
+ * </p>
+ *
+ * <p>
+ * <code>cast(conv(substring(md5([column name]),1,16),16,10) as signed)</code>
+ * </p>
*/
public final class MySQLJDBCIDMigrator extends AbstractJDBCIDMigrator {
-
+
public MySQLJDBCIDMigrator(DataSource dataSource) {
- this(dataSource, DEFAULT_MAPPING_TABLE, DEFAULT_LONG_ID_COLUMN, DEFAULT_STRING_ID_COLUMN);
+ this(dataSource, AbstractJDBCIDMigrator.DEFAULT_MAPPING_TABLE,
+ AbstractJDBCIDMigrator.DEFAULT_LONG_ID_COLUMN, AbstractJDBCIDMigrator.DEFAULT_STRING_ID_COLUMN);
}
-
+
public MySQLJDBCIDMigrator(DataSource dataSource,
String mappingTable,
String longIDColumn,
String stringIDColumn) {
- super(dataSource,
- "SELECT " + stringIDColumn + " FROM " + mappingTable + " WHERE " + longIDColumn + "=?",
- "REPLACE INTO " + mappingTable + " (" + longIDColumn + ',' + stringIDColumn + ") VALUES (?,?)");
+ super(dataSource, "SELECT " + stringIDColumn + " FROM " + mappingTable + " WHERE " + longIDColumn + "=?",
+ "REPLACE INTO " + mappingTable + " (" + longIDColumn + ',' + stringIDColumn + ") VALUES (?,?)");
}
-
+
}
\ No newline at end of file