前言
感知機算法(perceptron)是用於二分類的線性分類模型,將輸入實例劃分爲正例和負例的一個超平面,屬於判別模型。感知機算法旨在求出將訓練數據進行線性劃分的分類超平面,基於誤分類的損失函數,利用梯度下降法對損失函數進行極小化。
符號函數
符號函數應該都知道,這裏簡單過一下。
表達式:
圖像如下:
可以看到,符號函數就是一個典型的二分類算法,將輸入實例劃分正負兩類。
感知機模型
定義感知機模型:
假設輸入實例,對應的輸出分類,由輸入到輸出的感知機模型如下:
其中,w和b爲感知機模型參數,叫做權值,叫做偏置,表示w和x的內積。
下面解釋下這個模型:
觀察式(2),感知機模型的假設空間是線性分類模型,即函數集合。
爲了方便說明,這裏假設即每個樣本只有兩維特徵,那麼此時方程對應於二位空間中的一個超平面,其中w是超平面的法向量,b是超平面的截距。這個超平面將特徵空間劃分爲兩個部分,一部分爲正類,一部分爲負類。此時模型圖形如下:
所以,感知機算法就是不斷更新學習參數和,使得所有樣本被正確分類。
感知機算法
1、原始形式
給定一個線性可分的數據集:
感知機算法的目標是求得一個能夠將訓練集正實例和負實例點完全正確分開的分離超平面,爲了找出這樣的超平面,即確定感知機的參數和,需要定義損失函數,並將損失函數極小化。
怎麼選擇損失函數?這裏選擇了誤分類點到超平面S的總距離。
輸入數據集中的任意一點到超平面的距離:
對於誤分類點:
所以式(4)結合起來,就是:
因此,誤分類點到超平面S的距離爲:
假設超平面的誤分類點集合爲M,那麼所有誤分類點大超平面S的總距離爲:
將感知機的損失函數(也是感知機的經驗風險函數)定義如下:
結合式(5),顯然損失函數是非負的。如果沒有誤分類點,損失函數值爲0。而誤分類點越少,誤分類點離超平面越近,損失函數值就越小。
感知機算法的學習 策略就是取損失函數(8)最小的模型參數和。
下面就開始計算梯度:
損失函數極小化,即:
分別對和求導
參數更新,隨機選取一個誤分類點(x_{i},y_{i}),對進行更新:
爲學習率,通俗地說用它來設置超平面的移動的幅度,通常取0~1。通過迭代可以是損失函數不斷減小,直到爲0。
算法的直觀解釋:
當一個實例點被誤分類,即位於分離超平面的錯誤一側,則調整和的值,使分離超平面向該誤分類點的一側移動,以減少該誤分類點與超平面間的距離,直至超平面越過該誤差分類點使其被正確分類。
算法流程(直接截圖了):
算法的收斂性這裏就不給出證明了,他一定是收斂的,但前提是其數據集是線性可分的。當訓練集線性不可分時,感知機算法不收斂,迭代結果會發生震盪。
2、對偶形式
先說明爲什麼會有對偶形式,或者說相比於原始形式,對偶形式有什麼優點?、
再觀察式(11)和(12),對於每一個誤分類點,每次都要更新向量:w和b,然後對每一個新的w和b,要判斷下一個點是否被誤分類,還需要計算一個內積(式(5)),這樣計算量就比較大。
那麼再看看對偶形式的感知機。
對偶形式的算法判斷一個點是否被誤分類,使用如下公式:
觀察上式,雖然說也存在內積計算,但是每次計算的內積是相同的運算,也就是說可以在算法之前,將該內積矩陣提前計算出來,而不必像原始形式必須每次都要計算內積。
代碼
import numpy as np
import matplotlib.pylab as plt
#主函數
def main():
#構造訓練集
X_train = np.array([[3,3],[4,3],[1,1]])
y = np.array([1,1,-1])
#構造感知機
perceptron = MyPerceptron()
perceptron.fit(X_tain,y)
class MyPerceptron:
def __init__(self):
self.w = None
self.b = 0
self.learning_rate = 1
def fit(self,X_train,y):
self.w = np.zeros(X_train.sape[1])
i = 0
while i < X_train.shape[0]:
X = X_train[i]
y = y[i]
if y * (np.dot(self.w,X)+self.b)<=0:
self.w = self.w +self.learning_rate * np.dot(y,X)
self.b = self.b + self.learning_rate *y
i = 0 #如果是誤判點,則從頭檢測
else:
i += 1