public CachingUserNeighborhood(UserNeighborhood neighborhood, DataModel dataModel) throws TasteException { Preconditions.checkArgument(neighborhood != null, "neighborhood is null"); this.neighborhood = neighborhood; int maxCacheSize = dataModel.getNumUsers(); // just a dumb heuristic for sizing this.neighborhoodCache = new Cache<Long, long[]>(new NeighborhoodRetriever(neighborhood), maxCacheSize); }
/** * Exports the simple user IDs and associated item IDs in the data model. * * @return a {@link FastByIDMap} mapping user IDs to {@link FastIDSet}s representing that user's * associated items */ public static FastByIDMap<FastIDSet> toDataMap(DataModel dataModel) throws TasteException { FastByIDMap<FastIDSet> data = new FastByIDMap<>(dataModel.getNumUsers()); LongPrimitiveIterator it = dataModel.getUserIDs(); while (it.hasNext()) { long userID = it.nextLong(); data.put(userID, dataModel.getItemIDsFromUser(userID)); } return data; }
@Override public double itemSimilarity(long itemID1, long itemID2) throws TasteException { int preferring1and2 = dataModel.getNumUsersWithPreferenceFor(itemID1, itemID2); if (preferring1and2 == 0) { return Double.NaN; } int preferring1 = dataModel.getNumUsersWithPreferenceFor(itemID1); int preferring2 = dataModel.getNumUsersWithPreferenceFor(itemID2); int numUsers = dataModel.getNumUsers(); double logLikelihood = twoLogLambda( preferring1and2, preferring1 - preferring1and2, preferring2, numUsers - preferring2); return 1.0 - 1.0 / (1.0 + logLikelihood); }
/** Creates a possibly weighted AbstractSimilarity. */ AbstractSimilarity(final DataModel dataModel, Weighting weighting, boolean centerData) throws TasteException { if (dataModel == null) { throw new IllegalArgumentException("dataModel is null"); } this.dataModel = dataModel; this.weighted = weighting == Weighting.WEIGHTED; this.centerData = centerData; this.cachedNumItems = dataModel.getNumItems(); this.cachedNumUsers = dataModel.getNumUsers(); this.refreshHelper = new RefreshHelper( new Callable<Object>() { @Override public Object call() throws TasteException { cachedNumItems = dataModel.getNumItems(); cachedNumUsers = dataModel.getNumUsers(); return null; } }); this.refreshHelper.addDependency(this.dataModel); }
@Override public double evaluate( RecommenderBuilder recommenderBuilder, DataModelBuilder dataModelBuilder, DataModel dataModel, double trainingPercentage, double evaluationPercentage) throws TasteException { Preconditions.checkNotNull(recommenderBuilder); Preconditions.checkNotNull(dataModel); Preconditions.checkArgument( trainingPercentage >= 0.0 && trainingPercentage <= 1.0, "Invalid trainingPercentage: " + trainingPercentage + ". Must be: 0.0 <= trainingPercentage <= 1.0"); Preconditions.checkArgument( evaluationPercentage >= 0.0 && evaluationPercentage <= 1.0, "Invalid evaluationPercentage: " + evaluationPercentage + ". Must be: 0.0 <= evaluationPercentage <= 1.0"); log.info("Beginning evaluation using {} of {}", trainingPercentage, dataModel); int numUsers = dataModel.getNumUsers(); FastByIDMap<PreferenceArray> trainingPrefs = new FastByIDMap<PreferenceArray>(1 + (int) (evaluationPercentage * numUsers)); FastByIDMap<PreferenceArray> testPrefs = new FastByIDMap<PreferenceArray>(1 + (int) (evaluationPercentage * numUsers)); totalOfTrainingRatingsFromSource = 0; totalOfTrainingRatingsFromTargetWithContext = 0; totalOfTrainingRatingsFromTargetWithoutContext = 0; totalOfTestRatings = 0; LongPrimitiveIterator it = dataModel.getUserIDs(); while (it.hasNext()) { long userID = it.nextLong(); if (random.nextDouble() < evaluationPercentage) { splitOneUsersPrefs(trainingPercentage, trainingPrefs, testPrefs, userID, dataModel); } } // System.out.println("Training (Source, TargetWithoutContext, TargetWithContext): // "+totalOfTrainingRatingsFromSource+"/"+totalOfTrainingRatingsFromTargetWithoutContext+"/"+totalOfTrainingRatingsFromTargetWithContext); // int totalTraining = // (totalOfTrainingRatingsFromSource+totalOfTrainingRatingsFromTargetWithContext+totalOfTrainingRatingsFromTargetWithoutContext); // System.out.println("Training/Test: "+totalTraining+"/"+totalOfTestRatings); DataModel newDataModel = dataModel instanceof ContextualDataModel ? new ContextualDataModel(trainingPrefs) : new GenericDataModel(trainingPrefs); DataModel trainingModel = dataModelBuilder == null ? newDataModel : dataModelBuilder.buildDataModel(trainingPrefs); Recommender recommender = recommenderBuilder.buildRecommender(trainingModel); double result = getEvaluation(testPrefs, recommender); log.info("Evaluation result: {}", result); return result; }