推薦系統(tǒng)之推薦算法實戰(zhàn):mahout推薦算法框架

1.Mahout介紹

1.1概述

根據(jù)百度的解說,Mahout 是 Apache Software Foundation(ASF) 旗下的一個開源項目,提供一些可擴展的機器學(xué)習(xí)領(lǐng)域經(jīng)典算法的實現(xiàn),旨在幫助開發(fā)人員更加方便快捷地創(chuàng)建智能應(yīng)用程序。Mahout包含許多實現(xiàn),包括聚類、分類、推薦過濾、頻繁子項挖掘。此外,通過使用 Apache Hadoop 庫,Mahout 可以有效地擴展到云中。

1.2發(fā)展歷史

mahout一直伴隨Hadoop發(fā)展的,從一開始能夠幫助我們在Hadoop上實現(xiàn)很多機器學(xué)習(xí),到后來發(fā)現(xiàn)它的效率越來越慢,于是放棄使用了一段時間,在一年之后,大概14年開始宣布(0.9版本),截止14年底,mahout不再接受任何MapReduce開發(fā)的算法,轉(zhuǎn)向spark。我們知道,Hadoop也是經(jīng)歷了從1.0到2.0時代的變遷,而mahout也是跟著這樣一個變化而變化的。到了15年,mahout開始更新,更新到0.10、0.12版本后,mahout就開始使用基于Spark/Flink/H2O這樣一些平臺來去開發(fā)數(shù)據(jù)挖掘/機器學(xué)習(xí)庫。雖然改變了開發(fā)平臺,但也不是完全不支持了MapReduce的開發(fā),只是不再接受新的MapReduce算法開發(fā)。

1.3特點

擴展性:mahout本身只是一個機器學(xué)習(xí)庫,并不是一個平臺,不像H2O,H2O是完整的做機器學(xué)習(xí),預(yù)測分析的平臺,而MapReduce只是一個庫,它底層的存儲還是基于HDFS,它的調(diào)度還是使用了Hadoop平臺上的 YARN ,HDFS本身就給mahout帶來了存儲和計算
容錯性:是基于MapReduce/Spark/Flink這些計算引擎來實現(xiàn)的,而MapReduce/Spark/Flink本身具有非常好的容錯性,包括它的推送和執(zhí)行和失敗容錯機制等。

1.4組件

屬于Hadoop生態(tài)系統(tǒng)重要組成部分:如果Hadoop是一頭大象,而mahout就是一個訓(xùn)象師,引導(dǎo)它往什么方向走,做什么樣的事。它也是Hadoop的一個重要組件,伴隨Hadoop成長。

1.5實現(xiàn)的大部分常用的數(shù)據(jù)挖掘算法

聚類算法


分類算法

其他算法

1.6Mahout后端計算引擎

支持mr,后來轉(zhuǎn)向spark并包含原來的mr,spark最大特點是基于內(nèi)存、基于圖調(diào)度的方式、算子簡單易用和適用的語言(底層有實現(xiàn))
H2O本身是一個適用于做機器學(xué)習(xí)和預(yù)測分析的平臺,自身有一套算法支持的庫 ,H2O也可以在Hadoop中集成
Flink:支持流處理和批處理
有些不同的算法支持不同的計算引擎。

1.7Mahout架構(gòu)


Mahout架構(gòu):low-level

Mahout提供的算法架構(gòu)

2.mahout推薦算法介紹

2.1Mahout推薦系統(tǒng)介紹

協(xié)同過濾框架一
使用歷史數(shù)據(jù)(打分,點擊,購買等)作為推薦的依據(jù)
User-based: 通過發(fā)現(xiàn)類似的用戶推薦商品。由于用戶多變的特性,這種方法很那擴展;
Item-based:通過計算item之間相似度推薦商品。商品不易變化,相似度矩陣可離線計算得到。(誕生于Amazon)
?MF-based:通過將原始的user-item矩陣分解成小的矩陣,分析潛在的影響因子,并以解釋用戶的行為。(誕生于Netflix Prize)
協(xié)同過濾框架二
SVD(Singular Value Decomposition)因式分解實現(xiàn)協(xié)同過濾
基于ALS(alternating least squares)的協(xié)同過濾算法

