简体   繁体   English

Mahout:在一个推荐器中使用两个DataModels

[英]Mahout: Using two DataModels in one Recommender

I am trying to create a simple recommendation engine with two sets of boolean preference data. 我正在尝试使用两组布尔偏好数据创建一个简单的推荐引擎。 I want to use one data set to calculate UserSimilarity and UserNeighborhoods, and then use those neighborhoods to make recommendations from a second set of boolean preference data. 我想使用一个数据集来计算UserSimilarity和UserNeighborhoods,然后使用这些邻域从第二组布尔偏好数据中提出建议。

I seem to have this working, but the problem is that when I go to calculate recommendations, if a user has neighbors based on the first data set, but is not present in the second data set (though their neighbors are) it produces no recommendations. 我似乎正在工作,但是问题是,当我去计算推荐时,如果用户基于第一个数据集有邻居,但是在第二个数据集中不存在(尽管他们的邻居在),则不会产生推荐。

Here's RecommendationBuilder code: 这是RecommendationBuilder代码:

  recommenderBuilder = new RecommenderBuilder() {
      public Recommender buildRecommender(DataModel recommendationModel) throws TasteException {
          UserSimilarity similarity = new LogLikelihoodSimilarity(trainingModel);
          UserNeighborhood neighborhood = new NearestNUserNeighborhood(10, 0.7, similarity, recommendationModel);

          return new GenericBooleanPrefUserBasedRecommender(recommendationModel, neighborhood, similarity);
      }
  };

And here's a sample of the trainingModel file 这是trainingModel文件的示例

1,111
2,222

2,111
2,222

3,111
3,222

And the recommendationModel file 和commitmentModel文件

1,91
1,92

2,91

Running this recommends 92 for user 2, but throws a NoSuchUserException when it gets to user 3. 建议为用户2运行92,但是在到达用户3时抛出NoSuchUserException

Sol... Is there any way to produce recommendations from one data set based on similarities calculated on another data set, without needing to have all users present in the second data set? Sol ...是否有任何方法可以根据在另一个数据集上计算出的相似性从一个数据集生成推荐,而无需让所有用户都出现在第二个数据集中?

Here's the complete code I'm working with right now: 这是我现在正在使用的完整代码:

private DataModel trainingModel;
private DataModel recommendationModel;
private RecommenderEvaluator evaluator;
private RecommenderIRStatsEvaluator evaluator2;
private RecommenderBuilder recommenderBuilder;
private DataModelBuilder modelBuilder;

@Override
public void afterPropertiesSet() throws IOException, TasteException {

    trainingModel = new GenericBooleanPrefDataModel(
        GenericBooleanPrefDataModel.toDataMap(new FileDataModel(new File("/music.csv")))
    );

    recommendationModel = new GenericBooleanPrefDataModel(
            GenericBooleanPrefDataModel.toDataMap(new FileDataModel(new File("/movies.csv")))
    );

    evaluator = new AverageAbsoluteDifferenceRecommenderEvaluator();
    evaluator2 = new GenericRecommenderIRStatsEvaluator();


    recommenderBuilder = new RecommenderBuilder() {
        public Recommender buildRecommender(DataModel model) throws TasteException {
            UserSimilarity similarity = new LogLikelihoodSimilarity(trainingModel);
            UserNeighborhood neighborhood = new NearestNUserNeighborhood(10, 0.7, similarity, model);

            return new GenericBooleanPrefUserBasedRecommender(model, neighborhood, similarity);
        }
    };

    modelBuilder = new DataModelBuilder() {
        public DataModel buildDataModel( FastByIDMap<PreferenceArray> trainingData ) {
            return new GenericBooleanPrefDataModel( GenericBooleanPrefDataModel.toDataMap(trainingData) );
        }        
    };

}

And then running this method 然后运行此方法

    @Override
    public void testData() throws TasteException {

        double score = evaluator.evaluate(recommenderBuilder, modelBuilder, trainingModel, 0.9, 1.0);
        System.out.println("calculated score: " + score);

        try {
            IRStatistics stats = evaluator2.evaluate(
                    recommenderBuilder, modelBuilder, trainingModel, null, 2,
                    0.0,
                    1.0
            );
            System.out.println("recall: " + stats.getRecall());
            System.out.println("precision: " + stats.getPrecision());
        } catch (Throwable t) {
            System.out.println("throwing " + t);
        }

        List<RecommendedItem> recommendations = recommenderBuilder.buildRecommender(recommendationModel).recommend(1,2);
        System.out.println("user 1");
        for (RecommendedItem recommendation : recommendations) { System.out.println(recommendation);}

        recommendations = recommenderBuilder.buildRecommender(recommendationModel).recommend(2,2);
        System.out.println("user 2");
        for (RecommendedItem recommendation : recommendations) { System.out.println(recommendation);}

        try {
            recommendations = recommenderBuilder.buildRecommender(recommendationModel).recommend(3,2);
            System.out.println("user 3");
            for (RecommendedItem recommendation : recommendations) { System.out.println(recommendation);}
        } catch (Throwable t) {
            System.out.println("throwing " + t);
        }
}

Produces this output: 产生以下输出:

calculated score: 0.7033357620239258 recall: 1.0 precision: 1.0 user 1 user 2 RecommendedItem[item:9222, value:0.8516679] throwing org.apache.mahout.cf.taste.common.NoSuchUserException: 3 计算得分:0.7033357620239258召回:1.0精度:1.0用户1用户2 RecommendationItem [item:9222,值:0.8516679]抛出org.apache.mahout.cf.taste.common.NoSuchUserException:3

You can do what you are describing, and roughly how you are describing it. 您可以做您正在描述的事情,以及大致如何描述它。 The data set that powers the user similarity metric could indeed be different from the data set over which recommendations are made. 支持用户相似性度量的数据集的确可能与提出建议的数据集不同。 The user similarity metric could in fact be based on anything you like. 用户相似性指标实际上可以基于您喜欢的任何内容。

However it does need to be able to produce a user-user similarity for any pair in the data set used to make recommendations. 但是,它确实需要能够对用于提出建议的数据集中的任何一对产生用户-用户相似性。 I suggest you simply special-case this in your UserSimilarity implementation to return 0 or something when one user is unknown. 我建议您在UserSimilarity实现中对此进行特殊处理,以在一个用户未知时返回0或类似的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM