1. 程式人生 > >一文讀懂FM演算法優勢,並用python實現

一文讀懂FM演算法優勢,並用python實現

介紹

我仍然記得第一次遇到點選率預測問題時的情形,在那之前,我一直在學習資料科學,對自己取得的進展很滿意,在機器學習黑客馬拉松活動中也開始建立了自信,並決定好好迎接不同的挑戰。

為了做得更好,我購買了一臺記憶體16GB,i7處理器的機器,但是當我看到資料集的時候卻感到非常不安,解壓縮之後的資料大概有50GB - 我不知道基於這樣的資料集要怎樣進行點選率預測。幸運地是,Factorization Machines(FM)演算法拯救了我。

任何從事點選率預測問題或者推薦系統相關工作的人都會遇到類似的情況。由於資料量巨大,利用有限的計算資源對這些資料集進行預測是很有挑戰性的。

然而在大多數情況下,由於很多特徵對預測並不重要,所以這些資料集是稀疏的(每個訓練樣本只有幾個變數是非零的)。在資料稀疏的場景下,因子分解有助於從原始資料中提取到重要的潛式或隱式的特徵。

因子分解有助於使用低維稠密矩陣來表示目標和預測變數之間的近似關係。在本文中我將討論演算法Factorization Machines(FM) 和Field-Aware Factorization Machines(FFM),然後在迴歸/分類問題中討論因子分解的優勢,並通過python程式設計實現。


目錄

1. 因式分解的直觀介紹

2. FM演算法如何優於多項式和線性模型

3. FFM演算法介紹

4. 在python中使用xLearn庫進行演算法實現

因式分解的直觀介紹

為了直觀地理解矩陣分解,我們來看一個例子:假設有一個使用者-電影評分(1-5)矩陣,矩陣中的每一個值表示使用者給電影的評分(1-5)。

從上述表格中我們可以看出,一些評分是缺失的,我們想設計一種方法來預測這些缺失的評分。直觀上來講,利用矩陣分解來解決這個問題的關鍵是應該有一些潛在的特徵決定使用者如何評價一部電影。舉例來說 - 使用者A和B都是演員阿爾·帕西諾的粉絲,那麼他們就會對阿爾·帕西諾的電影評分較高。在上述例子中,對特定演員的偏好是一個隱藏的特性,因為我們沒有明確地將其包含在評分矩陣中。

假設我們要計算K個隱藏或潛在的特徵,我們的任務是找出矩陣P (U x K)和Q (D x K) (U – 使用者, D – 電影),使得 P x QT  近似等於評分矩陣R。


P矩陣的每一行表示使用者與不同特徵的相關性,Q矩陣的每一行表示該特徵與電影同樣的相關性。為了得到使用者ui對電影dj的評分,我們可以計算對應於ui和dj兩個向量的點積。

接下來要做的就是求出矩陣P和矩陣Q。我們使用梯度下降演算法來計算,目標函式是使使用者的實際評分與通過矩陣P和Q估計的評分之間的平方誤差最小,這裡的平方誤差由以下方程求出。


現在我們要給pik和qkj定義一個更新規則,梯度下降法中的更新規則是由最小化誤差值的梯度來定義的。

獲得梯度值後,接下來可以定義pik和qkj的更新規則。

這裡α是控制更新步長的學習速率,使用上述更新規則,我們可以迭代地執行操作,直到誤差收斂到最小,同時使用下面的公式計算總的誤差,以此來確定什麼情況下應該停止迭代。


上述解決方案很簡單並且經常會導致過擬合,即現有的評分都被準確預測到,但是不能很好地推廣到未知的資料上。為了解決這個問題,我們可以引入一個正則化引數 β,它將分別控制矩陣P和Q中向量“使用者-特徵”和“電影-特徵”,並給出一個更好的評分的近似值。

如果對利用python實現上述功能和相關細節感興趣,請參考這個連結http://www.quuxlabs.com/wp-content/uploads/2010/09/mf.py_.txt。一旦我們用上述方法計算出了矩陣P和Q,得到的近似評分矩陣如下:


現在,我們既能夠重新生成現有評分,也能對未知的評分進行一個合理的近似。

 

FM演算法如何優於多項式和線性模型

