推薦系統| 基於協同過濾


 

3. 基於協同過濾的推薦算法 (用戶和物品的關聯)

                    

 

                 

 

 

   協同過濾(Collaborative Filtering,CF)-- 用戶和物品之間關聯的用戶行為數據

  • ①基於近鄰的協同過濾 

    基於用戶(User-CF) --用戶畫像
    基於物品(Item-CF) -- 基於內容-特征工程

  • ②基於模型的協同過濾

    奇異值分解(SVD)
    潛在語義分析(LSA)
    支撐向量機(SVM)

             

協同過濾CF -- 用戶行為數據

  • 基於內容(Content based,CB)(物品的信息拿不到基於內容就無法做了)主要利用的是用戶評價過的物品的內容特征,而CF方法還可以利用其他用戶評分過的物品內容
  • CF 可以解決 CB 的一些局限 (用戶評價可得出物品的好壞,但CF無法做出冷啟動,基於大量數據)

    物品內容不完全或者難以獲得時,依然可以通過其他用戶的反饋給出推薦
    CF基於用戶之間對物品的評價質量,避免了CB僅依賴內容可能造成的對物品質量判斷的干擾
    CF推薦不受內容限制,只要其他類似用戶給出了對不同物品的興趣,CF就可以給用戶推薦出內容差異很大的物品(但有某種內在聯系)

  • 分為兩類:基於近鄰和基於模型

①. 基於近鄰的推薦

基於近鄰(基於用戶之間的關聯)的推薦系統根據的是相同“口碑”准則

是否應該給Cary推薦《泰坦尼克號》?

           

 基於用戶的協同過濾(User-CF) 用戶的行為數據

            

  • 基於用戶的協同過濾推薦的基本原理是,根據所有用戶對物品的偏好,發現與當前用戶口味和偏好相似的“鄰居”用戶群,並推薦近鄰所偏好的物品
  • 在一般的應用中是采用計算“K- 近鄰”的算法;基於這 K 個鄰居的歷史偏好信息,為當前用戶進行推薦
  • User-CF 和基於人口統計學的推薦機制 

    兩者都是計算用戶的相似度,並基於相似的“鄰居”用戶群計算推薦
    它們所不同的是如何計算用戶的相似度:基於人口統計學的機制只考慮用戶本身的特征,而基於用戶的協同過濾機制可是在用戶的歷史偏好的數據上計算用戶的相似度,它的基本假設是,喜歡類似物品的用戶可能有相同或者相似的口味和偏好

基於物品的協同過濾(Item-CF) 

       

  • 基於項目的協同過濾推薦的基本原理與基於用戶的類似,只是使用所有用戶對物品的偏好,發現物品和物品之間的相似度,然后根據用戶的歷史偏好信息,將類似的物品推薦給用戶
  • Item-CF 和基於內容(CB)的推薦

      其實都是基於物品相似度預測推薦,只是相似度計算的方法不一樣,前者是從用戶歷史的偏好推斷,而后者是基於物品本身的屬性特征信息

  • 同樣是協同過濾,在基於用戶和基於項目兩個策略中應該如何選擇呢?

    電商、電影、音樂網站,用戶數量遠大於物品數量
    新聞網站,物品(新聞文本)數量可能大於用戶數量

User-CF 和 Item-CF 的比較

同樣是協同過濾,在 User-CF 和 Item-CF 兩個策略中應該如何選擇呢?
Item-CF 應用場景  -- 用戶行為數據 -- 主流
  基於物品的協同過濾(Item-CF)推薦機制是 Amazon 在基於用戶的機制上改良的一種策略。因為在大部分的 Web 站點中,物品的個數是遠遠小於用戶的數量的,而且物品的個數和相似度相對比較穩定,同時基於物品的機制比基於用戶的實時性更好一些,所以 Item-CF 成為了目前推薦策略的主流
User-CF 應用場景
  設想一下在一些新聞推薦系統中,也許物品——也就是新聞的個數可能大於用戶的個數,而且新聞的更新程度也有很快,所以它的相似度依然不穩定,這時用 User-CF可能效果更好;
  所以,推薦策略的選擇其實和具體的應用場景有很大的關系

基於協同過濾的推薦優缺點

優點:
  它不需要對物品或者用戶進行嚴格的建模,而且不要求對物品特征的描述是機器可理解的,所以這種方法也是領域無關的
  這種方法計算出來的推薦是開放的,可以共用他人的經驗,很好的支持用戶發現潛在的興趣偏好
存在的問題:
  方法的核心是基於歷史數據,所以對新物品和新用戶都有“冷啟動”的問題
  推薦的效果依賴於用戶歷史偏好數據的多少和准確性
  在大部分的實現中,用戶歷史偏好是用稀疏矩陣進行存儲的,而稀疏矩陣上的計算有些明顯的問題,包括可能少部分人的錯誤偏好會對推薦的准確度有很大的影響等等
  對於一些特殊品味的用戶不能給予很好的推薦