2.2Mahout推薦系統(tǒng)架構(gòu)
2.3利用Mahout構(gòu)建推薦系統(tǒng)

輸入輸出
輸入:原始數(shù)據(jù)(user preferences,用戶偏好)
輸出:用戶偏好估計
步驟
Step 1:將原始數(shù)據(jù)映射到Mahout定義的Data Model中
Step 2: 調(diào)優(yōu)推薦組件
相似度組件,臨界關(guān)系組件等
Step 3: 計算排名估計值
Step 4:評估推薦結(jié)果

2.4Mahout推薦系統(tǒng)組件

Mahout關(guān)鍵抽象是通過Java Interface實現(xiàn)的:
DataModel Interface將原始數(shù)據(jù)映射成Mahout兼容格式
UserSimilarity Interface計算兩個用戶間的相關(guān)度
ItemSimilarity Interface計算兩個商品間的相關(guān)度
UserNeighborhood Interface定義用戶或商品間的“臨近”
Recommender Interface實現(xiàn)具體的推薦算法,完成推薦功能(包括訓(xùn)練,預(yù)測等)
推薦系統(tǒng)組件:DataModel

推薦系統(tǒng)組件:UserSimilarity

相似度舉例:TanimotoDistance


相似度舉例:CosineSimilarity

Pearson vs. Euclidean distance

Pearson vs. Euclidean distance

推薦系統(tǒng)組件:UserNeighborhood


從以上組件可以看出,Mahout提供了大量的基于CF的推薦器:
不同的推薦算法
不同的“鄰接”定義
不同的相似度定義
評估不同的算法實現(xiàn)非常耗時
Mahout提供了評估不同算法組合效果的工具
Mahout提供了標(biāo)準(zhǔn)的推薦系統(tǒng)評估接口

2.5推薦系統(tǒng)評估

Mahout提供了大量方法用于評估推薦系統(tǒng)
1.基于Prediction-based measures:
Mean Average Error 平均絕對誤差
RMSE (Root Mean Square Error) 均方根誤差

Class: AverageAbsoluteDifferenceEvaluator
Method: evaluate()
Parameters:
Recommender implementation
DataModel implementation
TrainingSet size (e.g. 70%)
% of the data to use in the evaluation (smaller % for fast prototyping)

2.基于IR-based measures
Precision, Recall, F1-measure 準(zhǔn)確率,召回率,F(xiàn)1混合
NDCG (ranking measure)

Class: GenericRecommenderIRStatsEvaluator
Method: evaluate()
Parameters:
Recommender implementation
DataModel implementation
Relevance Threshold (mean+standard deviation)
% of the data to use in the evaluation (smaller % for fast prototyping)

3.mahout推薦算法實戰(zhàn)

實例1:preferences

要求:
創(chuàng)建user-item偏好數(shù)據(jù),并輸出
實現(xiàn):
使用GenericUserPreferenceArray創(chuàng)建數(shù)據(jù)
通過PreferenceArray存儲數(shù)據(jù)
代碼如下:

package com.zdd.example;

import org.apache.mahout.cf.taste.impl.model.GenericUserPreferenceArray;
import org.apache.mahout.cf.taste.model.Preference;
import org.apache.mahout.cf.taste.model.PreferenceArray;

public class CreatePreferenceArray {
    private CreatePreferenceArray() {
    }

    public static void main(String[] args) {
        PreferenceArray User1Pref = new GenericUserPreferenceArray(2);
        User1Pref.setUserID(0, 1L);
        User1Pref.setItemID(0, 101L);
        User1Pref.setValue(0, 3.0f);
        User1Pref.setItemID(1, 102L);
        User1Pref.setValue(1, 4.0f);
        Preference pref = User1Pref.get(1);
        System.out.println(User1Pref);
    }
}

運行結(jié)果如下:
GenericUserPreferenceArray[userID:1,{101=3.0,102=4.0}]
表示用戶ID為1的用戶給商品101和102分別打分3.0和4.0

