基於用戶的協同過濾推薦算法


概述

計算機網絡技術帶給人們的最大貢獻之一就是數據的共享,如何使得我們的項目更加“深入人心”是我們需要不斷思考的方向。很多的項目都需要給用戶提供數據(例如博客、知識等),但是海量的數據從某種程度上會降低用戶獲取有用信息的效率。項目如果能給用戶推薦他們感興趣的博客,做到真正的“千人千面”,那將使得我們的項目更加智能,更加具有市場競爭力。

目前常用的推薦算法有:協同過濾、矩陣分解、聚類、深度學習等等,這里我主要聊聊基於用戶的系統過濾推薦算法。

原理

思想

協同過濾算法是一個大類,主要有基於用戶、基於物品、兩者結合等分支,這里我主要介紹的是基於用戶的協同過濾算法,這也是我在軟工實踐中使用過的算法。

主要的思想也很簡單,中國有一句俗語“物以類聚,人以群分”,我們可以有很大的把握認為一個和你很相似的用戶喜歡的物品也大概率也是你喜歡的物品,這就是基於用戶的協同過濾推薦算法的思想。

流程圖

圖片

步驟一:計算用戶相似度

相似度計算的方法有很多種,這里我主要采用的是余弦相似度:

圖片

算法比較簡單,主要是計算一個用戶相似度矩陣,通過一個大根堆來維護topN的N個相似用戶列表。

相關代碼如下:

/**
 * 獲取用戶的MAX_ACCOUNT_NUMBER個最相似的用戶
 *
 * @param name 用戶ID
 * @return 優先隊列,按照用戶相似度從高到低排序
 */
private static Queue<SimilarAccount> getSimilarUsers(String name) {
    Long blogNum = accountBlogSize.get(name);
    if ((blogNum == null) || (blogNum < 1)) {
        return null;
    }
    // 用戶相似度矩陣
    long[][] similarityMatrix = new long[MAX_ACCOUNT_NUMBER][MAX_ACCOUNT_NUMBER];
    int temp = 0;
    // 用戶所對應的博客集
    for (Map.Entry<String, TreeSet<BlogInterest>> entry : accountBlogCollection.entrySet()) {
        nameId.put(entry.getKey(), temp);
        idName.put(temp, entry.getKey());
        temp = temp + 1;
    }
    for (Map.Entry<Long, Set<String>> longSetEntry : blogAccountCollection.entrySet()) {// 博客所對應的用戶集
        Set<String> as = longSetEntry.getValue();
        for (String accO : as) {
            for (String accT : as) {
                if (accO.equals(accT)) {
                    continue;
                }
                // 更新有相同感興趣物品的用戶相似度矩陣,主要進行標記,矩陣的值代表相同物品的個數
                similarityMatrix[nameId.get(accO)][nameId.get(accT)]++;
                similarityMatrix[nameId.get(accT)][nameId.get(accO)]++;
            }
        }
    }
    // 進一步計算用戶相似度矩陣
    Queue<SimilarAccount> similar = new PriorityQueue<>((o1, o2) -> (int) (o2.getSimilar() - o1.getSimilar()));
    Long accountNum = accountBlogSize.get(name);
    for (int i = 0; i < similarityMatrix.length; ++i) {
        if (!accountBlogSize.containsKey(idName.get(i))) {
            continue;
        }
        Long num = accountBlogSize.get(idName.get(i));
        if (!idName.get(i).equals(name)) {
            similar.add(new SimilarAccount(idName.get(i),
                similarityMatrix[nameId.get(name)][i] / Math.sqrt(num * accountNum)));
        }
    }
    return similar;
}

步驟二:獲取需要推薦給用戶的物品

這一個步驟主要是遍歷相似用戶列表,獲取到相似用戶訪問過而當前用戶未訪問過的物品,這些物品就是我們要推薦給用戶的物品。

在這里我們還可以進一步計算一下當前用戶可能對該物品的興趣度,興趣度的計算有很多方法,這里主要采用的是將相似用戶的相似度*相似用戶對該物品的興趣度,然后進行所有的用戶累加。最后按照興趣度進行排序后再推薦給用戶。

相關代碼如下:

// 獲取相似用戶訪問過,而當前用戶未訪問過的物品
while (!similarAccountQueue.isEmpty()) {
    String similarID = similarAccountQueue.poll().getName();
    Set<BlogInterest> siat = accountBlogCollection.get(similarID);
    for (BlogInterest ai : siat) {
        flag = false;
        for (BlogInterest bi : ait) {
            if (bi.getBlogID().intValue() == ai.getBlogID().intValue()) {
                flag = true;// 表示該物品兩個用戶都訪問過,跳過
                break;
            }
        }
        if (flag) {
            continue;
        }
        ans.add(IDBlog.get(ai.getBlogID()));// 添加需要推薦的物品
    }
}

問題

問題一:冷啟動問題

這個問題主要來自於,網站剛開始運行的時候,用戶數、用戶訪問量、用戶興趣度等數據較少,那么會導致推薦效果不好、推薦數據少等問題。

解決方法也很簡單,我們可以人為在推薦的算法里面設置一個最小的“閾值列表”,即如果在前期推薦結果不好的情況下默認使用該列表進行填充。

還有一種解決方法是和別的多種推薦算法進行結合,最終的結果進行加權后得出。比如我們可以默認把一些訪問量topN的而用戶沒訪問過的物品推薦給用戶。

// 解決部分冷啟動問題(最初物品數太少,導致推薦的物品太少)
for (Blog blog : baseBlog) {
    if (ans.size() > 500) {
        break;
    }
    flag = false;
    for (Blog blog1 : ans) {
        if (blog1.getId().intValue() == blog.getId().intValue()) {
            flag = true;
            break;
        }
    }
    if (!flag) {
        ans.add(blog);
    }
}

問題二:數據稀疏問題

從代碼中我們很容易可以看出,計算相似度的復雜度較高,是O(n^2)級別,然而當我們僅對數據庫中的一小部分進行操作時,就會導致數據變稀疏,這樣可能會帶來推薦效果、性能的下降。

這個問題是算法本身的缺陷,需要對算法進行改進,或者結合多種算法。

總結

協同過濾算法是較為傳統的算法,算法的實現原理較為簡單,有着各種各樣的問題,但是算法本身的思路是值得借鑒的。目前比較新的算法有搭建深度神經網絡進行學習的算法,這種算法的推薦效果較好,但是這種算法仍然需要大量的數據用於訓練。我認為基於用戶的協同過濾算法其實可以和傳統的一些機器學習算法進行結合。比如在相似用戶查找那,可以采用聚類算法,推薦的過程可以考慮對數據進行降維處理,僅保留有價值的數據等等。

參考文獻

[1]推薦系統:協同過濾及其利弊


免責聲明!

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



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