Factorization Machine---因子分解機
①target function的推導
logistics regression algorithm model中使用的是特征的線性組合,最終得到的分割平面屬于線性模型,但是線性模型就隻能處理線性問題,是以對于非線性的問題就有點難處理了,對于這些複雜問題一般是兩種解決方法①對資料本身進行處理,比如進行特征轉換,和函數高維擴充等等。②對算法模型本身進行擴充,比如對linear regression加上正則化懲罰項進行改進得到lasso regression或者是ridge regression。
Factorization Machine就是一種對logistics regression的一種改進,線性的部分權值組合是不變的,在後面增加了非線性的交叉項。
target function:

表示的是系數矩陣V的第i維向量,
,k的大小稱為是度,度越大代表分解出來的特征就越多。對于每一個特征都會對應有一個
維的向量。前兩部分是傳統的線性模型,後一個部分就是将臉剛剛互不相同的特征分量之間的互相關系考慮進來了。也就是不同特征之間的吸引程度。
如果使用男女戀愛來解釋這個模型,得分score是男生對女生的一個喜歡程度,
代表的就是底分,可以看成是男生對于女生的第一感覺。對于第二部分可以看成是女生的優秀程度,第三部分就相當于是男女之間的事互動關系了,也就是男女之間的感覺,如果兩個男生對于同一個女生的感覺是一緻的,那麼他們的
就是一緻的,從本質上說,因子分解機也是探索一種相似性,其與協同過濾算法是類似的,但是這兩者的差別在于,因子分解機同時考慮了男生和男生間的相似性以及女生和女生間的相似性,但是協同過濾要麼隻考慮男生之間的相似性,要麼隻考慮女生之間的相似性。
優化求解target function

對于原始的target function計算複雜度是
,采用公式
的公式。于是化簡一波:
這樣就成功的把複雜度降到了
FM可以解決的問題主要是四種:
1.回歸問題:這時候的error function:
2.二分類問題:
3.排序問題。
4,推薦系統。
接下來就是模型的求解,自然就是求導了,我們做的是二分類問題,是以采用的就是第二種loss function求導,按照求導正常求取即可:
Factorization Machine的優點
①對于一些很稀疏的資料集也可以進行參數的預測,而SVM是不行的。
②FM有線性的複雜性,可以直接在原始資料進行預測,而不需要再做核函數或者特征轉換,對于SVM,是要基于對支援向量的優化的。
③FMs是一種通用的預測器,可用于任何實值特征向量。相比之下。其他最先進的因數分解模型隻在非常有限的輸入資料上工作。通過定義輸入資料的特征向量,FMs可以模拟最先進的模型,如偏置MF、SVD++、PITF或FPMC。
K的選擇
如果資料是一個稀疏矩陣,那麼可以選擇一個比較小的k,因為稀疏矩陣其實就已經表明這個矩陣的資訊是十分有限的了,再取比較大的k可能會導緻過拟合。如果資料并不是一個稀疏矩陣,可以選擇大一點的k來代表資料。
代碼實作
主要部分的代碼:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from loadDataSet import loadData
def Accuracy(preiction, classlabel):
score = 0
for i in range(len(preiction)):
if preiction[i] > 0.5:
preiction[i] = 1
else:
preiction[i] = -1
if preiction[i] == classlabel[i]:
score += 1
print('Accuracy: ', score/len(preiction))
def initialize(n, k):
v = np.mat(np.zeros((n, k)))
for i in range(n):
for j in range(k):
v[i, j] = np.random.normal(0, 0.2)
return v
def sigmoid(inx):
return 1.0/(1+np.exp(-inx))
def getCost(predict, classLabels):
m = len(predict)
error = 0.0
for i in range(m):
error -= np.log(sigmoid(predict[i]*classLabels[i]))
return error
def getPrediction(dataMatrix, w0, w, v):
m = np.shape(dataMatrix)[0]
result = []
for x in range(m):
inter_1 = dataMatrix[x] * v
inter_2 = np.multiply(dataMatrix[x], dataMatrix[x]) * np.multiply(v, v)
interaction = np.sum(np.multiply(inter_1, inter_1) - inter_2) / 2
p = w0 + dataMatrix[x] * w + interaction
pre = sigmoid(p[0, 0])
result.append(pre)
return result
def stocGradAscent(dataMatrix, classLabels, k, max_iter, alpha):
#initialize parameters
m, n = np.shape(dataMatrix)
w = np.zeros((n, 1))
w0 = 0
v = initialize(n, k)
#training
for it in range(max_iter):
for x in range(m):
inter_1 = dataMatrix[x] * v
inter_2 = np.multiply(dataMatrix[x], dataMatrix[x])*np.multiply(v, v)
interaction = np.sum(np.multiply(inter_1, inter_1) - inter_2)/2
p = w0 + dataMatrix[x]*w + interaction
loss = sigmoid(classLabels[x] * p[0, 0]) - 1
w0 = w0 - alpha*loss*classLabels[x]
for i in range(n):
if dataMatrix[x, i] != 0:
w[i, 0] = w[i, 0] - alpha*loss*classLabels[x]*dataMatrix[x, i]
for j in range(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])
if it % 1000 == 0:
print('-----iter: ', it, ', cost: ', getCost(getPrediction(np.mat(dataMatrix), w0, w, v), classLabels))
Accuracy(getPrediction(np.mat(dataMatrix), w0, w, v), classLabels)
if __name__ == '__main__':
dataMatrix, target = loadData('../Data/testSetRBF2.txt')
stocGradAscent(dataMatrix, target, 5, 5000, 0.01)
準備資料部分:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
def loadData(filename):
df = pd.read_csv(filename, sep=' ', names=['1', '2', 'target'])
data = []
target = []
for i in range(len(df)):
d = df.iloc[i]
ds = [d['1'], d['2']]
t = int(d['target'])
if t == 0:
t = -1
data.append(ds)
target.append(t)
return np.mat(data), np.mat(target).tolist()[0]
if __name__ == '__main__':
dataMatrix, target = loadData('../Data/testSetRBF2.txt')
print(dataMatrix)
print(target)
最後附上GitHub代碼: https://github.com/GreenArrow2017/MachineLearning/tree/master/MachineLearning/Factorization%20Machine