實例2:data model

PreferenceArray存儲了單個用戶的偏好,所有用戶的偏好數(shù)據(jù)如何保存?HashMap? NO!
Mahout引入了一個為推薦任務(wù)優(yōu)化的數(shù)據(jù)結(jié)構(gòu):FastByIDMap
需求:
使用GenericDataModel讀入FastByIDMap數(shù)據(jù)
代碼:

package com.zdd.example;

import org.apache.mahout.cf.taste.impl.common.FastByIDMap;
import org.apache.mahout.cf.taste.impl.model.GenericDataModel;
import org.apache.mahout.cf.taste.impl.model.GenericUserPreferenceArray;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.model.PreferenceArray;

public class CreateGenericDataModel {
    private CreateGenericDataModel() {
    }

    public static void main(String[] args) {
        FastByIDMap<PreferenceArray> preferences = new FastByIDMap<PreferenceArray>();
        PreferenceArray User1Pref = new GenericUserPreferenceArray(2);
        User1Pref.setUserID(0, 1L);
        User1Pref.setItemID(0, 101L);
        User1Pref.setValue(0, 3.0f);
        User1Pref.setItemID(1, 102L);
        User1Pref.setValue(1, 4.0f);

        PreferenceArray User2Pref = new GenericUserPreferenceArray(2);
        User2Pref.setUserID(0, 2L);
        User2Pref.setItemID(0, 101L);
        User2Pref.setValue(0, 3.0f);
        User2Pref.setItemID(1, 102L);
        User2Pref.setValue(1, 4.0f);

        preferences.put(1L, User1Pref);
        preferences.put(2L, User2Pref);

        DataModel model = new GenericDataModel(preferences);
        System.out.println(model);
        System.out.println(preferences);
    }
}

輸出如下:
GenericDataModel[users:1,2]
{1=GenericUserPreferenceArray[userID:1,{101=3.0,102=4.0}],2=GenericUserPreferenceArray[userID:2,{101=3.0,102=4.0}]}

實例3:Recommender

需求:通過User-based協(xié)同過濾推薦算法給用戶1推薦20個商品
實現(xiàn):
1.使用FileDataModel讀入文件
2.通過PearsonCorrelationSimilarity來計算相似度
3.使用GenericUserBasedRecommender構(gòu)建推薦引擎
ua.base數(shù)據(jù):



代碼:

package com.zdd.example;
import org.apache.mahout.cf.taste.impl.model.file.*;
import org.apache.mahout.cf.taste.impl.similarity.*;
import org.apache.mahout.cf.taste.impl.neighborhood.*;
import org.apache.mahout.cf.taste.impl.recommender.*;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.similarity.*;
import org.apache.mahout.cf.taste.neighborhood.*;
import org.apache.mahout.cf.taste.recommender.*;
import java.io.File;
import java.util.List;
public class RecommenderIntro {
    public static void main(String[] args) throws Exception{
        DataModel model = new FileDataModel(new File("data/ua.base"));
        UserSimilarity similarity = new PearsonCorrelationSimilarity(model);
        UserNeighborhood neighborhood = new NearestNUserNeighborhood(100, similarity, model);
        Recommender recommender = new GenericUserBasedRecommender(model, neighborhood, similarity);
        List<RecommendedItem> recommendedItems = recommender.recommend(1, 20);
        for (RecommendedItem recommendedItem: recommendedItems){
            System.out.println(recommendedItem);
        }
    }
}

推薦結(jié)果如下:


實例4:推薦模型評估(1)

需求:
評估實例3的推薦系統(tǒng)的優(yōu)劣
實現(xiàn):
使用AverageAbsoluteDifferenceRecommenderEvaluator和RMSRecommenderEvaluator來評估模型
通過RecommenderBuilder來實現(xiàn)評估模型
實現(xiàn)如下代碼:

package com.zdd.example;

