【问题标题】:Mahout: Using two DataModels in one RecommenderMahout:在一个 Recommender 中使用两个 DataModel
【发布时间】:2012-09-28 17:15:27
【问题描述】:

我正在尝试使用两组布尔偏好数据创建一个简单的推荐引擎。我想使用一个数据集来计算 UserSimilarity 和 UserNeighborhoods,然后使用这些邻域从第二组布尔偏好数据中提出建议。

我似乎有这个工作,但问题是当我去计算推荐时,如果用户有基于第一个数据集的邻居,但不存在于第二个数据集中(尽管他们的邻居是)它不产生任何建议。

这是 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);
      }
  };

这是 trainingModel 文件的示例

1,111
2,222

2,111
2,222

3,111
3,222

还有推荐模型文件

1,91
1,92

2,91

运行此建议为用户 2 提供 92,但在到达用户 3 时会抛出 NoSuchUserException

Sol... 有没有什么方法可以根据在另一个数据集上计算的相似性从一个数据集生成推荐,而无需让所有用户都出现在第二个数据集中?

这是我现在正在使用的完整代码:

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) );
        }        
    };

}

然后运行这个方法

    @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);
        }
}

产生这个输出:

计算得分:0.7033357620239258 召回率:1.0 精度:1.0 用户 1 用户 2 RecommendedItem[item:9222, value:0.8516679] 抛出 org.apache.mahout.cf.taste.common.NoSuchUserException: 3

【问题讨论】:

    标签: java machine-learning mahout


    【解决方案1】:

    你可以做你描述的事情,以及你描述它的大致方式。支持用户相似度度量的数据集确实可能不同于提出建议的数据集。用户相似度指标实际上可以基于您喜欢的任何内容。

    但是,它确实需要能够为用于提出建议的数据集中的任何对生成用户-用户相似度。我建议您在 UserSimilarity 实现中简单地对此进行特殊处理,以便在某个用户未知时返回 0 或其他内容。

    【讨论】:

    • 我考虑过这个。但这是否意味着实际使用了推荐数据集中的人的用户-用户相似度?第二个数据集非常稀疏且嘈杂,因此我不希望其中的模式影响推荐的选择方式。
    • 基于用户的rec算法本质上只是一个加权平均算法,其中权重是相似的。是的,即使它们的来源完全不相关,它们也会被使用。无论它们来自哪里,都与 rec 算法无关。您的数据能否以这种方式给出好的答案取决于数据。
    • 如果我要做的是根据数据集A确定用户1和2相似,然后向用户2建议用户1在数据集B中喜欢的所有内容;我的方法能做到这一点吗?
    • 是的,但是用户 1 和 2 需要存在于 A 和 B 中。(或者,您的代码需要帮助它假装它们存在。)推荐者所做的不仅仅是推荐其他人喜欢的一切——它是许多用户的加权平均值。我想这就是你的意思。
    • 谢谢。是的,我只是简单化了。虽然只有 2 个用户和布尔值和偏好的数据集,但我想它必须推荐用户 2 不喜欢的所有内容,或者什么都不喜欢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-27
    • 2015-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多