Factorization Machine

#Factorization Machine---因子分解機 ###①target function的推導 logistics regression algorithm model中使用的是特徵的線性組合,最終獲得的分割平面屬於線性模型,可是線性模型就只能處理線性問題,因此對於非線性的問題就有點難處理了,對於這些複雜問題通常是兩種解決方法①對數據自己進行處理,好比進行特徵轉換,和函數高維擴展等等。②對算法模型自己進行擴展,好比對linear regression加上正則化懲罰項進行改進獲得lasso regression或者是ridge regression。 Factorization Machine就是一種對logistics regression的一種改進,線性的部分權值組合是不變的,在後面增長了非線性的交叉項。 target function:$$y_{score} = w_0+\sum_{i=1}^nw_ix_i+\sum_{i=1}^{n-1}\sum_{j=i+1}^n<v_i, v_j>x_ix_j$$ $$<v_i, v_j> = \sum_{f=1}^kv_{i,f}*v_{j,f}$$ v_i表示的是係數矩陣V的第i維向量,v_i=(v_{i,1},v_{i,2},v_{i,3},...v_{i,k}),k的大小稱爲是度,度越大表明分解出來的特徵就越多。對於每個特徵都會對應有一個k維的向量。前兩部分是傳統的線性模型,後一個部分就是將臉剛剛互不相同的特徵份量之間的相互關係考慮進來了。也就是不一樣特徵之間的吸引程度。 若是使用男女戀愛來解釋這個模型,得分score是男生對女生的一個喜歡程度,w_0表明的就是底分,能夠當作是男生對於女生的第一感受。對於第二部分能夠當作是女生的優秀程度,第三部分就至關因而男女之間的事交互關係了,也就是男女之間的感受,若是兩個男生對於同一個女生的感受是一致的,那麼他們的v就是一致的,從本質上說,因子分解機也是探索一種類似性,其與協同過濾算法是相似的,可是這二者的區別在於,因子分解機同時考慮了男生和男生間的類似性以及女生和女生間的類似性,可是協同過濾要麼只考慮男生之間的類似性,要麼只考慮女生之間的類似性。 ###優化求解target functiongit

y_{score} = w_0+\sum_{i=1}^nw_ix_i+\sum_{i=1}^{n-1}\sum_{j=i+1}^n<v_i, v_j>x_ix_j$$ $$<v_i, v_j> = \sum_{f=1}^kv_{i,f}*v_{j,f}$$對於原始的target function計算複雜度是$O(n^2)$,採用公式$((a+b+c)^2-a^2-b^2-c^2)/2$的公式。因而化簡一波:![](https://upload-images.jianshu.io/upload_images/10624272-efc234eaef6d66ff.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
這樣就成功的把複雜度降到了$O(n)$
**FM能夠解決的問題主要是四種:
1.迴歸問題:這時候的error function:$$L = \frac{1}{2}\sum_{i=1}^m(y_i^{'}-y_i)^2

2.二分類問題:$$L = \sum_{i=1}^m-ln(sigmoid(y_i^{'}y_i))$$ 3.排序問題。 4,推薦系統。** 接下來就是模型的求解,天然就是求導了,咱們作的是二分類問題,因此採用的就是第二種loss function求導,按照求導常規求取便可:github

w_0 = w_0-\alpha[1-sigmoid(y^{'}y)]*y
w_i = w_i-\alpha[1-sigmoid(y^{'}y)]*y*x_i
v_{i,f} = v_{i,f}-\alpha[1-sigmoid(y^{'}y)]*y*[x_i\sum_{j=1}^nv_{j,f}x_j-v_{i,f}x_i^2]

###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)

複製代碼

準備數據部分:bash

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代碼: github.com/GreenArrow2…app

相關文章
相關標籤/搜索