import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.eval.RecommenderBuilder;
import org.apache.mahout.cf.taste.eval.RecommenderEvaluator;
import org.apache.mahout.cf.taste.impl.eval.AverageAbsoluteDifferenceRecommenderEvaluator;
import org.apache.mahout.cf.taste.impl.eval.RMSRecommenderEvaluator;
import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;
import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood;
import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.PearsonCorrelationSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood;
import org.apache.mahout.cf.taste.recommender.*;
import org.apache.mahout.cf.taste.similarity.UserSimilarity;

import java.io.File;

public class EvaluatorIntro {
    private EvaluatorIntro() {
    }

    public static void main(String[] args) throws Exception {
        final DataModel model = new FileDataModel(new File("data/ua.base"));
        RecommenderEvaluator evaluator = new AverageAbsoluteDifferenceRecommenderEvaluator();
        RecommenderEvaluator recommenderEvaluator = new RMSRecommenderEvaluator();

        RecommenderBuilder recommenderBuilder = new RecommenderBuilder() {
            @Override
            public Recommender buildRecommender(DataModel model) throws TasteException {
                UserSimilarity similarity = new PearsonCorrelationSimilarity(model);
                UserNeighborhood neighborhood = new NearestNUserNeighborhood(100, similarity, model);
                return new GenericUserBasedRecommender(model, neighborhood, similarity);
            }
        };
        //參數(shù)0.7表示評估的訓(xùn)練集為70%,1.0代表所有的用戶來參與評估
        double score = evaluator.evaluate(recommenderBuilder, null, model, 0.7, 1.0);
        double rmse = recommenderEvaluator.evaluate(recommenderBuilder, null, model, 0.7, 1.0);
        System.out.println(score);
        System.out.println(rmse);
    }
}

輸出結(jié)果如下:
0.8522242111918109
1.0888589811454357
從結(jié)果可以看到,平均絕對誤差大約為0.85,而均方根誤差大約為1.09,在這個不大的數(shù)據(jù)集中,這個結(jié)果還能接受。
我們可以更改第34行代碼來比較不同相似度的評分,這里用的相似度計算方式為皮爾森系數(shù):UserSimilarity similarity = new PearsonCorrelationSimilarity(model);
更改為歐幾里得:
UserSimilarity similarity = new EuclideanDistanceSimilarity(model);
更改為余弦相似度:
UserSimilarity similarity = new UncenteredCosineSimilarity(model);

實例5:推薦模型評估(2)

需求:
通過IR指標(biāo)來評估實例3的推薦系統(tǒng)的優(yōu)劣
實現(xiàn):
使用RecommenderIRStatsEvaluator來進行評估
實現(xiàn)代碼如下:

package com.zdd.example;

import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.eval.*;
import org.apache.mahout.cf.taste.impl.eval.GenericRecommenderIRStatsEvaluator;
import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;
import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood;
import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.PearsonCorrelationSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood;
import org.apache.mahout.cf.taste.recommender.*;
import org.apache.mahout.cf.taste.similarity.UserSimilarity;

import java.io.File;

public class IREvaluatorIntro {

    public static void main(String[] args) throws Exception {
        final DataModel model = new FileDataModel(new File("data/ua.base"));
        RecommenderIRStatsEvaluator evaluator = new GenericRecommenderIRStatsEvaluator();
        RecommenderBuilder recommenderBuilder = new RecommenderBuilder() {
            @Override
            public Recommender buildRecommender(DataModel model) throws TasteException {
                UserSimilarity similarity = new PearsonCorrelationSimilarity(model);
                UserNeighborhood neighborhood = new NearestNUserNeighborhood(100, similarity, model);
                return new GenericUserBasedRecommender(model, neighborhood, similarity);
            }
        };
        // 參數(shù)值5代表推薦5個商品,參數(shù)1.0代表全部用戶參與評估
        // 參數(shù)GenericRecommenderIRStatsEvaluator.CHOOSE_THRESHOLD代表Preference為多少時,兩個item時相關(guān)的,這個參數(shù)值代表
        // 我們在計算過程中自動調(diào)整這個閾值。
        IRStatistics stats = evaluator.evaluate(recommenderBuilder, null, model, null, 5, GenericRecommenderIRStatsEvaluator.CHOOSE_THRESHOLD, 1.0);
        System.out.println(stats.getPrecision());
        System.out.println(stats.getRecall());
        System.out.println(stats.getF1Measure());
    }
}

