天天看點

推薦算法——ALS模型算法分析、LFM算法推薦算法——ALS模型算法分析、LFM算法

文章目錄

  • 推薦算法——ALS模型算法分析、LFM算法
    • 簡介
    • ALS算法流程分析
    • LFM梯度下降算法-示例

推薦算法——ALS模型算法分析、LFM算法

簡介

  • ALS(Alternating Least Squares),即交替最小二乘法,因利用兩個矩陣進行交替優化而得名。求解大緻步驟如下:
    • 定義原始矩陣 A m , n = U m , k ∗ V k , n A_{m,n} = U_{m,k} * V_{k,n} Am,n​=Um,k​∗Vk,n​
    • 為 U m , k U_{m,k} Um,k​随機取值,固定 U m , k U_{m,k} Um,k​,利用最小二乘法求出 V k , n V_{k,n} Vk,n​
    • 固定 V k , n V_{k,n} Vk,n​,利用最小二乘法求出 U m , k U_{m,k} Um,k​
    • 持續交替進行求解,直到損失達到門檻值(即新矩陣近似于原始矩陣)
  • 比較經典的應用則是隐語義分析-推薦算法:原始矩陣為稀疏矩陣,通過ALS計算出的新矩陣則擁有原始矩陣缺失的值,即預測值。

