Mahout學習系列之推薦演算法

Thinkgamer_gyt發表於2016-03-31


開啟微信掃一掃,關注微信公眾號【資料與演算法聯盟】


轉載請註明出處:http://blog.csdn.net/gamer_gyt 
博主微博:http://weibo.com/234654758 
Github:https://github.com/thinkgamer

參考:

從原始碼剖析Mahout推薦引擎      

mahout 推薦系統示例       

Mahout推薦演算法API詳解

使用Mahout實現協同過濾 

Mahout的taste推薦系統裡的幾種Recommender分析


前言:Mahout框架整合了大量的常用的機器學習演算法,且都支援在Hadoop分散式環境下執行,很大程度上節約了資料處理的時間成本,其中的推薦演算法引擎有cf.taste包實現,它提供了一套完整的推薦演算法工具庫,同時規範了資料結構,並標準了程式開發過程。


1:Mahout推薦演算法介紹

2:Taste介面相關介紹

3:單機記憶體演算法實現

4:基於hadoop分散式演算法的實現

5:演算法評判標準



一:Mahout推薦演算法介紹

我們先看看一下org.apache.mahout.cf.taste如下圖所示


packages的說明:

common:公共類包括,異常,資料重新整理介面,權重常量

eval:定義構造器介面,類似於工廠模式(什麼是工廠模式請參考:http://blog.chinaunix.net/uid-25958655-id-4243289.html

model:定義資料型別介面
neighborhood:定義近鄰演算法的介面
recommender:定義推薦演算法的介面
similarity:定義相似度演算法介面
transforms:定義資料轉換介面
hadoop:基於hadoop的分散式演算法的實現類
impl:單機記憶體演算法實現類
從上面的packages情況來看,可以粗略的看出推薦引擎分為5個主要部分組成:資料模型,相似度演算法,近鄰演算法,推薦演算法,演算法評分器
從資料處理能力上看,演算法可以分為:單機記憶體演算法,基於hadoop的分散式演算法




二:Taste介面相關介紹

Mahout使用了Taste來提交協同過濾演算法的實現,它是一個基於Java實現的可擴充套件的,高效的推薦系統,Taste既實現了最基本的基於使用者的和基於內容的推薦演算法,同時也提供了擴充套件介面,使使用者可以方便的定義和實現自己的推薦演算法,同時,Taste不僅僅只適用於Java應用程式,它可以作為內部伺服器的一個元件以HTTP和Web Service的形式向外界提供推薦的邏輯,Taste的設計使它能滿足企業對推薦引擎在效能,靈活性和可擴充套件性等方面的要求。

Taste主要包括以下幾個介面:

  • DataModel 是使用者喜好資訊的抽象介面,它的具體實現支援從任意型別的資料來源抽取使用者喜好資訊。Taste 預設提供 JDBCDataModel 和 FileDataModel,分別支援從資料庫和檔案中讀取使用者的喜好資訊。
  • UserSimilarity 和 ItemSimilarity 。UserSimilarity 用於定義兩個使用者間的相似度,它是基於協同過濾的推薦引擎的核心部分,可以用來計算使用者的“鄰居”,這裡我們將與當前使用者口味相似的使用者稱為他的鄰居。ItemSimilarity 類似的,計算內容之間的相似度。
  • UserNeighborhood 用於基於使用者相似度的推薦方法中,推薦的內容是基於找到與當前使用者喜好相似的鄰居使用者的方式產生的。UserNeighborhood 定義了確定鄰居使用者的方法,具體實現一般是基於 UserSimilarity 計算得到的。
  • Recommender 是推薦引擎的抽象介面,Taste 中的核心元件。程式中,為它提供一個 DataModel,它可以計算出對不同使用者的推薦內容。實際應用中,主要使用它的實現類 GenericUserBasedRecommender 或者 GenericItemBasedRecommender,分別實現基於使用者相似度的推薦引擎或者基於內容的推薦引擎。
  • RecommenderEvaluator :評分器。
  • RecommenderIRStatsEvaluator :蒐集推薦效能相關的指標,包括準確率、召回率等等。

目前,Mahout為DataModel提供了以下幾種實現:

  • org.apache.mahout.cf.taste.impl.model.GenericDataModel
  • org.apache.mahout.cf.taste.impl.model.GenericBooleanPrefDataModel
  • org.apache.mahout.cf.taste.impl.model.PlusAnonymousUserDataModel
  • org.apache.mahout.cf.taste.impl.model.file.FileDataModel
  • org.apache.mahout.cf.taste.impl.model.hbase.HBaseDataModel
  • org.apache.mahout.cf.taste.impl.model.cassandra.CassandraDataModel
  • org.apache.mahout.cf.taste.impl.model.mongodb.MongoDBDataModel
  • org.apache.mahout.cf.taste.impl.model.jdbc.SQL92JDBCDataModel
  • org.apache.mahout.cf.taste.impl.model.jdbc.MySQLJDBCDataModel
  • org.apache.mahout.cf.taste.impl.model.jdbc.PostgreSQLJDBCDataModel
  • org.apache.mahout.cf.taste.impl.model.jdbc.GenericJDBCDataModel
  • org.apache.mahout.cf.taste.impl.model.jdbc.SQL92BooleanPrefJDBCDataModel
  • org.apache.mahout.cf.taste.impl.model.jdbc.MySQLBooleanPrefJDBCDataModel
  • org.apache.mahout.cf.taste.impl.model.jdbc.PostgreBooleanPrefSQLJDBCDataModel
  • org.apache.mahout.cf.taste.impl.model.jdbc.ReloadFromJDBCDataModel

從類名上就可以大概猜出來每個DataModel的用途,奇怪的是竟然沒有HDFS的DataModel,有人實現了一個,請參考 MAHOUT-1579 。

UserSimilarity 和 ItemSimilarity 相似度實現有以下幾種:

  • CityBlockSimilarity :基於Manhattan距離相似度
  • EuclideanDistanceSimilarity :基於歐幾里德距離計算相似度
  • LogLikelihoodSimilarity :基於對數似然比的相似度
  • PearsonCorrelationSimilarity :基於皮爾遜相關係數計算相似度
  • SpearmanCorrelationSimilarity :基於皮爾斯曼相關係數相似度
  • TanimotoCoefficientSimilarity :基於谷本系數計算相似度
  • UncenteredCosineSimilarity :計算 Cosine 相似度

以上相似度的說明,請參考Mahout推薦引擎介紹。

UserNeighborhood 主要實現有兩種:

  • NearestNUserNeighborhood:對每個使用者取固定數量N個最近鄰居
  • ThresholdUserNeighborhood:對每個使用者基於一定的限制,取落在相似度限制以內的所有使用者為鄰居

Recommender分為以下幾種實現:

  • GenericUserBasedRecommender:基於使用者的推薦引擎
  • GenericBooleanPrefUserBasedRecommender:基於使用者的無偏好值推薦引擎
  • GenericItemBasedRecommender:基於物品的推薦引擎
  • GenericBooleanPrefItemBasedRecommender:基於物品的無偏好值推薦引擎

RecommenderEvaluator有以下幾種實現:

  • AverageAbsoluteDifferenceRecommenderEvaluator :計算平均差值
  • RMSRecommenderEvaluator :計算均方根差

RecommenderIRStatsEvaluator的實現類是GenericRecommenderIRStatsEvaluator。


三:單機記憶體演算法實現

Mahout推薦演算法API詳解
單機演算法實現:就是在單機環境下執行的演算法,是由cf.taste專案實現的,象我們熟悉的User_CF,Item_CF都是支援單機執行的,並且引數可以靈活配置,單機演算法實現的例項如下:
測試資料集如下:/home/thinkgamer/test.txt


單機演算法實現參考:

mahout 推薦系統示例

1,101,5
1,102,3
1,103,2.5
2,101,2
2,102,2.5
2,103,5
2,104,2
3,101,2.5
3,104,4
3,105,4.5
3,107,5
4,101,5
4,103,3
4,104,4.5
4,106,4
5,101,4
5,102,3
5,103,2
5,104,4
5,105,3.5
5,106,4

實現的程式碼如下:

package tuijian_alone;

import java.io.*;
import java.util.*;
import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.impl.model.file.*;
import org.apache.mahout.cf.taste.impl.neighborhood.*;
import org.apache.mahout.cf.taste.impl.recommender.*;
import org.apache.mahout.cf.taste.impl.recommender.slopeone.SlopeOneRecommender;
import org.apache.mahout.cf.taste.impl.similarity.*;
import org.apache.mahout.cf.taste.model.*;
import org.apache.mahout.cf.taste.neighborhood.*;
import org.apache.mahout.cf.taste.recommender.*;
import org.apache.mahout.cf.taste.similarity.*;


public class tuijian_alone {
	// private TestMahout(){};


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

		tuijian_alone testMahout = new tuijian_alone();
		System.out.println("The baseUserCF Result:");
		testMahout.baseUserCF();
		System.out.println("The baseItemCF Result:");
		testMahout.baseItemCF();
		System.out.println("The baseSlopOne Result:");
		testMahout.baseSlopOne();
	}
	//基於使用者相似度的協同過濾推薦實現
	public void baseUserCF(){	
		try {
			// 1,構建模型
			DataModel dataModel = new FileDataModel(new File("../test.txt"));
			//2,計算相似度
			UserSimilarity userSimilarity = new PearsonCorrelationSimilarity(dataModel);
			//3,查詢K近鄰
			UserNeighborhood userNeighborhood = new NearestNUserNeighborhood(2, userSimilarity, dataModel);
			//4,構造推薦引擎
			Recommender recommender = new GenericUserBasedRecommender(dataModel, userNeighborhood, userSimilarity);
			//為使用者i推薦2個item
			for(int i=1;i<6;i++){
				System.out.println("recommand for user:" + i);
				List  recommendations = recommender.recommend(i, 2);
				for (RecommendedItem recommendation:recommendations){
					System.out.println(recommendation);
					}
				}
			}catch(IOException e){
				e.printStackTrace();
			}catch(TasteException e){
				e.printStackTrace();
			}
		}
	
	//基於內容相似度的協同過濾推薦實現
	public void baseItemCF(){
		DataModel model;
		try {
			model = new FileDataModel(new File("../test.txt"));
			ItemSimilarity itemsimilarity =new PearsonCorrelationSimilarity(model);
			Recommender recommender= new GenericItemBasedRecommender(model,itemsimilarity);
			List recommendations =recommender.recommend(1, 4);
			for(RecommendedItem recommendation :recommendations){
			   System.out.println(recommendation);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TasteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	//基於SlopOne的推薦實現
	public void baseSlopOne(){
		DataModel model;
		try {
			model = new FileDataModel(new File("/home/thinkgamer/Java/hadoop_shizhan/src/tuijian_alone/test.txt"));
			Recommender recommender= new SlopeOneRecommender(model);
			List recommendations =recommender.recommend(1, 4);
			for(RecommendedItem recommendation :recommendations){
			   System.out.println(recommendation);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println("Io Error");
			e.printStackTrace();
		} catch (TasteException e) {
			// TODO Auto-generated catch block
			System.out.println("Taste Error");
			e.printStackTrace();
		}

	}
	
}

執行結果如下圖所示:



單機記憶體演算法的問題在於:受限於單機的資源,對於中等規模的資料,有能力計算,但是超過100G的資料對於單機來說是不可能完成的任務


四:基於Hadoop分散式演算法實現

基於hadoop分散式演算法的實現,就是把單機記憶體演算法並行優化,把任務分散到多個計算機上一起執行,Mahout提供了基於ItemCFhadoop並行化演算法實現,基於hadoop分散式演算法實現參考:Mahout分步式程式開發 基於物品的協同過濾ItemCF

分散式演算法的問題在於,如何讓單機演算法並行化,在單機演算法中,我們只需要考慮演算法,資料結構,記憶體,CPU就夠了,但是分散式演算法還要額外考慮很多情況,比如多結點的資料合併,資料排序,網路通訊故障,節點當機重算,資料分散式儲存等等很多問題

並行化演算法實現參考:用Mahout構建職位推薦引擎   


五:演算法評判標準:召回率(recall)與查準率(precision)

Mahout提供了2個評估推薦器的指標,查準率和召回率(查全率),這兩個指標是搜尋引擎中經典的度量方法。


                   相關 不相關
檢索到          A        C
未檢索到      B        D
  • A:檢索到的,相關的 (搜到的也想要的)
  • B:未檢索到的,但是相關的 (沒搜到,然而實際上想要的)
  • C:檢索到的,但是不相關的 (搜到的但沒用的)
  • D:未檢索到的,也不相關的 (沒搜到也沒用的)

被檢索到的越多越好,這是追求“查全率”,即A/(A+B),越大越好。
被檢索到的,越相關的越多越好,不相關的越少越好,這是追求“查準率”,即A/(A+C),越大越好。

在大規模資料集合中,這兩個指標是相互制約的。當希望索引出更多的資料的時候,查準率就會下降,當希望索引更準確的時候,會索引更少的資料。


相關文章