輸出結(jié)果如下:
0.011523687580025595
0.011523687580025595
0.011523687580025593
從結(jié)果可以看到,各項指標(biāo)比較低。這是因為我們的數(shù)據(jù)樣本還是很小,下一個實例將會使用相對大一些的數(shù)據(jù)集,電影數(shù)據(jù)集來進行實踐。

實例6:MovieLens推薦系統(tǒng)

需求:
使用MovieLens 1M數(shù)據(jù)集實現(xiàn)電影推薦系統(tǒng)
步驟:
實現(xiàn)MovieLens數(shù)據(jù)集的DataModel
實現(xiàn)Item-based和User-based的協(xié)同過濾推薦,并保存結(jié)果
實現(xiàn)代碼分三個代碼文件,1.數(shù)據(jù)預(yù)處理,2.Item-based實現(xiàn),3.User-based實現(xiàn)
1.數(shù)據(jù)預(yù)處理:

package com.zdd.MovieLens;

import org.apache.commons.io.Charsets;
import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;
import org.apache.mahout.common.iterator.FileLineIterable;

import java.io.*;
import java.util.regex.Pattern;

public class MovieLensDataModel extends FileDataModel {

    private static String COLON_DELIMITER="::";
    private static Pattern COLON_DELIMITER_PATTERN=Pattern.compile(COLON_DELIMITER);

    public MovieLensDataModel(File ratingsFile) throws IOException{
        super(convertFile(ratingsFile));
    }

    private static File convertFile(File orginalFile) throws IOException{
        File resultFile = new File(System.getProperty("java.io.tmpdir"), "ratings.csv");
        if (resultFile.exists()){
            resultFile.delete();
        }
        try(Writer writer = new OutputStreamWriter(new FileOutputStream(resultFile), Charsets.UTF_8)) {

            for (String line: new FileLineIterable(orginalFile, false)){
                int lastIndex = line.lastIndexOf(COLON_DELIMITER);

                if (lastIndex < 0 ){
                    throw new IOException("Invalid data!");
                }
                String subLine = line.substring(0, lastIndex);

                String convertedSubLine = COLON_DELIMITER_PATTERN.matcher(subLine).replaceAll(",");
                writer.write(convertedSubLine);
                writer.write('\n');
            }
        } catch (IOException ioe){
            resultFile.delete();
            throw ioe;
        }
        return resultFile;
    }
}

2.Item-based實現(xiàn):

package com.zdd.MovieLens;
import org.apache.mahout.cf.taste.impl.recommender.GenericItemBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.LogLikelihoodSimilarity;
import org.apache.mahout.cf.taste.impl.similarity.precompute.FileSimilarItemsWriter;
import org.apache.mahout.cf.taste.impl.similarity.precompute.MultithreadedBatchItemSimilarities;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.recommender.ItemBasedRecommender;
import org.apache.mahout.cf.taste.similarity.ItemSimilarity;
import org.apache.mahout.cf.taste.similarity.precompute.BatchItemSimilarities;
import org.apache.mahout.cf.taste.similarity.precompute.SimilarItemsWriter;

import java.io.File;

public class BatchItemSimilaritiesMovieLens {
    private BatchItemSimilaritiesMovieLens(){
    }

    public static void main(String[] args) throws Exception{

        if (args.length !=1){
            System.err.println("Needs MovieLens 1M dataset as arugument!");
            System.exit(-1);
        }

        File resultFile = new File(System.getProperty("java.io.tmpdir"), "similarities.csv");

        DataModel dataModel = new MovieLensDataModel(new File(args[0]));
        ItemSimilarity similarity = new LogLikelihoodSimilarity(dataModel);
        ItemBasedRecommender recommender = new GenericItemBasedRecommender(dataModel, similarity);
        //參數(shù)5代表相似物品的數(shù)量
        BatchItemSimilarities batchItemSimilarities = new MultithreadedBatchItemSimilarities(recommender, 5);

        SimilarItemsWriter writer = new FileSimilarItemsWriter(resultFile);

        int numSimilarites = batchItemSimilarities.computeItemSimilarities(Runtime.getRuntime().availableProcessors(), 1, writer);

        System.out.println("Computed "+ numSimilarites+ " for "+ dataModel.getNumItems()+" items and saved them to "+resultFile.getAbsolutePath());
    }
}

