1. 程式人生 > >Mahout系列之推薦演算法-基於使用者協同過濾

Mahout系列之推薦演算法-基於使用者協同過濾

Mahout的一大特色就是包含了推薦演算法,裡面包括了多種常見的演算法,下面我們來分析分析。

針對基於使用者行為資料的推薦演算法一般稱為協同過濾演算法。協同過濾演算法有基於領域(neighborhood-based)的方法,隱語義模型(latent factor model)的方法,基於圖的隨機遊走(random walk on graph)演算法。目前用的最多的就是基於領域的方法,基於領域的演算法裡面主要有基於使用者的協同過濾演算法和基於物品的協同過濾演算法。下面幾點摘自mahout的官網關於推薦演算法的基本忠告

  • 不要一上來就來個分散式的基於Hadoop的推薦,除非必要;建議從非分散式的推薦開始,這樣簡單,靈活
  • 最為最佳實踐,系統在100M使用者-物品項的級別對4G記憶體現代伺服器來說是合適的可用的,能夠作為實時推薦執行起來
  • 超過了上述規模的可以考慮分散式系統,但是很多應用並沒有真的有100M的資料處理。很多資料可以簡化的,儘量修剪噪聲和舊的資料對結果沒有顯著的影響
  • 使用者和物品是否存在真的關聯,是否擁有真的使用者偏好資料。如果有使用者評級資料,可以考慮GenericItemBasedRecommender和PearsonCorrelationSimilarity 相似矩陣. 如果沒有則考慮GenericBooleanPrefItemBasedRecommender 和 LogLikelihoodSimilarity.
    如果想使用基於內容的item-item similarity,需要實現自己的ItemSimilarity.
  • CSV檔案可以使用 FileDataModel 資料儲存在資料庫可以使用MySQLJDBCDataModel (PostgreSQL counterpart, etc.) and R eloadFromJDBCDataModel。

1.基於使用者的協同過濾

按照官網推薦的實際,我們來個簡單的基於使用者的推薦引擎

1.1.準備資料  (dataset.csv)

3,12,4.5
3,13,4.0
3,14,3.0
3,15,3.5
3,16,4.5
3,17,4.0
3,18,5.0
4,10,5.0
4,11,5.0
4,12,5.0
4,13,0.0
4,14,2.0
4,15,3.0
4,16,1.0
4,17,4.0
4,18,1.0

1.2. 開始構建推薦模型

DataModel model = new FileDataModel(new File("data/dataset.csv"));  //讀取資料,獲得資料模型
UserSimilarity similarity = new PearsonCorrelationSimilarity(model);//構建使用者相似度評價方法,這裡用的是PearsonCorrelation相似度
UserNeighborhood neighborhood = new ThresholdUserNeighborhood(0.1, similarity, model);//使用預設的使用者近鄰閾值
UserBasedRecommender recommender = new GenericUserBasedRecommender(model, neighborhood, similarity);//計算得到推薦模型
List<RecommendedItem> recommendations = recommender.recommend(2, 3);//為使用者2,推薦3個物品
for (RecommendedItem recommendation : recommendations) {
System.out.println(recommendation);//列印每個物品ID
}

1.3.執行

將這個方法包裝下,放在main裡面就可以跑起來了。結果類似這樣:  INFO - Creating FileDataModel for file data\dataset.csv
  INFO - Reading file info...
  INFO - Read lines: 32
  INFO - Processed 4 users
 DEBUG - Recommending items for user ID '2'
 DEBUG - Recommendations are: [RecommendedItem[item:12, value:4.8328104], RecommendedItem[item:13, value:4.6656213], RecommendedItem[item:14, value:4.331242]]
 RecommendedItem[item:12, value:4.8328104]
RecommendedItem[item:13, value:4.6656213]
RecommendedItem[item:14, value:4.331242]

1.4千萬級別資料來執行

  生成資料,貼上程式碼為證:      public static void main(String[] args) {
int batchSize = 10000;
int recordsCnt = 30000000; //30M個
String fileName = "D:/tmp/recommandtestdata2.csv";
StringBuffer sb = new StringBuffer();
for (int i = 0; i < recordsCnt; i++) {
// System.out.println(i + "===" + (char) i);
if (sb == null) {
sb = new StringBuffer();
}
sb.append(getRandInt(1000000,1));// userId  1M個
sb.append(",");
sb.append(getRandInt(1000,1));// itemId
sb.append(",");
sb.append(getRandInt(5,1));// value
sb.append("\n");


if (i > 0 && (i % batchSize == 0)) {
System.out.println(i);
write2File(sb.toString(), fileName);// append data to file
sb = null;
}
}
}
      public static int getRandInt(int max, int min) {
return (int) (Math.random() * (max - min) + min);
}
     public static void write2File(String str, String path) {
RandomAccessFile myFileStream;
try {
myFileStream = new RandomAccessFile(path, "rw");
myFileStream.seek(myFileStream.length());
myFileStream.write((str).getBytes("UTF-8"));


// myFileStream.w
myFileStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
直接跑,肯定會出錯:  Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
at org.apache.mahout.cf.taste.impl.model.GenericUserPreferenceArray$1.apply(GenericUserPreferenceArray.java:251)
修改JVM options -Xmx2512M   INFO - Creating FileDataModel for file D:\tmp\recommandtestdata2.csv
  INFO - Reading file info...
  INFO - Processed 1000000 lines
  INFO - Processed 2000000 lines
  。。。。。。(此處省略)
  INFO - Processed 28000000 lines
  INFO - Processed 29000000 lines
  INFO - Read lines: 29990001
  INFO - Processed 10000 users
  INFO - Processed 20000 users   。。。。。。(此處省略)
  INFO - Processed 980000 users
  INFO - Processed 990000 users
  INFO - Processed 999999 users
 DEBUG - Recommending items for user ID '2'
 DEBUG - Recommendations are: [RecommendedItem[item:458, value:2.5922961], RecommendedItem[item:842, value:2.5879922], RecommendedItem[item:802, value:2.5861814]]
 RecommendedItem[item:458, value:2.5922961]
RecommendedItem[item:842, value:2.5879922]
RecommendedItem[item:802, value:2.5861814]
說明:本人是在個人PC(64位)上跑的,這樣足夠說明開始介紹的Mahout官網說的沒錯,100M的單機就可以了,剛剛的!