1. 背景
在數據爆炸咱們天天被數據困擾的今天,數據量發生指數級的增加,每年產生的大數據是過去歷史的總和。那麼在茫茫數據大海中,對於數據生產者,怎麼將本身的信息精準投放給所需的用戶呢?而對於數據消費者,怎麼從海量數據中快速獲取本身須要的信息呢?這時推薦引擎應運而生。
推薦應用其實已經走進咱們的生活,典型的推薦應用:
a. 豆瓣網站
豆瓣根據個人讀書列表,及相應評論,爲我推薦出以下結果:java
b. 購物網站
亞馬孫根據個人購書清單和相應書評,爲我推薦的以下結果:
web
1.1 問題抽象
咱們能夠把推薦模型進行數據的抽象,假設有1,2,3,4和5個用戶分別各自購買了101,102,103至107物品中的物品,並對其進行了各自購買的物品進行評分,那麼推薦引擎如何根據用戶喜愛,推薦他們各自未買的物品呢?以下數據集:
算法
2. 推薦引擎背景及算法api
若是你最近想看電影,你可能諮詢周圍的人,並且一般你更傾向詢問與「興趣相投」的人,從他們的口味中,得出一個最近電影排名集,來敲定你想看的電影,這是協同過濾的基本思想。圖解:ide
算法具體解決的兩個問題:
a. 如何找到「興趣相投的」人羣,造成一個羣體,咱們稱之爲鄰域「neighborhood「。
b. 如何從既定的鄰域中,排序出喜愛的項目列表?大數據
2.1 類似度
若是咱們把每一個用戶的評分列表當作一個一維度向量,那麼能夠根據向量的類似度定量化用戶之間的類似性。類似度分類主要有:網站
a. 基於歐幾里德距離計算類似度ui
b. 基於 Cosine 類似度idea
c. 基於皮爾遜相關係數計算類似度spa
d. 基於 Tanimoto 係數計算類似度
2.2 鄰域
物以類聚,既然咱們獲取了用戶之間的類似度值,那麼那些人羣歸爲一個鄰域呢?一般有兩種方法:
a. 規定 Fix-size,根據類似度值排名,取前fix-size的個數做爲一個鄰域
b. 規定threshold,類似度值大於規定值歸爲一個鄰域
2.3 推薦值計算
定量的計算推測用戶a對某個物品v的喜愛程度,公式以下: ΣSim(i,j)Vi
即爲其它各位用戶對物品v的評分值的線性加權平均,其中,權重是類似度值sim,v表示對各物品的評分。
因此整個計算的過程是經過2.1和2.2解決問題a,而後根據2.3解決問題b的過程。
2.4 推薦算法分類
典型的推薦算法有:基於用戶的推薦和基於物品的推薦兩種。
上述的思路從基於用戶的推薦方法講解的,而在實際電商網站應用中,因爲物品數量是遠遠大於每位用戶的購買數量的,並且用戶之間購買的物品重疊性較低,很難找到鄰域。這時,能夠換個從商品的角度思考,商品間的類似性。根據用戶購物歷史偏好,計算物品間的類似性,流程和基於用戶的推薦同樣。
3. mahout協同過濾的應用接口
3.1 類似度
類似度接口有UserSimilarity和ItemSimilarity,其主要方法以下:
double userSimilarity(long userID1, long userID2) double itemSimilarity(long itemID1, long itemID2)
其繼承類分別:
a. PearsonCorrelationSimilarity:基於皮爾遜相關係數計算類似度
b. EuclideanDistanceSimilarity:基於歐幾里德距離計算類似度
c. TanimotoCoefficientSimilarity:基於 Tanimoto 係數計算類似度
d. UncerteredCosineSimilarity:計算 Cosine 類似度
3.2 鄰域
鄰域類UserNeighborhood,其主要接口以下:
long[] getUserNeighborhood(long userID)
輸入給定用戶,給出與其類似的用戶列表
其繼承類分別:
a. NearestNUserNeighborhood:對每一個用戶取固定數量 N 的最近鄰居
b. ThresholdUserNeighborhood:對每一個用戶基於必定的限制,取落在類似度門限內的全部用戶爲鄰居。
3.3 Recommender
關聯數據模型和類似度算法模型,進行具體的計算,接口以下:
List<RecommendedItem> recommend(long userID, int howMany)
給定用戶id和推薦的結果個數,返回推薦的結果
3.4 各種圖關係以下:
4. 代碼樣例和推薦結果
4.1 mahout代碼樣例
public static void main(String[] args) throws IOException, TasteException { // TODO Auto-generated method stub System.out.println("starting "); String file = "item.csv"; DataModel model = new FileDataModel(new File(file)); System.out.println("starting userCF "); userCF(model); System.out.println(); System.out.println("starting itemCF"); itemCF(model); } public static void userCF(DataModel model) { try { UserSimilarity user = new UncenteredCosineSimilarity(model); NearestNUserNeighborhood neighbor = new NearestNUserNeighborhood(NEIGHBORHOOD_NUM, user, model); Recommender r = new GenericUserBasedRecommender(model, neighbor, user); LongPrimitiveIterator iter = model.getUserIDs(); while (iter.hasNext()) { long uid = iter.nextLong(); List<RecommendedItem> list = r.recommend(uid, RECOMMENDER_NUM); System.out.printf("user:%s", uid); for (RecommendedItem rItem : list) { System.out.printf("(%s,%f)", rItem.getItemID(), rItem.getValue()); } System.out.println(); } } catch (TasteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void itemCF(DataModel dataModel) { try { ItemSimilarity itemSimilarity = new UncenteredCosineSimilarity(dataModel); Recommender recommender = new GenericItemBasedRecommender(dataModel, itemSimilarity); Recommender cachingRecommender = new CachingRecommender(recommender); LongPrimitiveIterator iter = dataModel.getUserIDs(); while (iter.hasNext()) { long uid = iter.nextLong(); List<RecommendedItem> list = cachingRecommender.recommend(uid, RECOMMENDER_NUM); System.out.printf("user:%s", uid); for (RecommendedItem rItem : list) { System.out.printf("(%s,%f)", rItem.getItemID(), rItem.getValue()); } System.out.println(); } } catch (TasteException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
4.2 推薦結果
5. 評估標準
結果推薦出來,天然須要一套標準評判各自方法推薦的結果好壞。評價標準能夠參考http://blog.fens.me/mahout-recommendation-api/#gsc.tab=0的2節。
參考:
1. http://en.wikipedia.org/wiki/Collaborative_filtering
2. http://www.ibm.com/developerworks/cn/web/1103_zhaoct_recommstudy1/
3. https://www.ibm.com/developerworks/cn/web/1103_zhaoct_recommstudy2/
4. http://www.ibm.com/developerworks/cn/web/1103_zhaoct_recommstudy3/