基於用戶的協同過濾推薦算法WEB版代碼實現
(包含輸出用戶-評分矩陣模型、用戶間相似度、最近鄰居、推薦結果、平均絕對誤差MAE、查準率、召回率)
一、開發工具及使用技術
MyEclipse10、jdk1.7、mahout API、movielens數據集。
二、實現過程
1、定義用戶-電影評分矩陣:
/**
* 用戶-電影評分矩陣工具類
*/
public class DataModelUtil {
//定義用戶-電影評分矩陣
private static DataModel model = null ;
//初始化數據
static{
try {
//找到用戶-電影評分文件
// File file = new File(Constant.dataPath+Constant.rateFile);
// model = new FileDataModel(file);//實例化數據源
//jar包中的文件必須改成文件流進行操作,而且數據文件必須放在src文件夾下
InputStream inputStream = DataModelUtil.class.getClassLoader().
getResourceAsStream(Constant.dataPath+Constant.rateFile);
File file = new File("d://"+Constant.rateFile);
if (!file.exists())
file.createNewFile();
OutputStream outputStream = new FileOutputStream(file);
int bytesRead = 0;
byte[] buffer = new byte[1024];
while ((bytesRead = inputStream.read(buffer, 0, 1024)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.close();
inputStream.close();
model = new FileDataModel(file);//實例化數據源
// File file = new File(Constant.dataPath+Constant.rateFile2);
// model = new FileDataModel(file, "::");//實例化數據源
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 得到用戶-電影評分矩陣
* @return
*/
public static DataModel getDataModel(){
return model;
}
/**
* 獲取矩陣中的所有用戶
* @return
*/
public static LongPrimitiveIterator getUserids(){
try {
return model.getUserIDs();
} catch (TasteException e) {
e.printStackTrace();
}
return null;
}
/**
* 獲取矩陣中的所有電影
* @return
*/
public static LongPrimitiveIterator getItemids(){
try {
return model.getItemIDs();
} catch (TasteException e) {
e.printStackTrace();
}
return null;
}
/**
* 根據用戶id和電影id找到評分
* @param userid
* @param itemid
* @return
*/
public static Float getPreferenceValue(long userid,long itemid){
try {
return model.getPreferenceValue(userid,itemid);
} catch (TasteException e) {
e.printStackTrace();
}
return null;
}
}
2、計算用戶之間的相似度:
/**
* 相似度工具類
*/
public class SimilarityUtil {
/**
* 獲取用戶相似度對象
* @param dataModel
* @return
*/
public static UserSimilarity getUserSimilarity(DataModel dataModel){
return (UserSimilarity) getPearsonSimilarity(dataModel);
}
/**
* 使用pearson皮爾森相似度算法
* @param dataModel
* @return
*/
private static Object getPearsonSimilarity(DataModel dataModel){
try {
return new PearsonCorrelationSimilarity(dataModel);
} catch (TasteException e) {
e.printStackTrace();
}
return null;
}
}
3、計算目標用戶的最近鄰居:
/**
* 最近鄰居工具類
* @author line
*
*/
public class NearestNUserUtil {
/**
* 最近鄰居工具方法
* @param userSimilarity
* @param dataModel
* @return
*/
public static UserNeighborhood getNearestNUser(UserSimilarity userSimilarity,
DataModel dataModel){
try {
return new NearestNUserNeighborhood(Constant.knn, userSimilarity, dataModel);
} catch (TasteException e) {
e.printStackTrace();
}
return null;
}
}
4、定義推薦器:
/**
* 推薦器工具類
* @author line
*
*/
public class RecommendUtil {
public static Recommender getRecommend(DataModel dataModel,
UserNeighborhood neighborhood,UserSimilarity userSimilarity){
return new GenericUserBasedRecommender(dataModel, neighborhood, userSimilarity);
}
}
5、計算MAE、precision、recall:
/**
* 協同過濾算法評判標準類
*/
public class JudgeUtil {
// public static void main(String[] args) {
// getJudge();
// }
/**
* 協同過濾算法評判標準方法
*/
public static void getJudge(){
System.out.println("計算平均絕對誤差MAE、查準率、召回率開始");
try {
RandomUtils.useTestSeed();
//這裡使用的評估方法--平均差值
RecommenderEvaluator evaluator = new AverageAbsoluteDifferenceRecommenderEvaluator();
/*
我們創建了一個推薦器生成器
因為評估的時候我們需要將源數據中的一部分作為測試數據,其他作為算法的訓練數據
需要通過新訓練的DataModel構建推薦器,所以採用生成器的方式生成推薦器
*/
RecommenderBuilder builder = new RecommenderBuilder() {
public Recommender buildRecommender(DataModel dataModel) throws TasteException {
UserSimilarity userSimilarity = SimilarityUtil.getUserSimilarity(dataModel);
LongPrimitiveIterator userids = DataModelUtil.getUserids();
UserNeighborhood neighborhood = NearestNUserUtil.getNearestNUser(userSimilarity, dataModel);
return RecommendUtil.getRecommend(dataModel, neighborhood, userSimilarity);
}
};
/*
RecommenderEvaluator負責將數據分為訓練集和測試集,用訓練集構建一個DataModel和Recommender用來進行測試活動,得到結果之後在於真實數據進行比較。
參數中0.7代表訓練數據為70%,測試數據是30%。最後的1.0代表的是選取數據集的多少數據做整個評估。
此處第二個null處,使用null就可以滿足基本需求,但是如果我們有特殊需求,比如使用特殊的DataModel,在這裡可以使用DataModelBuilder的一個實例。
*/
double score = evaluator.evaluate(builder, null, DataModelUtil.getDataModel(),
Constant.trainCount, Constant.testCount);
/*
最後得出的評估值越小,說明推薦結果越好
最後的評價結果是0.943877551020408,表示的是平均與真實結果的差值是0.9.
*/
System.out.println("平均絕對誤差MAE:"+score);
/*
計算推薦4個結果時的查準率和召回率,使用評估器,並設定評估期的參數
4表示"precision and recall at 4"即相當於推薦top4,然後在top-4的推薦上計算準確率和召回率
查準率為0.75 上面設置的參數為4,表示 Precision at 4(推薦4個結果時的查準率),平均有3/4的推薦結果是好的
Recall at 4 推薦兩個結果的查全率是1.0 表示所有的好的推薦都包含在這些推薦結果中
*/
RandomUtils.useTestSeed();
RecommenderIRStatsEvaluator statsEvaluator = new GenericRecommenderIRStatsEvaluator();
IRStatistics stats = statsEvaluator.evaluate(builder, null, DataModelUtil.getDataModel(),
null, Constant.cfCount, GenericRecommenderIRStatsEvaluator.CHOOSE_THRESHOLD, 1.0);
System.out.println("查準率:"+stats.getPrecision());
System.out.println("召回率:"+stats.getRecall());
}
catch (Exception e) {e.printStackTrace();
}
System.out.println("計算平均絕對誤差MAE、查準率、召回率結束");
}
}
三、運行結果
1、用戶-電影評分矩陣:
2、用戶相似度:
3、用戶最近鄰:
4、推薦結果:
5、MAE、precision、recall結果:
歡迎留言、私信交流或關注博客https://blog.csdn.net/u011291472
閱讀更多 搞笑來了了 的文章