運行代碼,打印結(jié)果如下:



可以看到,在3706個物品中,有18530個相似物品的結(jié)果
并且在C:\Users\ADMINI~1\AppData\Local\Temp目錄下,會產(chǎn)生ratings.csv和similarities.csv兩個文件
similarities.csv數(shù)據(jù)如下:


3.User-based實現(xiàn)

package com.zdd.MovieLens;

import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.eval.RecommenderBuilder;
import org.apache.mahout.cf.taste.impl.eval.RMSRecommenderEvaluator;
import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood;
import org.apache.mahout.cf.taste.impl.recommender.CachingRecommender;
import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.PearsonCorrelationSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.Recommender;
import org.apache.mahout.cf.taste.similarity.UserSimilarity;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

public class UserRecommenderMovieLens {
    private UserRecommenderMovieLens(){
    }

    public static void main(String[] args) throws Exception {

        if (args.length != 1) {
            System.err.println("Needs MovieLens 1M dataset as arugument!");
            System.exit(-1);
        }

        File resultFile = new File(System.getProperty("java.io.tmpdir"), "userRcomed.csv");

        DataModel dataModel = new MovieLensDataModel(new File(args[0]));
        UserSimilarity similarity = new PearsonCorrelationSimilarity(dataModel);
        UserNeighborhood neighborhood = new NearestNUserNeighborhood(100, similarity, dataModel);

        Recommender recommender = new GenericUserBasedRecommender(dataModel, neighborhood, similarity);
        Recommender cachingRecommender = new CachingRecommender(recommender);

        //Evaluate
        RMSRecommenderEvaluator evaluator = new RMSRecommenderEvaluator();
        RecommenderBuilder recommenderBuilder = new RecommenderBuilder() {
            @Override
            public Recommender buildRecommender(DataModel dataModel) throws TasteException {
                UserSimilarity similarity = new PearsonCorrelationSimilarity(dataModel);
                UserNeighborhood neighborhood = new NearestNUserNeighborhood(100, similarity, dataModel);
                return new GenericUserBasedRecommender(dataModel, neighborhood, similarity);
            }
        };
        double score = evaluator.evaluate(recommenderBuilder, null, dataModel, 0.9, 0.5);
        System.out.println("RMSE score is "+score);

        try(PrintWriter writer = new PrintWriter(resultFile)){
            for (int userID=1; userID <= dataModel.getNumUsers(); userID++){
                List<RecommendedItem> recommendedItems = cachingRecommender.recommend(userID, 2);
                String line = userID+" : ";
                for (RecommendedItem recommendedItem: recommendedItems){
                    line += recommendedItem.getItemID()+":"+recommendedItem.getValue()+",";
                }
                if (line.endsWith(",")){
                    line = line.substring(0, line.length()-1);
                }
                writer.write(line);
                writer.write('\n');
            }
        } catch (IOException ioe){
            resultFile.delete();
            throw ioe;
        }
        System.out.println("Recommended for "+dataModel.getNumUsers()+" users and saved them to "+resultFile.getAbsolutePath());
    }
}

運行代碼,結(jié)果如下:
RMSE score is 1.0747072266152768
Recommended for 6040 users and saved them to C:\Users\ADMINI~1\AppData\Local\Temp\userRcomed.csv
打開userRcomed.csv文件,如下:
1 : 32:5.0,28:5.0
2 : 2726:5.0,2607:5.0
3 : 2624:5.0,1262:5.0
使用電影數(shù)據(jù)集,給每個用戶推薦了2個打分最高的商品。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容