②基於模型的協同過濾思想

基本思想
  用戶具有一定的特征,決定着他的偏好選擇;
  物品具有一定的特征,影響着用戶需是否選擇它;
  用戶之所以選擇某一個商品,是因為用戶特征與物品特征相互匹配;
基於這種思想,模型的建立相當於從行為數據中提取特征,給用戶和物品同時打上“標簽”;這和基於人口統計學的用戶標簽、基於內容方法的物品標簽本質是一樣的,都是特征的提取和匹配;
有顯性特征時(比如用戶標簽、物品分類標簽)我們可以直接匹配做出推薦;沒有時,可以根據已有的偏好數據,去發掘出隱藏的特征,這需要用到隱語義模型(LFM)

  基於模型的協同過濾推薦,就是基於樣本的用戶偏好信息,訓練一個推薦模型,然后根據實時的用戶喜好的信息進行預測新物品的得分,計算推薦
基於近鄰的推薦和基於模型的推薦 -- 用的都是用戶行為數據
  基於近鄰的推薦是在預測時直接使用已有的用戶偏好數據,通過近鄰數據來預測對新物品的偏好(類似分類)
  而基於模型的方法,是要使用這些偏好數據來訓練模型,找到內在規律,再用模型來做預測(類似回歸)
訓練模型時,可以基於標簽內容來提取物品特征,也可以讓模型去發掘物品的潛在特征;這樣的模型被稱為 隱語義模型(Latent Factor Model,LFM)

隱語義模型(LFM)

用隱語義模型來進行協同過濾的目標
  揭示隱藏的特征,這些特征能夠解釋為什么給出對應的預測評分
  這類特征可能是無法直接用語言解釋描述的,事實上我們並不需要知道,類似“玄學”
通過矩陣分解進行降維分析
  協同過濾算法非常依賴歷史數據,而一般的推薦系統中,偏好數據又往往是稀疏的;這就需要對原始數據做降維處理
  分解之后的矩陣,就代表了用戶和物品的隱藏特征
隱語義模型的實例:
  基於概率的隱語義分析(pLSA)
  隱式迪利克雷分布模型(LDA)
  矩陣因子分解模型(基於奇異值分解的模型,SVD)

LFM 降維方法 —— 矩陣因子分解

假設用戶物品評分矩陣為 R,現在有 m 個用戶,n 個物品
我們想要發現 k 個隱類(用戶和物品的隱藏特征),我們的任務就是找到兩個矩陣 P 和 Q,使這兩個矩陣的乘積近似等於 R,即將用戶物品評分矩陣 R 分解成為兩個低維矩陣相乘:

            用戶的在m行中K個隱藏特征,

   

 矩陣因子分解

     

LFM 的進一步理解

  我們可以認為,用戶之所以給電影打出這樣的分數,是有內在原因的,我們可以挖掘出影響用戶打分的隱藏因素,進而根據未評分電影與這些隱藏因素的關聯度,決定此未評分電影的預測評分;
  應該有一些隱藏的因素,影響用戶的打分,比如電影:演員、題材、年代…甚至不一定是人直接可以理解的隱藏因子;
  找到隱藏因子,可以對 user 和 item 進行關聯(找到是由於什么使得 user 喜歡/不喜歡此 item,什么會決定 user 喜歡/不喜歡此 item),就可以推測用戶是否會喜歡某一部未看過的電影。

對於用戶看過的電影,會有相應的打分,但一個用戶不可能看過所有電影,對於用戶沒有看過的電影是沒有評分的,因此用戶評分矩陣大部分項都是空的,是一個稀疏矩陣

 如果我們能夠根據用戶給已有電影的打分推測出用戶會給沒有看過的電影的打分,那么就可以根據預測結果給用戶推薦他可能打高分的電影

矩陣因子分解

我們現在來做一個一般性的分析
一個 m×n 的打分矩陣 R 可以用兩個小矩陣 Pm×k 和 Qk×n 的乘積 𝑅 ̂ 來近似:

          

得到 Pm×k 和 Qk×n 的乘積 𝑅 ̂ 不再是稀疏的,之前 R 中沒有的項也可以由 P、Q 的乘積算出,這就得到了一個 預測評分矩陣;

P定義的是一列,構成的用戶特征,某一個用戶的特征;Qi表示某個物品的特征向量;Rui表某一個用戶對物品的評分

       

如果得到的預測評分矩陣 𝑅 ̂ 與原評分矩陣 R 在已知評分位置上的值都近似,那么我們認為它們在預測位置上的值也是近似的

       