首先考慮一組點選率預測資料的訓練示例。以下資料來自相關體育新聞網站(釋出商)和體育用品公司(廣告商)。


當我們討論FM或者FFM的時候,資料集中的每一列(比如上述表格中的出版商、廣告商等)將被稱為一個欄位,每一個值( ESPN、Nike 等)都被稱為一個特徵。

線性或邏輯迴歸模型在很多問題上表現很好,但缺點是這種模型只能學習所有變數或者特徵各自的影響,無法學習變數之間的相互作用


在上述等式中,w0、wESPN等代表引數,xESPN、xNike等代表資料集中的各個特徵,通過最小化上述函式的對數損失,得到邏輯迴歸模型。捕獲特徵之間相互作用的一種方法是使用多項式函式,將每個特徵對的乘積作為單獨的引數來學習,並且把每一個乘積作為一個獨立的變數。


這也可以稱為 Poly2模型,因為每一項都只考慮了兩個特徵之間的相互影響。

問題在於,即使面對一箇中等大小的資料集,也需要一個龐大的模型,這對儲存模型所需要的記憶體空間和訓練模型所花費的時間都有很大的影響;

其次,對於一個稀疏資料集,這種技術不能很好地學習所有的權重或引數,因為沒有有足夠的訓練樣本使每一個特徵對的權重是可靠的。

救星FM

FM演算法解決了成對特徵互動的問題。它使我們能夠根據每一對特徵組合中的可靠資訊(隱藏特徵)來訓練模型,同時在時間和空間複雜度上更有效地實現上述目標。具體來講,它將成對互動特徵作為低維向量的點積(長度為K)進行建模,以下包含了一個二階因子分解的方程。


FM(K=3)項中每個引數的表示方法如下:


上述等式中,我們分別計算了與2個特徵對應的2個長度為3的潛因子的點積。

從建模的角度來看,這是非常強大的,因為每一個特徵最後都會轉換到一個相似特徵被互相巢狀的空間,簡而言之,點積基本上表示了潛在特徵的相似程度,特徵越相近,點積越大。

對於餘弦函式,當 θ是0時,得到最大值1;當 θ是180度,得到-1,所以當 θ接近於0時,相似性最大。

FM演算法的另一個巨大優勢是能夠線上性時間複雜度下使用簡單的數學方法計算模型中成對特徵的相互作用。如果你想進一步瞭解具體的實現步驟,請參考連結中關於FM演算法的原始研究論文。

https://www.csie.ntu.edu.tw/~b97053/paper/Rendle2010FM.pdf


示例:FM演算法效能優於 POLY2演算法的演示

考慮以下一組虛構的點選率資料:

這個資料集由作為釋出者的體育網站和體育用品廣告商構成。廣告是以彈出的方式來顯示的,使用者可以選擇點選廣告或者關閉廣告。


特徵對(ESPN,Adidas)只有一個負的訓練資料,那麼在Poly2演算法中,這個特徵對可能會學到一個負的權重值wESPN,Adidas;而在FM演算法中,由於特徵對(ESPN,Adidas)是由wESPN·wAdidas決定的,而其中的wESPN和wAdidas分別是從其他特徵對中學到的(比如(ESPN,Nike),(NBC,Adidas)等),所以預測可能更加精確。

另一個例子是特徵對(NBC,Gucci)沒有任何訓練資料,對於Poly2演算法,這個特徵對的預測值為0;但是在FM演算法中,因為wNBC和wGucci可以從其他特徵對中學到,所以仍然有可能得到有意義的預測值。

FFM演算法介紹


為了理解FFM演算法,我們需要認識field的概念。field通常是指包含一個特定特徵的更廣泛的類別。在上述訓練示例中,field分別指釋出者(P)、廣告商(A)和性別(G)。

在FM演算法中,每一個特徵只有一個隱向量v,來學習其他特徵帶來的潛在影響。以ESPN為例,wESPN被用來學習特徵Nike(wESPN·wNike)和Male(wESPN.wMale)之間的潛在作用。

但是,由於ESPN和Male屬於不同的field,所以對特徵對(ESPN,Nike)和(ESPN,Male)的起作用的潛在作用可能不同。FM演算法無法捕捉這個差異,因為它不區分field的概念,在這兩種情況中,它會使用相同引數的點積來計算。

