Example usage for org.apache.mahout.cf.taste.impl.common RunningAverage getAverage

List of usage examples for org.apache.mahout.cf.taste.impl.common RunningAverage getAverage

Introduction

In this page you can find the example usage for org.apache.mahout.cf.taste.impl.common RunningAverage getAverage.

Prototype

double getAverage();

Source Link

Usage

From source file:net.ufida.info.mahout.common.SlopeOneRecommender.java

License:Apache License

private float doEstimatePreference(long userID, long itemID) throws TasteException {
    double count = 0.0;
    double totalPreference = 0.0;
    PreferenceArray prefs = getDataModel().getPreferencesFromUser(userID);
    RunningAverage[] averages = diffStorage.getDiffs(userID, itemID, prefs);
    int size = prefs.length();
    for (int i = 0; i < size; i++) {
        RunningAverage averageDiff = averages[i];
        if (averageDiff != null) {
            double averageDiffValue = averageDiff.getAverage();
            if (weighted) {
                double weight = averageDiff.getCount();
                if (stdDevWeighted) {
                    double stdev = ((RunningAverageAndStdDev) averageDiff).getStandardDeviation();
                    if (!Double.isNaN(stdev)) {
                        weight /= 1.0 + stdev;
                    }/*from w  w  w .  j a v a2 s . c  om*/
                    // If stdev is NaN, then it is because count is 1. Because we're weighting by count,
                    // the weight is already relatively low. We effectively assume stdev is 0.0 here and
                    // that is reasonable enough. Otherwise, dividing by NaN would yield a weight of NaN
                    // and disqualify this pref entirely
                    // (Thanks Daemmon)
                }
                totalPreference += weight * (prefs.getValue(i) + averageDiffValue);
                count += weight;
            } else {
                totalPreference += prefs.getValue(i) + averageDiffValue;
                count += 1.0;
            }
        }
    }
    if (count <= 0.0) {
        RunningAverage itemAverage = diffStorage.getAverageItemPref(itemID);
        return itemAverage == null ? Float.NaN : (float) itemAverage.getAverage();
    } else {
        return (float) (totalPreference / count);
    }
}

From source file:recommender.GenericRecommenderIRStatsEvaluatorCustom.java

License:Apache License

