You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mahout.apache.org by ss...@apache.org on 2013/03/07 11:10:00 UTC
svn commit: r1453756 - in
/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste: hadoop/als/
impl/recommender/ recommender/
Author: ssc
Date: Thu Mar 7 10:10:00 2013
New Revision: 1453756
URL: http://svn.apache.org/r1453756
Log:
MAHOUT-1151, a few more fixes
Added:
mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/als/CappableRecommendedItem.java
Modified:
mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/als/ParallelALSFactorizationJob.java
mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/als/RecommenderJob.java
mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/GenericRecommendedItem.java
mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/recommender/RecommendedItem.java
Added: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/als/CappableRecommendedItem.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/als/CappableRecommendedItem.java?rev=1453756&view=auto
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/als/CappableRecommendedItem.java (added)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/als/CappableRecommendedItem.java Thu Mar 7 10:10:00 2013
@@ -0,0 +1,76 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.mahout.cf.taste.hadoop.als;
+
+import com.google.common.base.Preconditions;
+import org.apache.mahout.cf.taste.recommender.RecommendedItem;
+import org.apache.mahout.common.RandomUtils;
+
+/**
+ * Mutable variant of {@link RecommendedItem} that allows to cap the preference to a max value
+ */
+class CappableRecommendedItem implements RecommendedItem {
+
+ private final long itemID;
+ private float value;
+
+ /**
+ * @throws IllegalArgumentException
+ * if item is null or value is NaN
+ */
+ public CappableRecommendedItem(long itemID, float value) {
+ Preconditions.checkArgument(!Float.isNaN(value), "value is NaN");
+ this.itemID = itemID;
+ this.value = value;
+ }
+
+ @Override
+ public long getItemID() {
+ return itemID;
+ }
+
+ @Override
+ public float getValue() {
+ return value;
+ }
+
+ public void capToMaxValue(float maxValue) {
+ if (value > maxValue) {
+ value = maxValue;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "CappableRecommendedItem[item:" + itemID + ", value:" + value + ']';
+ }
+
+ @Override
+ public int hashCode() {
+ return (int) itemID ^ RandomUtils.hashFloat(value);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof CappableRecommendedItem)) {
+ return false;
+ }
+ RecommendedItem other = (RecommendedItem) o;
+ return itemID == other.getItemID() && value == other.getValue();
+ }
+}
Modified: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/als/ParallelALSFactorizationJob.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/als/ParallelALSFactorizationJob.java?rev=1453756&r1=1453755&r2=1453756&view=diff
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/als/ParallelALSFactorizationJob.java (original)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/als/ParallelALSFactorizationJob.java Thu Mar 7 10:10:00 2013
@@ -269,7 +269,7 @@ public class ParallelALSFactorizationJob
throws IOException, InterruptedException {
Vector ratings = ratingsWritable.get();
- List<Vector> featureVectors = Lists.newArrayList();
+ List<Vector> featureVectors = Lists.newArrayListWithCapacity(ratings.getNumNondefaultElements());
Iterator<Vector.Element> interactions = ratings.iterateNonZero();
while (interactions.hasNext()) {
int index = interactions.next().index();
Modified: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/als/RecommenderJob.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/als/RecommenderJob.java?rev=1453756&r1=1453755&r2=1453756&view=diff
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/als/RecommenderJob.java (original)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/als/RecommenderJob.java Thu Mar 7 10:10:00 2013
@@ -38,10 +38,12 @@ import org.apache.mahout.math.map.OpenIn
import org.apache.mahout.math.set.OpenIntHashSet;
import java.io.IOException;
+import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.PriorityQueue;
/**
* <p>Computes the top-N recommendations per user from a decomposition of the rating matrix</p>
@@ -97,7 +99,6 @@ public class RecommenderJob extends Abst
return -1;
}
-
return 0;
}
@@ -109,6 +110,9 @@ public class RecommenderJob extends Abst
}
};
+ private static final Comparator<RecommendedItem> DESCENDING_BY_PREFERENCE_VALUE =
+ Collections.reverseOrder(BY_PREFERENCE_VALUE);
+
static class PredictionMapper
extends Mapper<IntWritable,VectorWritable,IntWritable,RecommendedItemsWritable> {
@@ -118,7 +122,9 @@ public class RecommenderJob extends Abst
private int recommendationsPerUser;
private float maxRating;
- private RecommendedItemsWritable result = new RecommendedItemsWritable();
+ private PriorityQueue<RecommendedItem> topKItems;
+
+ private RecommendedItemsWritable recommendations = new RecommendedItemsWritable();
@Override
protected void setup(Context ctx) throws IOException, InterruptedException {
@@ -132,6 +138,8 @@ public class RecommenderJob extends Abst
M = ALSUtils.readMatrixByRows(pathToM, ctx.getConfiguration());
maxRating = Float.parseFloat(ctx.getConfiguration().get(MAX_RATING));
+
+ topKItems = new PriorityQueue<RecommendedItem>(recommendationsPerUser + 1, BY_PREFERENCE_VALUE);
}
@Override
@@ -141,23 +149,27 @@ public class RecommenderJob extends Abst
Vector ratings = ratingsWritable.get();
final int userID = userIDWritable.get();
final OpenIntHashSet alreadyRatedItems = new OpenIntHashSet(ratings.getNumNondefaultElements());
- final TopK<RecommendedItem> topKItems = new TopK<RecommendedItem>(recommendationsPerUser, BY_PREFERENCE_VALUE);
Iterator<Vector.Element> ratingsIterator = ratings.iterateNonZero();
while (ratingsIterator.hasNext()) {
alreadyRatedItems.add(ratingsIterator.next().index());
}
+ topKItems.clear();
+
M.forEachPair(new IntObjectProcedure<Vector>() {
@Override
public boolean apply(int itemID, Vector itemFeatures) {
if (!alreadyRatedItems.contains(itemID)) {
double predictedRating = U.get(userID).dot(itemFeatures);
- // manual check to avoid an object instantiation per unknown item
- if (topKItems.size() < recommendationsPerUser || (float) predictedRating > topKItems.peek().getValue()) {
- topKItems.offer(new GenericRecommendedItem(itemID, (float) predictedRating));
+ if (topKItems.size() < recommendationsPerUser) {
+ topKItems.add(new CappableRecommendedItem(itemID, (float) predictedRating));
+ } else if (predictedRating > topKItems.peek().getValue()) {
+ topKItems.add(new CappableRecommendedItem(itemID, (float) predictedRating));
+ topKItems.poll();
}
+
}
return true;
}
@@ -165,13 +177,14 @@ public class RecommenderJob extends Abst
if (!topKItems.isEmpty()) {
- List<RecommendedItem> recommendedItems = topKItems.retrieve();
+ List<RecommendedItem> recommendedItems = Lists.newArrayList(topKItems);
+ Collections.sort(recommendedItems, DESCENDING_BY_PREFERENCE_VALUE);
for (RecommendedItem topItem : recommendedItems) {
- topItem.capToMaxValue(maxRating);
+ ((CappableRecommendedItem) topItem).capToMaxValue(maxRating);
}
- result.set(recommendedItems);
- ctx.write(userIDWritable, result);
+ recommendations.set(recommendedItems);
+ ctx.write(userIDWritable, recommendations);
}
}
}
Modified: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/GenericRecommendedItem.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/GenericRecommendedItem.java?rev=1453756&r1=1453755&r2=1453756&view=diff
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/GenericRecommendedItem.java (original)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/GenericRecommendedItem.java Thu Mar 7 10:10:00 2013
@@ -32,7 +32,7 @@ import com.google.common.base.Preconditi
public final class GenericRecommendedItem implements RecommendedItem, Serializable {
private final long itemID;
- private float value;
+ private final float value;
/**
* @throws IllegalArgumentException
@@ -55,13 +55,6 @@ public final class GenericRecommendedIte
}
@Override
- public void capToMaxValue(float maxValue) {
- if (value > maxValue) {
- value = maxValue;
- }
- }
-
- @Override
public String toString() {
return "RecommendedItem[item:" + itemID + ", value:" + value + ']';
}
Modified: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/recommender/RecommendedItem.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/recommender/RecommendedItem.java?rev=1453756&r1=1453755&r2=1453756&view=diff
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/recommender/RecommendedItem.java (original)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/recommender/RecommendedItem.java Thu Mar 7 10:10:00 2013
@@ -38,10 +38,4 @@ public interface RecommendedItem {
*/
float getValue();
- /**
- * set a maximum preference value
- *
- * @param maxValue
- */
- void capToMaxValue(float maxValue);
}