推薦系統的PMF - 概率矩陣分解和協同過濾

自動化推薦系統通常用於根據現有的偏好數據爲用戶提供他們感興趣的產品建議。 文獻中通常描述了不同類型的推薦系統。我們這篇文章將突出介紹兩個主要類別,然後在第二個類別上進一步擴展:

基於內容的過濾:這些過濾器利用用戶偏好來做出新的預測。 當用戶提供有關其偏好的明確信息時,系統會記錄並使用這些信息來自動提出建議。 我們日常使用的許多網站和社交媒體都屬於此類。

協同過濾:當用戶提供的信息不足以提出項目建議時,會發生什麼情況? 在這些情況下,我們可以使用其他用戶提供的具有相似首選項的數據。 此類別中的方法利用了一組用戶的過去選擇歷史來得出建議。

在第一種情況下,期望給定的用戶建立一個清楚表明偏好的配置文件,在第二種情況下,此信息可能無法完全使用,但是我們希望我們的系統仍能夠基於類似的證據提出建議 用戶提供。 一種稱爲概率矩陣分解的方法(簡稱爲PMF)通常用於協同過濾,並且將成爲本文其餘部分討論的主題。 現在讓我們深入研究此算法的細節及其直覺。

概率矩陣分解解釋

假設我們有一組用戶u1,u2,u3…uN,他們對一組項目v1,v2,v3…vM進行評分。 然後,我們可以將評分構建爲N行和M列的矩陣R,其中N是用戶數,M是要評分的項目數。

評分映射。 可以將其視爲每個用戶(行)對多個項目(列)進行評分的矩陣

R矩陣的一個重要特徵是它是稀疏的。 也就是說,僅其某些單元格具有非空的評級值,而其他單元格則沒有。 對於給定的用戶A,系統應該能夠基於他/她的偏好以及類似用戶的選擇來提供項目推薦。 但是,用戶A不必明確推薦某項就可以對其進行推薦。 具有相似首選項的其他用戶將彌補有關用戶A的缺失數據。這就是爲什麼概率矩陣分解屬於協同過濾推薦系統的類別。

讓我們考慮一下電影推薦系統。 想象一下,如果我們被要求觀看和評價特定季節中放映的每部電影會是什麼樣子。 那是不切實際的,不是嗎? 我們根本沒有時間這樣做。

鑑於並非所有用戶都能夠對所有可用項目進行評分,我們必須找到一種方法來填補R矩陣的信息空白,並且仍然能夠提供相關建議。 PMF通過利用類似用戶提供的評級來解決此問題。 從技術上講,它利用了貝葉斯學習的一些原理,這些原理也適用於我們缺少或不完整數據的其他情況。

可以通過使用兩個低階矩陣U和V來估計R矩陣,如下所示:


此處,UT是一個NxD矩陣,其中N是註冊用戶數,D是等級。 V是DxM矩陣,其中M是要評估的項目數。 因此,NxM評級矩陣R可以通過以下方式近似:

公式1:R表達式

從現在開始,我們的工作是找到UT和V,它們將反過來成爲模型的參數。 因爲U和V是低階矩陣,所以PMF也被稱爲低階矩陣分解問題。 此外,U和V矩陣的這一特殊特徵使得PMF甚至對於包含數百萬條記錄的數據集也可擴展。

PMF從貝葉斯學習中得出的直覺用於參數估計。 一般而言,我們可以說在貝葉斯推斷中,我們的目的是藉助貝葉斯規則來找到模型參數的後驗分佈:

公式2:參數的貝葉斯規則

在這裏,X是我們的數據集,θ是分佈的參數或參數集。 α是分佈的超參數。 p(θ| X,α)是後驗分佈,也稱爲後驗分佈。 p(X |θ,α)是似然,p(θ|α)是先驗。 訓練過程的整體思路是,隨着我們獲得有關數據分佈的更多信息,我們將調整模型參數θ以適合數據。 從技術上講,後驗分佈的參數將插入到先前的分佈中,以進行訓練過程的下一次迭代。 也就是說,給定訓練步驟的後驗分佈最終將成爲下一步驟的先驗。 重複該過程,直到步驟之間的後驗分佈p(θ| X,α)幾乎沒有變化爲止。

現在,讓我們回到有關PMF的直覺上。 如前所述,我們的模型參數將是U和V,而R將是我們的數據集。 經過培訓後,我們將得到一個修訂的R *矩陣,該矩陣還將包含對用戶項目單元格最初在R中爲空的評分。我們將使用此修訂的評分矩陣進行預測。 基於這些考慮,我們將擁有:


其中σ是零均值球形高斯分佈的標準偏差。 然後,通過替換等式2中的這些表達式,我們將得到:

由於U和V矩陣彼此獨立(用戶和項獨立發生),因此該表達式也可以這樣寫:


公式3:PMF的A-Posteriori分佈

現在是時候找出該方程式的每個分量了。 首先,似然函數由下式給出:

公式4:觀測等級的分佈

在此,I {ij}是一個指標,當第i行和第j列的評級存在時,其值爲1,否則爲0。 如我們所見,此分佈是具有以下參數的spherical Gaussian分佈:

反過來,U和V的先驗分佈由下式給出:

公式5和6:U和V的先驗分佈

這是兩個零均值球面高斯(spherical Gaussians)。 然後,通過在3中替換4、5和6,我們將得到:


