1. 程式人生 > >感知機--Python實現

感知機--Python實現

感知機簡介

感知機是二類分類的線性分類模型,其輸入為例項的特徵向量,輸出為例項的類別,取+1和-1二值。感知機對應於輸入空間(特徵空間)中將例項劃分成正負兩類的分離超平面,屬於判別模型。感知機學習指在求出將訓練資料進行線性劃分的分離超平面。

  • 前提條件:線性可分的資料集。
  • 損失函式:基於誤分類的損失函式。
  • 學習演算法:梯度下降法。
  • L0範數:向量中非0的元素個數。
  • L1範數:向量中各元素絕對值之和。
  • L2範數:向量中各元素的平方和之後開根號。

原始形式

輸入:訓練資料集T={(x1,y1),(x2,y2),,(xN,yN)}T=\{(x_1,y_1),(x_2,y_2),\dots,(x_N,y_N) \}

,學習率η(0<η1)\eta(0<\eta\leq1) 輸出:w,b 感知機模型 f(x)=sign(wx+b) f(x) = sign(w \cdot x + b)

  1. 選取初值w0,b0w_0,b_0
  2. 在訓練集中選取資料(xi,yi)(x_i,y_i)
  3. 如果yi(wxi+b)0y_i(w\cdot x_i+b)\leq0 ww+ηyixi w\leftarrow w + \eta y_i x_i
    bb+ηyib \leftarrow b + \eta y_i
  4. 轉至2,直至訓練集中沒有誤分類點
原始形式Python程式碼:

import numpy as np


Data_set = np.array([[3,3,1],[4,3,1],[1,1,-1]])

w = np.array([0,0])
b = 0
theta = 1
history = []

def ganzhiji(dataset):
    
    global w, b, theta , history
    s = dataset.shape[0]
    history.append([w,b])
    
    for i in range(s):
        if (dataset[i,2]*(np.dot(w,dataset[i,0:2])+b)<=0):
            w = w + theta*dataset[i,2]*dataset[i,0:2]
            b = b + theta*dataset[i,2]
            ganzhiji(dataset)
            return w,b 

if __name__=='__main__':
    s = ganzhiji(Data_set)
    print("最終迭代引數為:" ,s)
    print("迭代過程引數變化: \n" )
    for i in history:
        print(i)

執行結果: 感知機原始形式執行結果

對偶形式

輸入:線性可分的資料集T={(x1,y1),(x2,y2),,(xN,yN)}T=\{(x_1,y_1),(x_2,y_2),\dots,(x_N,y_N) \},學習率η(0&lt;η1)\eta(0&lt;\eta\leq1) 輸出:α,b\alpha,b 感知機模型: f(x)=sign(j=1Nαjyjxjx+b),α=(α1,α2,,αN)Tf(x)=sign(\sum_{j=1} ^N \alpha_jy_jx_j\cdot x+b),其中\alpha = (\alpha_1,\alpha_2,\dots,\alpha_N)^T

  1. α0,b0\alpha \leftarrow0,b\leftarrow0
  2. 在訓練集中選取資料(xi,yi)(x_i,y_i)
  3. 如果yi(j=1Nαjyjxjx+b)0y_i(\sum_{j=1}^N \alpha_jy_jx_j\cdot x+b)\leq0 αiαi+η\alpha_i\leftarrow\alpha_i+\eta bb+ηyb\leftarrow b+\eta y
  4. 轉至2直到沒有誤分類資料。

對偶形式中訓練例項僅以內積的形式出現,可以預先將訓練集中例項間的內積計算出來並以矩陣的形式儲存,這個矩陣就是Gram矩陣:G=[xixj]NNG=[x_i \cdot x_j]_N*_N

對偶形式
import numpy as np

Data_set = np.array([[3,3,1],[4,3,1],[1,1,-1]])

datax = Data_set[:,0:2]
datay = Data_set[:,2]
length = Data_set.shape[0]
history =[]
Gram = np.zeros([length,length])
for i in range(length):
    for j in range(length):
        Gram[i][j] = np.dot(datax[i],datax[j])
print("輸出格拉姆矩陣:\n",Gram)

alpha = np.zeros([1,Data_set.shape[0]])[0]
b = 0

def ganzhiji2():
    global w1,w2,history,alpha,b
    w1 , w2 = np.dot(alpha*datay,datax)
    history.append([[w1,w2],b])
    for i in range(Data_set.shape[0]):
        if((np.dot(alpha*datay,Gram[:,i])+b)*datay[i] <= 0):
            alpha[i] = alpha[i] + 1
            b = b + datay[i]
            ganzhiji2()
    return alpha,b
    
if __name__== '__main__':
    s = ganzhiji2()    
    print("最終迭代引數為:",w1,w2,b)
    print("迭代過程引數變化: \n" )
    for i in history:
        print(i)

執行結果: 對偶形式執行結果

當訓練集線性可分時,感知機學習演算法存在無窮多個解,其解由於不同的初值或迭代順序不同而可能有所不同。