io.seldon.recommendation.combiner.RankSumCombiner.java Source code

Java tutorial

Introduction

Here is the source code for io.seldon.recommendation.combiner.RankSumCombiner.java

Source

/*
 * Seldon -- open source prediction engine
 * =======================================
 *
 * Copyright 2011-2015 Seldon Technologies Ltd and Rummble Ltd (http://www.seldon.io/)
 *
 * ********************************************************************************************
 *
 * Licensed 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 io.seldon.recommendation.combiner;

import io.seldon.clustering.recommender.ItemRecommendationResultSet;
import io.seldon.recommendation.RecommendationPeer;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 *
 * Combine recommendations from algorithms based on their rank in the list of recs.
 *
 * @author firemanphil
 *         Date: 23/02/15
 *         Time: 11:00
 */
@Component
public class RankSumCombiner implements AlgorithmResultsCombiner {

    private final int numResultSetsToUse;
    private final boolean strict;

    @Autowired
    public RankSumCombiner(@Value("${combiner.ranksum.maxResultSets:2}") int numResultSetsToUse,
            @Value("${combiner.ranksum.strict:false}") boolean strict) {
        this.numResultSetsToUse = numResultSetsToUse;
        this.strict = strict;
    }

    @Override
    public boolean isEnoughResults(int numRecsRequired, List<RecommendationPeer.RecResultContext> resultsSets) {
        int numValidSets = 0;
        for (RecommendationPeer.RecResultContext set : resultsSets) {
            if (set.resultSet.getResults().size() >= numRecsRequired) {
                numValidSets++;
            }
        }
        return numValidSets >= numResultSetsToUse;
    }

    @Override
    public RecommendationPeer.RecResultContext combine(int numRecsRequired,
            List<RecommendationPeer.RecResultContext> resultsSets) {
        Map<Long, String> item_recommender_lookup = new HashMap<>();
        Map<ItemRecommendationResultSet.ItemRecommendationResult, Integer> rankSumMap = new HashMap<>();
        List<RecommendationPeer.RecResultContext> validResultSets = new ArrayList<>();
        List<String> validResultsAlgKeys = new ArrayList<>();
        for (RecommendationPeer.RecResultContext set : resultsSets) {
            if ((strict && set.resultSet.getResults().size() >= numRecsRequired)
                    || (!strict && set.resultSet.getResults().size() > 0)) {
                validResultSets.add(set);
                validResultsAlgKeys.add(set.algKey);
            }
        }

        for (int i = 0; i < numRecsRequired; i++) {
            for (RecommendationPeer.RecResultContext validResultSet : validResultSets) {
                List<ItemRecommendationResultSet.ItemRecommendationResult> ordered = validResultSet.resultSet
                        .getResults();
                Collections.sort(ordered, Collections.reverseOrder());
                if (i < ordered.size()) {
                    final ItemRecommendationResultSet.ItemRecommendationResult itemRecommendationResult = ordered
                            .get(i);
                    Integer rankSum = rankSumMap.get(itemRecommendationResult);
                    if (rankSum == null)
                        rankSum = 0;
                    rankSum += (numRecsRequired - i);
                    rankSumMap.put(itemRecommendationResult, rankSum);

                    { // capture the recommender used for item
                        String original_value = item_recommender_lookup.put(itemRecommendationResult.item,
                                validResultSet.resultSet.getRecommenderName());
                        if (original_value != null) {
                            item_recommender_lookup.put(itemRecommendationResult.item, original_value);
                        }
                    }
                }
            }
        }

        List<ItemRecommendationResultSet.ItemRecommendationResult> orderedResults = new ArrayList<>();
        for (Map.Entry<ItemRecommendationResultSet.ItemRecommendationResult, Integer> entry : rankSumMap
                .entrySet()) {
            Float newScore = entry.getValue().floatValue();
            Long item = entry.getKey().item;
            ItemRecommendationResultSet.ItemRecommendationResult result = new ItemRecommendationResultSet.ItemRecommendationResult(
                    item, newScore);
            orderedResults.add(result);
        }

        Collections.sort(orderedResults, Collections.reverseOrder());
        RecommendationPeer.RecResultContext recResultContext = new RecommendationPeer.RecResultContext(
                new ItemRecommendationResultSet(orderedResults, StringUtils.join(validResultsAlgKeys, ':')),
                StringUtils.join(validResultsAlgKeys, ':'));
        recResultContext.item_recommender_lookup = item_recommender_lookup;
        return recResultContext;
    }

}