爲了訓練我們的模型,我們將尋求通過將參數U和V的導數等價爲零來最大化此函數。 但是,由於高斯函數中的exp函數,這樣做將非常困難。 爲了克服這個問題,我們應該將對數應用於前面的方程式的兩邊,然後應用所需的導數。 因此,通過將對數應用於上一個方程的兩邊,我們將獲得:

這是一個更容易區分的表達方式。 我們也知道,根據定義,高斯PDF由以下公式給出:

因此,我們對數後驗的表達式將如下所示(注意:爲簡單起見,我們已刪除了常量):

Fro後綴表示Frobenius範數,它由下式給出:


最後,通過引入一些附加的符號來標識模型的超參數,我們將獲得:


公式7:PMF的對數後驗


然後,通過對參數微分方程式7並將導數等於零,我們將得到:


從這裏,我們可以導出表達式以更新Ui和Vj:

公式8和9:用於更新U和V的表達式

假設λU和λV都不爲零,則可以保證所涉及的逆矩陣存在。 作爲訓練過程的一部分,我們將迭代更新Ui和Vj。 一旦找到最佳值,就可以使用方程式7獲得log-MAP的值(最大後驗值)。正如我們在Python實現中所看到的那樣,我們可以使用該值來監控訓練收斂 。

用Python實現

爲了進行訓練,我們使用了IMDB電影數據庫的一個子集,然後將其分爲兩部分分別進行訓練和驗證。

初始化:爲了初始化V,我們從零均值高斯繪製隨機數,標準偏差爲1 /λV。 此外,等級值D被設置爲較小的值10。

def initialize_parameters(lambda_U, lambda_V):
    U = np.zeros((n_dims, n_users), dtype=np.float64)
    V = np.random.normal(0.0, 1.0 / lambda_V, (n_dims, n_movies))
    
    parameters['U'] = U
    parameters['V'] = V
    parameters['lambda_U'] = lambda_U
    parameters['lambda_V'] = lambda_V

更新參數:爲了更新U和V,我們使用公式8和9:

def update_parameters():
    U = parameters['U']
    V = parameters['V']
    lambda_U = parameters['lambda_U']
    lambda_V = parameters['lambda_V']
    
    for i in range(n_users):
        V_j = V[:, R[i, :] > 0]
        U[:, i] = np.dot(np.linalg.inv(np.dot(V_j, V_j.T) + lambda_U * np.identity(n_dims)), np.dot(R[i, R[i, :] > 0], V_j.T))
        
    for j in range(n_movies):
        U_i = U[:, R[:, j] > 0]
        V[:, j] = np.dot(np.linalg.inv(np.dot(U_i, U_i.T) + lambda_V * np.identity(n_dims)), np.dot(R[R[:, j] > 0, j], U_i.T))
        
    parameters['U'] = U
    parameters['V'] = V

計算對數後驗:對數後驗由公式7給出:

def log_a_posteriori():
    lambda_U = parameters['lambda_U']
    lambda_V = parameters['lambda_V']
    U = parameters['U']
    V = parameters['V']
    
    UV = np.dot(U.T, V)
    R_UV = (R[R > 0] - UV[R > 0])
    
    return -0.5 * (np.sum(np.dot(R_UV, R_UV.T)) + lambda_U * np.sum(np.dot(U, U.T)) + lambda_V * np.sum(np.dot(V, V.T)))

訓練循環:要訓練模型,我們調用先前的函數並監視對數後驗以及在訓練和測試集上評估的RMSE(均方根誤差):

def train(n_epochs):
    initialize_parameters(0.3, 0.3)
    log_aps = []
    rmse_train = []
    rmse_test = []

    update_max_min_ratings()
    rmse_train.append(evaluate(train_set))
    rmse_test.append(evaluate(test_set))
    
    for k in range(n_epochs):
        update_parameters()
        log_ap = log_a_posteriori()
        log_aps.append(log_ap)

        if (k + 1) % 10 == 0:
            update_max_min_ratings()

            rmse_train.append(evaluate(train_set))
            rmse_test.append(evaluate(test_set))
            print('Log p a-posteriori at iteration', k + 1, ':', log_ap)

    update_max_min_ratings()

    return log_aps, rmse_train, rmse_test

我們將訓練循環運行150次迭代,結果如下:


在左側,我們可以看到在訓練模型時對數後驗如何演變。 在右側,我們可以看到在訓練集和測試集上評估的RMSE值。 考慮到R預測可能超出額定值的0-5範圍,我們使用線性插值法確保R值受此間隔限制。 原始論文[1]提出了其他方法,例如使用邏輯函數和線性插值。 對於訓練,還建議使用帶動量的梯度下降來處理較大的數據集。

最後,以下是數據庫中用戶ID爲45的電影推薦:

結論

PMF是用於協作過濾的強大算法。 它利用具有相似首選項的用戶提供的數據向特定用戶提供推薦。 它也被稱爲低秩矩陣分解方法,因爲它使用低秩矩陣來估計等級R矩陣,然後進行有用的預測。

引用

[1] Salakhutdinov, Ruslan & Mnih, Andriy. Probabilistic Matrix Factorization. In NIPS’07: Proceedings of the 20th International Conference on Neural Information Processing Systems, pages 1257–1264, 2007.

[2] Brooks-Bartlett Jonny. Probability concepts explained: Bayesian inference for parameter estimation.

作者:Oscar Contreras Carrasco

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章