在FFM演算法中,每個特徵有若干個隱向量。例如,當考慮特徵ESPN和Nike之間的互動作用時,用符號wESPN,A來表示ESPN的隱藏特徵,其中A(廣告商)表示特徵Nike的field。類似的,關於性別的field的一個重要的引數wESPN,G也會被學習到。

事實證明,FFM演算法對獲得由 Criteo、Avazu、Outbrain舉辦的點選率(CTR)比賽第一名是至關重要的,同時也幫助贏得了2015年RecSys挑戰賽的三等獎。關於點選率資料集可以從Kaggle獲得。

在python中使用xLearn庫進行演算法實現


一些在python中實現FM & FFM的最流行的庫如下所示:

為了在資料集上使用FM演算法,需要將資料轉換為libSVM格式。以下為訓練和測試的資料檔案格式:

<label> <feature1>:<value1> <feature2>:<value2> …


在增加了field的概念之後,每個特徵被唯一編碼並被賦值,上述圖中,特徵ESPN用1表示,特徵Nike用2表示,以此類推。每一行包含一個等效的訓練示例並以“\ n”或換行符結尾。

對於分類(二進位制/多類),<label>是一個指示類標籤的整數。

對於迴歸,<label>是任何實數的目標值。

測試檔案中的標籤僅用於計算準確度或誤差,未知的情況下可以用任何數值填寫第一列。


同樣,對於FFM演算法,需要將資料轉換為libffm格式。在這裡,我們也需要對field進行編碼,因為該演算法需要field的資訊來學習。格式如下:

<label><field1>:<feature1>:<value1><field2>:<feature2>:<value2> …

有關數值特徵的重要說明

數值特徵需要被離散化(通過將特定數值特徵的整個範圍分成較小的範圍並且分別對每個範圍進行標記編碼而轉換為分類特徵),然後如上所示轉換為libffm格式。

另一種可能性是新增一個與特徵值相同的虛擬field值,它將是該特定行的數值特徵(例如,具有值45.3的特徵可以被變換為1:1:45.3)。 但是虛擬field值可能不包含任何資訊,因為它們僅僅是這些數值特徵的複製品。

xLearn

最近推出的xLearn庫提供了一個在各種資料集上實現FM和FFM模型的快速解決方案。 它比libfm和libffm庫快得多,為模型測試和調優提供了更好的功能。

在這裡,我們將用一個例子來說明FFM演算法,資料來自Criteo點選率預測挑戰賽中CTR資料集的一個微小(1%)抽樣。 你可以從這裡[Office1] 下載這個資料集。

但首先我們需要將其轉換為xLearn所需的libffm格式以擬合模型。 以下函式將標準資料幀格式的資料集轉換為libffm格式。

df = Dataframe to be converted to ffm format

Type = Train/Test/Val

Numerics = list of all numeric fields

Categories = list of all categorical fields

Features = list of all features except the Label and Id

xLearn可以直接處理csv以及libsvm格式的資料來實現FM演算法,但對FFM演算法而言,我們必須將資料轉換為libffm格式。

一旦我們有了libffm格式的資料集,就可以使用xLearn庫來訓練模型。

類似於任何其他機器學習演算法,資料集被分成一個訓練集和一個驗證集。xLearn使用驗證/測試對數損失來自動執行提前停止的操作,並且我們還可以在隨機梯度下降的迭代中為驗證集設定其他的監控指標。

下面的python指令碼可以用於在ffm格式的資料集上使用xLearn來訓練和調整FFM模型的超引數。

該庫還允許我們使用cv()函式進行交叉驗證:

可以使用以下程式碼片段對測試集進行預測:

結語

在這篇文章中,我們已經演示了對一般分類/迴歸問題的因式分解的用法。如果您在執行這個演算法的過程中遇到任何問題請及時告知我們。有關xLearn詳細文件將在這個連結中給出,並會得到定期更新和支援。

http://xlearn-doc.readthedocs.io/en/latest/python_api.html

原文連結:

https://www.analyticsvidhya.com/blog/2018/01/factorization-machines/
--------------------- 
作者:資料派THU 
來源:CSDN 
原文:https://blog.csdn.net/tmb8z9vdm66wh68vx1/article/details/79091671 
版權宣告:本文為博主原創文章,轉載請附上博文連結!