@Override
public IRStatistics evaluate(RecommenderBuilder recommenderBuilder, DataModelBuilder dataModelBuilder,
        DataModel dataModel, IDRescorer rescorer, int at, double relevanceThreshold,
        double evaluationPercentage) throws TasteException {

    prop = new Properties();
    try {/*from w w w . j  av a 2s. c  om*/
        prop.load(GenericRecommenderIRStatsEvaluatorCustom.class.getResourceAsStream("settings.properties"));
    } catch (IOException ex) {
        java.util.logging.Logger.getLogger(GenericRecommenderIRStatsEvaluatorCustom.class.getName())
                .log(Level.SEVERE, null, ex);
    }

    // load settings from MySQL database
    loadSettings();

    Preconditions.checkArgument(recommenderBuilder != null, "recommenderBuilder is null");
    Preconditions.checkArgument(dataModel != null, "dataModel is null");
    Preconditions.checkArgument(at >= 1, "at must be at least 1");
    Preconditions.checkArgument(evaluationPercentage > 0.0 && evaluationPercentage <= 1.0,
            "Invalid evaluationPercentage: " + evaluationPercentage
                    + ". Must be: 0.0 < evaluationPercentage <= 1.0");

    int numItems = dataModel.getNumItems();
    System.out.println("Data model numItems: " + numItems);
    RunningAverage precision = new FullRunningAverage();
    RunningAverage recall = new FullRunningAverage();
    RunningAverage fallOut = new FullRunningAverage();
    RunningAverage nDCG = new FullRunningAverage();
    int numUsersRecommendedFor = 0;
    int numUsersWithRecommendations = 0;

    // map to store diversity ranges => number of users
    HashMap<String, String> map = new HashMap<>();

    LongPrimitiveIterator it = dataModel.getUserIDs();
    while (it.hasNext()) {

        long userID = it.nextLong();

        if (userID == 0) {
            continue;
        }

        // get the top users
        if (!list.contains(userID + "")) {
            continue;
        }

        if (random.nextDouble() >= evaluationPercentage) {
            // Skipped
            continue;
        }

        long start = System.currentTimeMillis();

        PreferenceArray prefs = dataModel.getPreferencesFromUser(userID);
        System.out.println("User preferences: " + prefs);

        // List some most-preferred items that would count as (most) "relevant" results
        double theRelevanceThreshold = 0;//Double.isNaN(relevanceThreshold) ? computeThreshold(prefs) : relevanceThreshold;
        FastIDSet relevantItemIDs = dataSplitter.getRelevantItemsIDs(userID, at, theRelevanceThreshold,
                dataModel);
        System.out.println("Relevant items: " + relevantItemIDs);
        System.out.println("Relevance threshold: " + theRelevanceThreshold);

        int numRelevantItems = relevantItemIDs.size();
        if (numRelevantItems <= 0) {
            continue;
        }

        FastByIDMap<PreferenceArray> trainingUsers = new FastByIDMap<>(dataModel.getNumUsers());
        LongPrimitiveIterator it2 = dataModel.getUserIDs();
        while (it2.hasNext()) {
            dataSplitter.processOtherUser(userID, relevantItemIDs, trainingUsers, it2.nextLong(), dataModel);
        }

        DataModel trainingModel = dataModelBuilder == null ? new GenericDataModel(trainingUsers)
                : dataModelBuilder.buildDataModel(trainingUsers);
        try {
            trainingModel.getPreferencesFromUser(userID);
        } catch (NoSuchUserException nsee) {
            continue; // Oops we excluded all prefs for the user -- just move on
        }

        int size = numRelevantItems + trainingModel.getItemIDsFromUser(userID).size();
        if (size < 2 * at) {
            // Really not enough prefs to meaningfully evaluate this user
            System.out
                    .println("Really not enough prefs (" + size + ") to meaningfully evaluate user: " + userID);
            continue;
        }

        Recommender recommender = recommenderBuilder.buildRecommender(trainingModel);

        int intersectionSize = 0;
        List<RecommendedItem> recommendedItems = recommender.recommend(userID, at, rescorer);
        HashMap<Long, Double> user_preferences = getUserPreferencesList(userID);
        for (RecommendedItem recommendedItem : recommendedItems) {
            double preference = isRelevant(user_preferences, recommendedItem);
            System.out.println("Preference: " + preference);
            if (relevantItemIDs.contains(recommendedItem.getItemID()) || preference != 0) {
                intersectionSize++;
            }
        }

        int numRecommendedItems = recommendedItems.size();

        // Precision
        if (numRecommendedItems > 0) {
            precision.addDatum((double) intersectionSize / (double) numRecommendedItems);
            System.out.println(
                    "intersectionSize: " + intersectionSize + " numRecommendedItems: " + numRecommendedItems);
        }

        // Recall
        recall.addDatum((double) intersectionSize / (double) numRelevantItems);

        // Fall-out
        if (numRelevantItems < size) {
            fallOut.addDatum(
                    (double) (numRecommendedItems - intersectionSize) / (double) (numItems - numRelevantItems));
        }

        // nDCG
        // In computing, assume relevant IDs have relevance 1 and others 0
        double cumulativeGain = 0.0;
        double idealizedGain = 0.0;
        for (int i = 0; i < numRecommendedItems; i++) {
            RecommendedItem item = recommendedItems.get(i);
            double discount = 1.0 / log2(i + 2.0); // Classical formulation says log(i+1), but i is 0-based here
            if (relevantItemIDs.contains(item.getItemID())) {
                cumulativeGain += discount;
            }
            // otherwise we're multiplying discount by relevance 0 so it doesn't do anything

            // Ideally results would be ordered with all relevant ones first, so this theoretical
            // ideal list starts with number of relevant items equal to the total number of relevant items
            if (i < numRelevantItems) {
                idealizedGain += discount;
            }
        }
        if (idealizedGain > 0.0) {
            nDCG.addDatum(cumulativeGain / idealizedGain);
        }

        // Reach
        numUsersRecommendedFor++;
        if (numRecommendedItems > 0) {
            numUsersWithRecommendations++;
        }

        long end = System.currentTimeMillis();

        log.info("Evaluated with user {} in {}ms", userID, end - start);
        log.info("Precision/recall/fall-out/nDCG/reach: {} / {} / {} / {} / {}", precision.getAverage(),
                recall.getAverage(), fallOut.getAverage(), nDCG.getAverage(),
                (double) numUsersWithRecommendations / (double) numUsersRecommendedFor);
        System.out.println("Relevant items: " + numRelevantItems);
        System.out.println("Precision: " + precision.getAverage());
        System.out.println("Recall: " + recall.getAverage());
        System.out.println("Fall-out: " + fallOut.getAverage());
        System.out.println("nDCG: " + nDCG.getAverage());
        System.out.println("Reach: " + (double) numUsersWithRecommendations / (double) numUsersRecommendedFor);
        double diversity = getDiversity(recommendedItems);
        System.out.println("Diversity: " + diversity);
        if (diversity >= 0 && diversity < 0.1) {
            int count = map.get("0-0.1") != null ? Integer.parseInt(map.get("0-0.1")) + 1 : 1;
            map.put("0-0.1", count + "");
        } else if (diversity >= 0.1 && diversity < 0.2) {
            int count = map.get("0.1-0.2") != null ? Integer.parseInt(map.get("0.1-0.2")) + 1 : 1;
            map.put("0.1-0.2", count + "");
        } else if (diversity >= 0.2 && diversity < 0.3) {
            int count = map.get("0.2-0.3") != null ? Integer.parseInt(map.get("0.2-0.3")) + 1 : 1;
            map.put("0.2-0.3", count + "");
        } else if (diversity >= 0.3 && diversity < 0.4) {
            int count = map.get("0.3-0.4") != null ? Integer.parseInt(map.get("0.3-0.4")) + 1 : 1;
            map.put("0.3-0.4", count + "");
        } else if (diversity >= 0.4 && diversity < 0.5) {
            int count = map.get("0.4-0.5") != null ? Integer.parseInt(map.get("0.4-0.5")) + 1 : 1;
            map.put("0.4-0.5", count + "");
        } else if (diversity >= 0.5 && diversity < 0.6) {
            int count = map.get("0.5-0.6") != null ? Integer.parseInt(map.get("0.5-0.6")) + 1 : 1;
            map.put("0.5-0.6", count + "");
        } else if (diversity >= 0.6 && diversity < 0.7) {
            int count = map.get("0.6-0.7") != null ? Integer.parseInt(map.get("0.6-0.7")) + 1 : 1;
            map.put("0.6-0.7", count + "");
        } else if (diversity >= 0.7 && diversity < 0.8) {
            int count = map.get("0.7-0.8") != null ? Integer.parseInt(map.get("0.7-0.8")) + 1 : 1;
            map.put("0.7-0.8", count + "");
        } else if (diversity >= 0.8 && diversity < 0.9) {
            int count = map.get("0.8-0.9") != null ? Integer.parseInt(map.get("0.8-0.9")) + 1 : 1;
            map.put("0.8-0.9", count + "");
        } else if (diversity >= 0.9) {
            int count = map.get("0.9-1") != null ? Integer.parseInt(map.get("0.9-1")) + 1 : 1;
            map.put("0.9-1", count + "");
        }
    }

    JSONObject json = new JSONObject(map);

    writeFile(prop.getProperty("metrics_file"), json.toJSONString());

    return new IRStatisticsImplCustom(precision.getAverage(), recall.getAverage(), fallOut.getAverage(),
            nDCG.getAverage(), (double) numUsersWithRecommendations / (double) numUsersRecommendedFor);
}