ALS算法流程分析

  • 資料(矩陣 A m n A_{mn} Amn​)
    user/item 商品1 商品2 商品3 商品4
    使用者1 9 - 6 8
    使用者2 3 9 - 4
    使用者3 - - 6 8
    使用者4 9 8 5 9
    使用者5 8 7 6 -
    • 我們的原始資料是不同使用者對于不同商品的評分或喜好程度。因為使用者不可能買過每樣商品,是以會存在部分商品未評分的情況。
  • 算法目标:挖掘出使用者對未購買過的商品的喜好程度,也就是說要分析出原始稀疏矩陣 A m , n A_{m,n} Am,n​中的缺失值。
  • 利用ALS算法,将稀疏矩陣 A m , n A_{m,n} Am,n​拆解為兩個矩陣 U m , k U_{m,k} Um,k​ 、 V k , n V_{k,n} Vk,n​,即 A m , n = U m , k ∗ V k , n A_{m,n} = U_{m,k} * V_{k,n} Am,n​=Um,k​∗Vk,n​
    • k代表了使用者與商品的隐含關聯特征個數,需要使用者指定
    • U m , k U_{m,k} Um,k​代表了使用者與k個隐含特征的值
    • V k , n V_{k,n} Vk,n​代表了商品與k個隐含特征的值(不過是逆矩陣形式)
  • 按照ALS算法的流程,需要先固定矩陣 U m , k U_{m,k} Um,k​
    • 此處資料中:m=5,n=4。我們假定 k=3,并随機充填矩陣 U 5 , 3 U_{5,3} U5,3​
    • 得到的矩陣 U 5 , 3 U_{5,3} U5,3​,如下
      user/k k1 k2 k3
      使用者1 3 5 6
      使用者2 4 3 3
      使用者3 2 5 3
      使用者4 6 2 2
      使用者5 5 3 4
  • 此時,已知矩陣 A 5 , 4 A_{5,4} A5,4​部分值(稀疏)、矩陣 U 5 , 3 U_{5,3} U5,3​所有值,需要求解矩陣 V 3 , 4 V_{3,4} V3,4​
    • 未知矩陣 V 3 , 4 V_{3,4} V3,4​,如下
      k/item 商品1 商品2 商品3 商品4
      k1 w11 w12 w13 w14
      k2 w21 w22 w23 w24
      k3 w31 w32 w33 w34
  • 那麼該如何求解呢?不急,我們先看看矩陣乘法計算公式, U 5 , 3 ∗ V 3 , 4 = A 5 , 4 U_{5,3} * V_{3,4} = A_{5,4} U5,3​∗V3,4​=A5,4​的示例如下
    • 商品1與所有使用者的計算,如下
      • 3 ∗ w 11 + 5 ∗ w 21 + 6 ∗ w 31 = 9 3 * w_{11} + 5 * w_{21} + 6 * w_{31} = 9 3∗w11​+5∗w21​+6∗w31​=9
      • 4 ∗ w 11 + 3 ∗ w 21 + 3 ∗ w 31 = 3 4 * w_{11} + 3 * w_{21} + 3 * w_{31} = 3 4∗w11​+3∗w21​+3∗w31​=3
      • 2 ∗ w 11 + 5 ∗ w 21 + 3 ∗ w 31 = 缺 失 值 2 * w_{11} + 5 * w_{21} + 3 * w_{31} = 缺失值 2∗w11​+5∗w21​+3∗w31​=缺失值
      • 6 ∗ w 11 + 2 ∗ w 21 + 2 ∗ w 31 = 9 6 * w_{11} + 2 * w_{21} + 2 * w_{31} = 9 6∗w11​+2∗w21​+2∗w31​=9
      • 5 ∗ w 11 + 3 ∗ w 21 + 4 ∗ w 31 = 8 5 * w_{11} + 3 * w_{21} + 4 * w_{31} = 8 5∗w11​+3∗w21​+4∗w31​=8
    • 商品2與所有使用者的計算,如下
      • 3 ∗ w 12 + 5 ∗ w 22 + 6 ∗ w 32 = 缺 失 值 3 * w_{12} + 5 * w_{22} + 6 * w_{32} = 缺失值 3∗w12​+5∗w22​+6∗w32​=缺失值
      • 4 ∗ w 12 + 3 ∗ w 22 + 3 ∗ w 32 = 9 4 * w_{12} + 3 * w_{22} + 3 * w_{32} = 9 4∗w12​+3∗w22​+3∗w32​=9
      • 2 ∗ w 12 + 5 ∗ w 22 + 3 ∗ w 32 = 缺 失 值 2 * w_{12} + 5 * w_{22} + 3 * w_{32} = 缺失值 2∗w12​+5∗w22​+3∗w32​=缺失值
      • 6 ∗ w 12 + 2 ∗ w 22 + 2 ∗ w 32 = 8 6 * w_{12} + 2 * w_{22} + 2 * w_{32} = 8 6∗w12​+2∗w22​+2∗w32​=8
      • 5 ∗ w 12 + 3 ∗ w 22 + 4 ∗ w 32 = 7 5 * w_{12} + 3 * w_{22} + 4 * w_{32} = 7 5∗w12​+3∗w22​+4∗w32​=7
    • 其他同理…
  • 從每個商品與所有使用者的計算公式中,不難發現一個商品的所有w值與其他商品的w值無關!是以,不同商品的w值計算,我們可以分開來做。
  • 回想一下,機器學習中的線性回歸!同理,我們可以将求一個商品的多個w值看作多元線性回歸:
    • 例如求商品1的多個w值
      • 矩陣 V 3 , 4 V_{3,4} V3,4​中的第一列的 w 11 w_{11} w11​、 w 21 w_{21} w21​、 w 31 w_{31} w31​是待求的系數
      • 矩陣 U 5 , 3 U_{5,3} U5,3​中的所有行的值是用于訓練的資料
      • 矩陣 A 5 , 4 A_{5,4} A5,4​中第一列的9、3、缺失值、9、8是标簽資料
      • 注意:标簽為缺失值的部分,即待預測的值,不參與計算
    • 其他商品同理
  • 是以,我們可以利用線性回歸(ALS中是最小二乘法)求出所有商品的w值,即得到矩陣 V 3 , 4 V_{3,4} V3,4​
  • 接着,固定矩陣 V 3 , 4 V_{3,4} V3,4​,反過來求解矩陣 U 5 , 3 U_{5,3} U5,3​
  • 如此反複的進行多次求值
  • 直到 U 5 , 3 ∗ V 3 , 4 U_{5,3} * V_{3,4} U5,3​∗V3,4​得到得矩陣與矩陣 A 5 , 4 A_{5,4} A5,4​的損失小于某個門檻值(或是達到一定次數),既可完成求解
  • 最終,推薦算法使用時,利用求得的矩陣 U 5 , 3 ∗ V 3 , 4 U_{5,3} * V_{3,4} U5,3​∗V3,4​,可以預測出使用者對未購買過的商品的喜好程度,進而進行推薦!
  • Spark ALS模型使用示例:《Spark進階資料分析》——音樂推薦(ALS算法)

