感知機:python
假設輸入空間是\(\chi\subseteq R^n\),輸出空間是\(\gamma =\left( +1,-1\right)\)。輸入\(\chi\in X\)表示實例的特徵向量,對應於輸入空間的點;輸出\(y\in \gamma\)表示實例的類別。由輸入空間到輸出空間的以下函數:
\[ f\left( x\right) =sign\left( wx+b\right) \]
稱爲感知機。其中,w和b爲感知機模型的參數,sign是符號函數,即:
\[ sign\left( x\right) =\begin{cases}+1 &x\geq 0\\-1 &x<0 \end{cases} \]git
假設訓練數據集是線性可分的,感知機學習的目標就是求得一個可以將訓練集正實例點和負實例點完成正確分開的分離超平面。爲了找出這樣的超平面,即肯定感知機模型參數w,b,需定義損失函數並將損失函數極小化。
損失函數使用誤分類點到超平面S的總距離,所以輸入空間\(R^n\)中任何一點\(x_0\)到超平面S的距離爲:
\[ \dfrac {1}{\left\| w\right\| }\left| wx+b\right| \]
在這裏,\(\left\| w\right\|\)是w的\(L_2\)範數。github
對於誤分類的數據\(\left(x_i,y_i\right)\)來講,算法
\[ -y_i( wx_i+b) >0 \]函數
成立。由於當\(wx_i + b >0\)時,\(y_i=-1\),而當\(wx_i + b < 0\)時,\(y_i=+1\),所以,誤分類點\(x_i\)到超平面S的距離是:學習
\[ -\dfrac {1}{\left\| w\right\| }y_i( wx_i+b) \]
這樣,假設超平面S的誤分類點集合爲M,那麼因此誤分類點到超平面S的總距離爲:優化
\[ -\dfrac {1}{\left\| w\right\| }\sum _{x_{i} \in M}y_{i}\left( wx_{i}+b\right) \]
不考慮\(\dfrac {1}{\left\| w\right\| }\),就獲得感知機學習的損失函數:
\[ L\left( w,b\right) =-\sum _{x_{i\varepsilon }n}y_i\left(wx_i+b\right) \]
其中M爲誤分類點的集合。spa
感知機算法是使得損失函數\(L(w,b)\)極小化的最優化問題,能夠使用隨機梯度降低法來進行最優化。code
假設誤分類點集合M是固定的,那麼損失函數\(L(w,b)\)的梯度由
\[ \nabla _{w}L\left( \omega ,b\right) =-\sum _{x_{i\varepsilon }n}y_{i}x_{i} \]blog
\[ \nabla _{b}L\left( \omega ,b\right) =-\sum _{x_{i\varepsilon }n}y_{i} \]
給出,隨機選取一個誤分類點\((x_i,y_i)\),對w,b進行更新:
\[ w\leftarrow w+\eta y_ix_i \]
\[ b\leftarrow b+\eta y_i \]
其中\(\eta(0<\eta \leq1)\) 稱爲學習率(learning rate),這樣經過迭代能夠使得損失函數\(L(w,b)\)不斷減少,直到爲0。
感知機算法原始形式的主要訓練過程:
def trainPerceptron(dataMat, labelMat, eta): m, n = dataMat.shape weight = np.zeros(n) bias = 0 flag = True while flag: for i in range(m): if np.any(labelMat[i] * (np.dot(weight, dataMat[i]) + bias) <= 0): weight = weight + eta * labelMat[i] * dataMat[i].T bias = bias + eta * labelMat[i] print("weight, bias: ", end="") print(weight, end=" ") print(bias) flag = True break else: flag = False return weight, bias
完整代碼能夠前往個人github查看,還有可視化過程。
https://github.com/yangliu0/MachineLearning/tree/master/Perceptron
假設\(w_0,b_0\)均初始化爲0,對誤分類點經過
\[ w\leftarrow w+\eta y_ix_i \]
\[ b\leftarrow b+\eta y_i \]
逐步修改\(w,b\),設修改n次,則\(w,b\)關於\((w_i,y_i)\)的增量分爲是\(\alpha_i y_ix_i\)和\(\alpha_i y_i\),這裏的\(\alpha_i=n_i \eta\),其中\(n_i\)表示第i個點誤分類的次數,這樣最後學習到的\(w,b\)能夠分別表示爲
\[ w=\sum ^{N}_{i=1}\alpha _{i}y_{i}x_{i} \]
\[ b=\sum ^{N}_{i=1}\alpha _{i}y_{i} \]
實例點更新的次數越多,意味着它距離分離超平面越近,也就越難正確分類。
訓練過程:輸出\(\alpha,b\),其中\(\alpha = (\alpha_1, \alpha_2,...,\alpha_N)^T\)
(1)\(\alpha\leftarrow0, b\leftarrow0\)
(2)在訓練集中選取數據\((x_i, y_i)\)
(3)若是\(y_{i}\left( \sum ^{n}_{j=1}\alpha _{j}y_{j}x_{j}\cdot x_{i}+b\right)\leq0\),則
\[ \alpha_i \leftarrow\alpha_i + \eta \]
\[ b\leftarrow b+\eta y_i \]
(4)轉到(2),直到沒有錯誤。
最後經過\(w=\sum ^{N}_{i=1}\alpha _{i}y_{i}x_{i}\)計算出\(w\),使用上述過程求出的\(b\),即計算出模型參數。
如下就是上述感知機對偶形式的python訓練代碼:
def trainModel(dataMat, labelMat, alpha, b, eta): flag = True while flag: for i in range(m): if (labelMat[i, 0] * (np.sum((alpha * labelMat * np.dot(dataMat, dataMat[i].T).reshape((m, 1)))) + b)) <= 0: alpha[i] = alpha[i] + eta b = b + eta * labelMat[i] flag = True break else: flag = False w = np.dot(dataMat.T, alpha * labelMat) return w, b
如下就是結果可視化圖,能夠看出,訓練的感知機算法對線性可分的點進行了很好的劃分。
感知機算法的原始形式和對偶形式分別對應了支持向量機(SVM)的兩種相應形式,是它們的基礎。
上述兩種形式的感知機算法完整實現能夠在個人github查看,使用python實現。
https://github.com/yangliu0/MachineLearning/tree/master/Perceptron
[1]統計學習方法.李航