FM算法python实现
在計算廣告中,CTR預估(click-through rate)是非常重要的一個環節,對于特征組合來說,FM(因子分解機)是其中較為經典且被廣泛使用的模型。?
1、FM原理?
=>重點內容解決稀疏數據下的特征組合問題
可用于高度稀疏數據場景
具有線性的計算復雜度
?????對于categorical(類別)類型特征,需要經過One-Hot Encoding轉換成數值型特征。CTR/CVR預測時,用戶的性別、職業、教育水平、品類偏好,商品的品類等,經過One-Hot編碼轉換后都會導致樣本數據的稀疏性。特別是商品品類這種類型的特征,如商品的末級品類約有550個,采用One-Hot編碼生成550個數值特征,但每個樣本的這550個特征,有且僅有一個是有效的(非零)。由此可見,經過One-Hot編碼之后,大部分樣本數據特征是比較稀疏的(即特定樣本的特征向量很多維度為0),同時導致特征空間大。(對于每一個特征,如果它有m個可能值,那么經過獨熱編碼后,就變成了m個二元特征(取值0或1)。并且,這些特征互斥,每次只有一個激活。因此,數據會變成稀疏的.) sklearn中preprocessing.OneHotEncoder實現該編碼方法。?
?????通過觀察大量的樣本數據可以發現,某些特征經過關聯之后,與label之間的相關性就會提高。例如,“USA”與“Thanksgiving”、“China”與“Chinese New Year”這樣的關聯特征,對用戶的點擊有著正向的影響。換句話說,來自“China”的用戶很可能會在“Chinese New Year”有大量的瀏覽、購買行為,而在“Thanksgiving”卻不會有特別的消費行為。這種關聯特征與label的正向相關性在實際問題中是普遍存在的,如“化妝品”類商品與“女”性,“球類運動配件”的商品與“男”性,“電影票”的商品與“電影”品類偏好等。因此,引入兩個特征的組合是非常有意義的。(我的理解:個性化特征)
一般的線性模型為:?
?
從上面的式子很容易看出,一般的線性模型壓根沒有考慮特征間的關聯(組合)。為了表述特征間的相關性,我們采用多項式模型。在多項式模型中,特征xi與xj的組合用xixj表示。為了簡單起見,我們討論二階多項式模型。具體的模型表達式如下:?
?(1)?
上式中,n表示樣本的特征數量,xi表示第i個特征。?
與線性模型相比,FM(Factorization Machine)的模型就多了后面特征組合的部分。?
從公式(1)可以看出,組合特征的參數一共有 n(n?1)/2 個,任意兩個參數都是獨立的。然而,在數據稀疏性普遍存在的實際應用場景中,二次項參數的訓練是很困難的。其原因是,每個參數 wij 的訓練需要大量 xi 和xj都非零的樣本;由于樣本數據本來就比較稀疏,滿足“xi 和 xj 都非零”的樣本將會非常少。訓練樣本的不足,很容易導致參數 wij 不準確,最終將嚴重影響模型的性能。?
類似地,所有二次項參數W i,j可以組成一個對稱陣W,那么這個矩陣就可以分解為 W=VVT,V的第i行便是第i維特征的隱向量,則FM的模型方程為:?
2、FM交叉項求解過程?
?
對表達式進行化簡,可以把時間復雜度降低到O(kn)?
第一步是一個矩陣(矩陣中所有元素求和)減去對角線部分,然后除以2。多項式部分的計算復雜度是O(kn).即FM可以在線性時間對新樣本作出預測
3、實現步驟?
代碼簡單實現:
添加依賴項:
from __future__ import division
from math import exp
import pandas as pd
from numpy import *
from random import normalvariate
from datetime import datetime
from sklearn import preprocessing
讀取數據:
def load_train_data(data):
? ? global min_max_scaler
? ? data = pd.read_csv(data)
? ? labelMat = data.ix[:,-1]* 2 - 1
? ? X_train = np.array(data.ix[:, :-1])
? ? min_max_scaler = preprocessing.MinMaxScaler()
? ? X_train_minmax = min_max_scaler.fit_transform(X_train)
? ? return X_train_minmax,labelMat
def laod_test_data(data):
? ? data = pd.read_csv(data)
? ? labelMat = data.ix[:, -1] * 2 - 1
? ? X_test = np.array(data.ix[:, :-1])
? ? X_tset_minmax = min_max_scaler.transform(X_test)
? ? return X_tset_minmax, labelMat
定義sigmod函數:
def sigmoid(inx):
? ? return 1. / (1. + exp(-max(min(inx, 10), -10)))
模型訓練:
def FM_function(dataMatrix, classLabels, k, iter):
? ? m, n = shape(dataMatrix)
? ? alpha = 0.01
? ? w = zeros((n, 1))
? ? w_0 = 0.
? ? v = normalvariate(0, 0.2) * ones((n, k))
? ? for it in xrange(iter):
? ? ? ? print it
? ? ? ? for x in xrange(m):
? ? ? ? ? ? inter_1 = dataMatrix[x] * v
? ? ? ? ? ? inter_2 = multiply(dataMatrix[x], dataMatrix[x]) * multiply(v, v)
? ? ? ? ? ? interaction = sum(multiply(inter_1, inter_1) - inter_2) / 2.
? ? ? ? ? ? p = w_0 + dataMatrix[x] * w + interaction ?#
? ? ? ? ? ? loss = sigmoid(classLabels[x] * p[0, 0]) - 1
? ? ? ? ? ? w_0 = w_0 - alpha * loss * classLabels[x]
? ? ? ? ? ? for i in xrange(n):
? ? ? ? ? ? ? ? if dataMatrix[x, i] != 0:
? ? ? ? ? ? ? ? ? ? w[i, 0] = w[i, 0] - alpha * loss * classLabels[x] * dataMatrix[x, i]
? ? ? ? ? ? ? ? ? ? for j in xrange(k):
? ? ? ? ? ? ? ? ? ? ? ? v[i, j] = v[i, j] - alpha * loss * classLabels[x] * (
? ? ? ? ? ? ? ? ? ? ? ? dataMatrix[x, i] * inter_1[0, j] - v[i, j] * dataMatrix[x, i] * dataMatrix[x, i])
? ? return w_0, w, v
精確度計算及其評估Assessment:
def Assessment(dataMatrix, classLabels, w_0, w, v):
? ? m, n = shape(dataMatrix)
? ? allItem = 0
? ? error = 0
? ? result = []
? ? for x in xrange(m):
? ? ? ? allItem += 1
? ? ? ? inter_1 = dataMatrix[x] * v
? ? ? ? inter_2 = multiply(dataMatrix[x], dataMatrix[x]) * multiply(v, v)
? ? ? ? interaction = sum(multiply(inter_1, inter_1) - inter_2) / 2.
? ? ? ? p = w_0 + dataMatrix[x] * w + interaction
? ? ? ? pre = sigmoid(p[0, 0])
? ? ? ? result.append(pre)
? ? ? ? if pre < 0.5 and classLabels[x] == 1.0:
? ? ? ? ? ? error += 1
? ? ? ? elif pre >= 0.5 and classLabels[x] == -1.0:
? ? ? ? ? ? error += 1
? ? ? ? else:
? ? ? ? ? ? continue
? ? print result
? ? return float(error) / allItem
main函數:
if __name__ == '__main__':
? ? #-------讀取數據----------
? ? trainData = 'train.txt'
? ? testData = 'test.txt'
? ? #------模型訓練----
? ? dataTrain, labelTrain = load_train_data(trainData)
? ? dataTest, labelTest = laod_test_data(testData)
? ? w_0, w, v = FM_function(mat(dataTrain), labelTrain, 15, 100)
參考資料:?
1. https://blog.csdn.net/jediael_lu/article/details/77772565#1fm?
2. https://www.jianshu.com/p/55be900e18db?
3. http://baijiahao.baidu.com/s?id=1589879343345420975&wfr=spider&for=pc?
4. https://blog.csdn.net/g11d111/article/details/77430095
---------------------?
作者:lieyingkub99?
來源:CSDN?
原文:https://blog.csdn.net/lieyingkub99/article/details/80897743?
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!
總結
以上是生活随笔為你收集整理的FM算法python实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一文读懂FM算法优势,并用python实
- 下一篇: 梯度迭代树回归(GBDT)算法介绍及Sp