/*
* Source code for listing 5.5
*
*/
package mia.recommender.ch05;
import com.google.common.io.Files;
import com.google.common.io.InputSupplier;
import com.google.common.io.Resources;
import org.apache.mahout.cf.taste.common.Refreshable;
import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.impl.common.FastIDSet;
import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;
import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood;
import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.EuclideanDistanceSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood;
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.cf.taste.similarity.UserSimilarity;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Collection;
import java.util.List;
public class LibimsetiRecommender implements Recommender {
private final Recommender delegate;
private final DataModel model;
private final FastIDSet men;
private final FastIDSet women;
private final FastIDSet usersRateMoreMen;
private final FastIDSet usersRateLessMen;
public LibimsetiRecommender() throws TasteException, IOException {
this(new FileDataModel(readResourceToTempFile("ratings.dat")));
}
public LibimsetiRecommender(DataModel model)
throws TasteException, IOException {
UserSimilarity similarity = new EuclideanDistanceSimilarity(model);
UserNeighborhood neighborhood =
new NearestNUserNeighborhood(2, similarity, model);
delegate =
new GenericUserBasedRecommender(model, neighborhood, similarity);
this.model = model;
FastIDSet[] menWomen = GenderRescorer.parseMenWomen(readResourceToTempFile("gender.dat"));
men = menWomen[0];
women = menWomen[1];
usersRateMoreMen = new FastIDSet(50000);
usersRateLessMen = new FastIDSet(50000);
}
@Override
public List<RecommendedItem> recommend(long userID, int howMany)
throws TasteException {
IDRescorer rescorer = new GenderRescorer(
men, women, usersRateMoreMen, usersRateLessMen, userID, model);
return delegate.recommend(userID, howMany, rescorer);
}
@Override
public List<RecommendedItem> recommend(long userID,
int howMany,
IDRescorer rescorer)
throws TasteException {
return delegate.recommend(userID, howMany, rescorer);
}
@Override
public float estimatePreference(long userID, long itemID)
throws TasteException {
IDRescorer rescorer = new GenderRescorer(
men, women, usersRateMoreMen, usersRateLessMen, userID, model);
return (float) rescorer.rescore(
itemID, delegate.estimatePreference(userID, itemID));
}
@Override
public void setPreference(long userID, long itemID, float value)
throws TasteException {
delegate.setPreference(userID, itemID, value);
}
@Override
public void removePreference(long userID, long itemID)
throws TasteException {
delegate.removePreference(userID, itemID);
}
@Override
public DataModel getDataModel() {
return delegate.getDataModel();
}
@Override
public void refresh(Collection<Refreshable> alreadyRefreshed) {
delegate.refresh(alreadyRefreshed);
}
static File readResourceToTempFile(String resourceName) throws IOException {
String absoluteResource = resourceName.startsWith("/") ? resourceName : '/' + resourceName;
InputSupplier<? extends InputStream> inSupplier;
try {
URL resourceURL = Resources.getResource(LibimsetiRecommender.class, absoluteResource);
inSupplier = Resources.newInputStreamSupplier(resourceURL);
} catch (IllegalArgumentException iae) {
File resourceFile = new File(resourceName);
inSupplier = Files.newInputStreamSupplier(resourceFile);
}
File tempFile = File.createTempFile("taste", null);
tempFile.deleteOnExit();
Files.copy(inSupplier, tempFile);
return tempFile;
}
}