LFM梯度下降算法-示例

  • 導包
    import numpy as np
    import pandas as pd
               
  • 準備User-Item資料
    # 定義User-Item稀疏矩陣
    # 0代表矩陣的缺失值
    R = np.array(
        [[8, 9, 2, 2,0, 1],
        [3, 2, 5, 6, 0, 0],
        [8, 8, 0, 3, 7, 2],
        [3, 3, 0, 8, 8, 1],
        [7, 0, 3, 2, 5, 9],
        [0, 2, 2, 6, 7, 1],
        [8, 0, 3, 0, 4, 0],
        [3, 9, 0, 8, 6, 8],
        [3, 2, 5, 0, 8, 0],
        [6, 2, 3, 8, 0, 7]]
    )
               
  • LFM梯度下降算法
    def lfm_gradient_descent(R, k=3, steps=1000, alpha=0.001, lam=0.0001):
        """
        LFM梯度下降算法
        
        :param R: 原始稀疏矩陣 User-Item
        :param k: User與Item之間的隐含特征個數
        :param steps: 最大疊代次數
        :param alpha: 學習曲率
        :param lam: 正則化系數
        """
        
        m = len(R)
        n = len(R[0])
        
        # 随機初始化矩陣U,V
        P = np.random.rand(m, k)
        Q =  np.random.rand(k, n)
        
        # 最大疊代steps次
        for step in range(steps):
            # 修正矩陣P、Q
            for user in range(m):
                for item in range(n):
                    # 跳過稀疏矩陣A的缺失值部分
                    if R[user][item] > 0:
                        # 誤差
                        error = np.dot(P[user,:], Q[:, item]) - R[user][item]
                        # 利用誤差error更新矩陣P、Q
                        for i in range(k):
                            P[user][i] -= alpha * (2 * error * Q[i][item] + 2 * lam * P[user][i])
                            Q[i][item] -= alpha * (2 * error * P[user][i] + 2 * lam * Q[i][item])
            # 計算新矩陣與原始稀疏矩陣的損失
            # newR = np.dot(P, Q)
            cost = 0
            for user in range(m):
                for item in range(n):
                    if R[user][item] > 0:
                   		# 損失
                        cost += (np.dot(P[user,:], Q[:,item]) - R[user][item]) ** 2
                        # 正則化
                        cost += lam * sum(P[user,:]**2) + lam * sum(Q[:,item]**2)
                               
            # 達到門檻值,跳出疊代
            if cost < 0.5:
                break;
                
        return P,Q
               
  • 調用算法與結果展示
    P,Q = lfm_gradient_descent(R, 4, 10000, 0.005, 0.0005)
    
    print("--------- 矩陣P ---------")
    print(P)
    print("--------- 矩陣Q ---------")
    print(Q)
    print("--------- 新矩陣P*Q ---------")
    print(np.dot(P, Q))
    print("--------- 原始稀疏矩陣R ---------")
    print(R)
               
  • 列印結果展示
    --------- 矩陣P ---------
    [[ 2.47101945 -0.09314859  1.38122566  0.23276072]
     [-0.4175392   0.88409428  0.62463847  2.39820982]
     [ 2.10106116  0.1731982   1.56076663  0.37699979]
     [ 0.98266167  2.10821349  0.74604873  0.13698655]
     [ 0.46591391 -0.45260323  1.54408459  1.95285085]
     [ 0.62855731  1.56571349  1.05862982  0.00706062]
     [ 0.95726687 -1.11403965  1.48064885  2.10244858]
     [ 1.97143103  1.32056111 -0.72112522  2.56245347]
     [ 0.07027225  2.03254073  0.78322988  1.50645914]
     [-0.04846877  1.64219853  2.02188288  1.15083635]]
     --------- 矩陣Q ---------
    [[ 1.58242819  3.19303543  0.95667258  0.48655993  1.21054208 -0.6060828 ]
     [-0.35870851 -0.34836087  1.15881715  3.27881658  2.32052529  0.09664613]
     [ 2.78744452  0.53842092 -0.49708206  0.58858015  2.40623536  1.15769018]
     [ 0.92791198  1.38316166  1.951467    1.22337834  0.88932108  3.86373607]]
     --------- 新矩陣P*Q ---------
    [[ 8.00969538  8.98812847  2.02365673  1.99459832  6.30567239  0.99171252]
     [ 2.98861476  2.01222899  4.99458605  5.99719289  5.1819201  10.32769524]
     [ 7.96302376  8.0102283   2.17060619  2.97002692  7.03617947  2.0068338 ]
     [ 3.0054383   2.99441722  3.2795967   7.99726497  7.99870986  1.00114949]
     [ 7.01575177  5.17782475  2.96462993  2.04058504  4.96587355  9.00674711]
     [ 3.39043557  2.04132685  1.90325185  6.07124444  6.94776448  1.02320811]
     [ 7.99253533  7.14991343  2.99167776  0.2566066   4.00619612  9.14958844]
     [ 3.01358624  8.99083579  8.77530468  7.99950709  5.99454255  7.99858102]
     [ 2.96318244  2.02170798  4.97304635  9.00248294  8.02599098  6.88114446]
     [ 6.03799225  1.95357653  3.09741652  7.9588332   9.64067885  6.97533011]]
     --------- 原始稀疏矩陣R ---------
    [[8 9 2 2 0 1]
     [3 2 5 6 0 0]
     [8 8 0 3 7 2]
     [3 3 0 8 8 1]
     [7 0 3 2 5 9]
     [0 2 2 6 7 1]
     [8 0 3 0 4 0]
     [3 9 0 8 6 8]
     [3 2 5 0 8 0]
     [6 2 3 8 0 7]]