模型的求解 —— 損失函數

現在的問題是,怎樣得到這樣的分解方式 𝑅 ̂=𝑃×𝑄 呢?
矩陣分解得到的預測評分矩陣 𝑅 ̂,與原評分矩陣 R 在已知的評分項上可能會有誤差,我們的目標是找到一個最好的分解方式,讓分解之后的預測評分矩陣總誤差最小
損失函數
我們選擇平方損失函數,並且加入正則化項,以防過擬合

           

模型的求解算法 —— ALS

  現在,矩陣因子分解的問題已經轉化成了一個標准的優化問題,需要求解 P、Q,使目標損失函數取最小值
  最小化過程的求解,一般采用隨機梯度下降算法或者交替最小二乘法來實現
  交替最小二乘法(Alternating Least Squares,ALS):
  ALS的思想是,由於兩個矩陣P和Q都未知,且通過矩陣乘法耦合在一起,為了使它們解耦,可以先固定Q,把P當作變量,通過損失函數最小化求出P,這就是一個經典的最小二乘問題;再反過來固定求得的P,把Q當作變量,求解出Q:如此交替執行,直到誤差滿足閾值條件,或者到達迭代上限。

ALS算法具體過程如下:
  ① 為 Q 指定一個初值 Q0,可以是 隨機生成或者全局平均值
  ②固定當前 Q0 值,求解 P0
  ③固定當前 P0 值,求解 Q1
  ④固定當前 Q1 值,求解 P1
  ⑤…(重復以上過程)
  ⑥直到損失函數的值 C 收斂,迭代結束

求解過程
以固定 Q,求解 P為例
由於每一個用戶 u 都是相互獨立的,當 Q 固定時,用戶特征向量 Pu 應該取得的值與其它用戶特征向量無關;所以每一個 Pu 都可以單獨求解
優化目標 min┬(𝑃,𝑄)⁡𝐶 可轉化為

    

ALS 算法

   

   

 梯度下降算法

   

 

LFM梯度下降算法實現

import numpy as np
import pandas as pd

1. 數據准備
# 評分矩陣R
R = np.array([[4,0,2,0,1],
             [0,2,3,0,0],
             [1,0,2,4,0],
             [5,0,0,3,1],
             [0,0,1,5,1],
             [0,3,2,4,1],])
len(R[0])
====>
5

2. 算法實現

"""
@輸入參數:
R:M*N 的評分矩陣
K:隱特征向量維度
max_iter: 最大迭代次數
alpha:步長
lamda:正則化系數

@輸出:
分解之后的 P,Q
P:初始化用戶特征矩陣M*K
Q:初始化物品特征矩陣N*K
"""

# 給定超參數

K = 5
max_iter = 5000
alpha = 0.0002
lamda = 0.004

# 核心算法
def LFM_grad_desc( R, K=2, max_iter=1000, alpha=0.0001, lamda=0.002 ):
    # 基本維度參數定義
    M = len(R)
    N = len(R[0])
    
    # P,Q初始值,隨機生成
    P = np.random.rand(M, K)
    Q = np.random.rand(N, K)
    Q = Q.T
    
    # 開始迭代
    for step in range(max_iter):
        # 對所有的用戶u、物品i做遍歷,對應的特征向量Pu、Qi梯度下降
        for u in range(M):
            for i in range(N):
                # 對於每一個大於0的評分,求出預測評分誤差
                if R[u][i] > 0:
                    eui = np.dot( P[u,:], Q[:,i] ) - R[u][i]
                    
                    # 代入公式,按照梯度下降算法更新當前的Pu、Qi
                    for k in range(K):
                        P[u][k] = P[u][k] - alpha * ( 2 * eui * Q[k][i] + 2 * lamda * P[u][k] )
                        Q[k][i] = Q[k][i] - alpha * ( 2 * eui * P[u][k] + 2 * lamda * Q[k][i] )
        
        # u、i遍歷完成,所有特征向量更新完成,可以得到P、Q,可以計算預測評分矩陣
        predR = np.dot( P, Q )
        
        # 計算當前損失函數
        cost = 0
        for u in range(M):
            for i in range(N):
                if R[u][i] > 0:
                    cost += ( np.dot( P[u,:], Q[:,i] ) - R[u][i] ) ** 2
                    # 加上正則化項
                    for k in range(K):
                        cost += lamda * ( P[u][k] ** 2 + Q[k][i] ** 2 )
        if cost < 0.0001:
            break
        
    return P, Q.T, cost

3. 測試

P, Q, cost = LFM_grad_desc(R, K, max_iter, alpha, lamda)

print(P)
print(Q)
print(cost)

predR = P.dot(Q.T)

print(R)
predR

    

 

     

 


免責聲明!

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



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