協同過濾算法——推薦引擎比你更了解你自己



1. 背景
  在數據爆炸我們每天被數據困擾的今天,數據量發生指數級的增長,每一年產生的大數據是過去歷史的總和。那么在茫茫數據大海中,對於數據生產者,怎么將自己的信息精准投放給所需的用戶呢?而對於數據消費者,怎么從海量數據中快速獲取自己需要的信息呢?這時推薦引擎應運而生。
  推薦應用其實已經走進我們的生活,典型的推薦應用:
a. 豆瓣網站
  豆瓣根據我的讀書列表,及相應評論,為我推薦出如下結果:

                       
b. 購物網站
  亞馬孫根據我的購書清單和相應書評,為我推薦的如下結果:
                      


1.1 問題抽象
    我們可以把推薦模型進行數據的抽象,假設有1,2,3,4和5個用戶分別各自購買了101,102,103至107物品中的物品,並對其進行了各自購買的物品進行評分,那么推薦引擎如何根據用戶喜好,推薦他們各自未買的物品呢?如下數據集:
           

2. 推薦引擎背景及算法

      如果你最近想看電影,你可能咨詢周圍的人,而且通常你更傾向詢問與“興趣相投”的人,從他們的口味中,得出一個最近電影排名集,來敲定你想看的電影,這是協同過濾的基本思想。圖解:

                   

 

  算法具體解決的兩個問題:
  a. 如何找到“興趣相投的”人群,形成一個群體,我們稱之為鄰域“neighborhood“。
  b. 如何從既定的鄰域中,排序出喜好的項目列表?

2.1 相似度
  如果我們把每個用戶的評分列表看成一個一維度向量,那么可以根據向量的相似度定量化用戶之間的相似性。相似度分類主要有:

 a. 基於歐幾里德距離計算相似度

  

 b. 基於 Cosine 相似度

  

 c. 基於皮爾遜相關系數計算相似度

 

 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/

5. http://blog.csdn.net/huagong_adu/article/details/7362908

6. http://blog.fens.me/mahout-recommendation-api/#gsc.tab=0


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM