python 反射機制,感知機(perceptron):原理、python實現及sklearn.linear_model.Perceptron參數詳解

 2023-11-05 阅读 28 评论 0

摘要:文章目錄1.感知機模型介紹2.感知機學習策略3.感知機學習算法3.1 原始形式3.2.1算法收斂性的證明3.2對偶形式4.python實現感知機算法4.1手寫感知機算法4.2 scikit-learn實操4.2.1sklearn.linear_model.Perceptron參數解釋4.2.2sklearn.linear_model.Perceptron屬性解釋4.2.3sk

文章目錄

  • 1.感知機模型介紹
  • 2.感知機學習策略
  • 3.感知機學習算法
    • 3.1 原始形式
      • 3.2.1算法收斂性的證明
    • 3.2對偶形式
  • 4.python實現感知機算法
    • 4.1手寫感知機算法
    • 4.2 scikit-learn實操
      • 4.2.1sklearn.linear_model.Perceptron參數解釋
      • 4.2.2sklearn.linear_model.Perceptron屬性解釋
      • 4.2.3sklearn.linear_model.Perceptron實戰

1.感知機模型介紹

感知機是一個二分類線性分類模型,二分類是指輸出YYY的分類只有兩個值,取+1和-1,線性分類是指模型將訓練數據集用一個線性超平面分離(如果特征空間XXX?\sube?RnR^nRn,那么該線性超平面就是n-1維)。

感知機模型屬于判別模型,即通過輸入的樣本直接學習到fff(xxx),而沒有學習到XXXYYY的聯合分布PPP(XXX,YYY

感知機模型的形式:f(x)=sign(w?x+b)f(x) = sign(w \centerdot x+b)f(x)=sign(w?x+b) sign為符號函數,當w?xw \centerdot xw?x +++ b >0時取1,<0時取-1。w?xw \centerdot xw?x+++b即是該模型要學習的超平面,將實例劃分為正負兩類。

python 反射機制。感知機模型的假設空間:定義在特征空間中的所有線性分類模型,{fff|f(x)f(x)f(x)=w?xw \centerdot xw?x+++b}

2.感知機學習策略

假設空間中有無數個模型,那么哪一個才是最好的呢?這就涉及到模型的學習策略

假設數據集是線性可分的,即存在一個超平面 w?xw \centerdot xw?x+++b=0將數據集的正例和反例完全分開。正例在w?xw \centerdot xw?x+++b>0一側,反例在另一側。
yi={+1if?w?x+b>0?1if?w?x+b<0y_i =\begin{cases} +1 &\text{if } w \centerdot x+b>0 \\ -1 &\text{if } w \centerdot x+b<0 \end{cases}yi?={+1?1?if?w?x+b>0if?w?x+b<0?

損失函數也叫代價函數,是指模型分類錯誤時的代價值。這里的模型的損失函數可以是誤分類點的比例,但是該函數不是要求參數www 和 b的連續可導函數,不利于求解最優模型。

另一種損失函數是考慮所有誤分類點到該超平面w?xw \centerdot xw?x+++b=0的總距離。特征空間任意一點x0x_0x0?到超平面距離為:∣w?x0+b∣∥w∥\LARGE\frac{| w \centerdot x_0+b|}{\|w \|}ww?x0?+b?, ∥w∥\|w \|w為向量www的模長。我們要計算的就是所有誤分類的點到超平面的距離。若所有誤分類點屬于集合M,則
CostFunction=∑xi?M∣w?xi+b∣∥w∥CostFunction = \sum\limits_{x_i \sube M}\LARGE\frac{| w \centerdot x_i+b|}{\|w \|}CostFunction=xi??M?ww?xi?+b?
但是有絕對值,也不好對參數求導,于是想到若(xi,yi)(x_i, y_i)(xi?,yi?) 誤分類,即 ?yi(w?xi+b)-y_i(w \centerdot x_i+b)?yi?(w?xi?+b)>0,所以絕對值可去,不過得加個負號。而且模長始終為正不用考慮,可以去掉,于是得到最終的損失函數:
L(w,b)=?∑xi?Myi(w?x+b)\Large L(w,b)=-\sum\limits_{x_i \sube M}y_i(w \centerdot x+b)L(w,b)=?xi??M?yi?(w?x+b)
最優模型即是使以上損失函數達最小值時的模型。

3.感知機學習算法

3.1 原始形式

知道了什么樣的模型是最優的,可是如何來求解最優模型模型呢?這就是學習算法要做的事。感知機利用 隨機梯度下降法(stochastic gradient descent) 來求解出w,bw,bw,b從而得出最優模型。
梯度我理解為偏導數組成的向量,損失函數L(w,b)L(w,b)L(w,b)有兩個參數,梯度也就有兩個元素(有兩個方向下降),L可以沿著這兩個方向下降。

java和python的區別??L(w,b)?w=?∑xi?Myixi\LARGE\frac{\partial L(w,b)}{\partial w} =-\sum\limits_{x_i \sube M}y_ix_i?w?L(w,b)?=?xi??M?yi?xi?
?L(w,b)?b=?∑xi?Myi\LARGE\frac{\partial L(w,b)}{\partial b} =-\sum\limits_{x_i \sube M}y_i?b?L(w,b)?=?xi??M?yi?

隨機梯度下降法隨機選取一個誤分類點(xj,yj)(x_j,y_j)(xj?,yj?)(而不是像在線性回歸的梯度下降法中使用所有點)對w,bw,bw,b進行更新,然而隨機一誤分類點并不能保證w,bw,bw,b是一直是朝著正確的方向改進。
w←w+ηyjxj\LARGE w \leftarrow w + \eta y_jx_jww+ηyj?xj?
b←b+ηyj\LARGE b \leftarrow b +\eta y_jbb+ηyj?
η\Large\etaη 為步長,或叫學習率,決定L下降的快慢。那么我有疑問,這樣更新L一定會逐漸下降嗎?
更新前:
L0(w,b)=?∑xi?Myi(w0?xi+b0)\Large L_0(w,b)= \Large-\sum\limits_{x_i \sube M}y_i(w_0 \centerdot x_i+b_0)L0?(w,b)=?xi??M?yi?(w0??xi?+b0?)
更新w1=w0+ηyjxj;b1=b0+ηyj\LARGE w_1= w_0 + \eta y_jx_j ; \LARGE b_1 = b_0 +\eta y_jw1?=w0?+ηyj?xj?;b1?=b0?+ηyj?
更新后L1(w,b)=?∑xi?Myi(w1?xi+b1)=?∑xi?Myi((w0+ηyjxj)?xi+b0+ηyj)=?∑xi?Myi(w0?xi+b0)?∑xi?Myi(ηyjxj?xi+ηyj)=L0(w,b)?∑xi?Myi(ηyjxj?xi+ηyj)\Large \begin{aligned} L_1(w,b) &=-\sum\limits_{x_i \sube M}y_i(w_1 \centerdot x_i+b_1)\\ &=-\sum\limits_{x_i \sube M}y_i( (w_0 + \eta y_jx_j)\centerdot x_i+b_0+\eta y_j)\\ &=-\sum\limits_{x_i \sube M}y_i(w_0\centerdot x_i+b_0) -\sum\limits_{x_i \sube M}y_i (\eta y_jx_j \centerdot x_i +\eta y_j)\\ &=L_0(w,b)-\sum\limits_{x_i \sube M}y_i (\eta y_jx_j \centerdot x_i +\eta y_j) \end{aligned} L1?(w,b)?=?xi??M?yi?(w1??xi?+b1?)=?xi??M?yi?((w0?+ηyj?xj?)?xi?+b0?+ηyj?)=?xi??M?yi?(w0??xi?+b0?)?xi??M?yi?(ηyj?xj??xi?+ηyj?)=L0?(w,b)?xi??M?yi?(ηyj?xj??xi?+ηyj?)?
問題是,減號后面這項真的大于0嗎,這個式子里面就一項一定是大于0的(即i=ji=ji=j時),但是其他項就無法判斷了吧。如果不是大于0就說明L不一定是一直下降的。然而感知機算法好像整個過程并沒有計算過這個損失函數,它是所有誤分類點導致的誤差,這個算法的思想不是直接改進w,bw,bw,b使它減小,而是逐步地改進它的每一個部分(也就是每一個誤分類點),從而達到整體的改進。也就是說隨機梯度下降算法計算的并不是真正的梯度,真正的梯度應該像批梯度計算那樣需要所有樣本才能計算。隨機梯度只是用一個樣本進行對真正的梯度進行了一次預估,因此可能會有偏差。即隨機梯度下降算法不一定保證每次前進方向都是正確的,所以會帶來波動。 在更新(w,b)(w,b)(w,b)這個過程中,可能會出現總損失函數L(w,b)L(w,b)L(w,b)上升的情況, 因為你只針對一個點更新(w,b)(w,b)(w,b),有可能會使原先分類正確的點又誤分類,也有可能使誤分類的點距離更遠,但是總體是螺旋式下降,所以如果數據集是線性可分,那么損失函數迭代下去就會向0靠近,下面證明為什么該算法雖然有波動,但最終還是會收斂到0。

3.2.1算法收斂性的證明

對于線性可分的數據集,利用批量梯度下降的話,(w,b)(w,b)(w,b)每一次的更新都必然使損失函數L(w,b)\ L(w,b)?L(w,b)下降,最終必然會收斂到0,沒必要進行收斂性的證明。但是因為使用隨機了隨機梯度下降,每一次(w,b)(w,b)(w,b)的更新不是使總的損失函數L(w,b)\ L(w,b)?L(w,b)下降,而是僅僅使隨機誤分類點(xj,yj)(x_j,y_j)(xj?,yj?)的損失——即 ?yi(w?x+b)-y_i(w \centerdot x+b)?yi?(w?x+b) 下降。那么每一次更新都可能使得總損失函數L(w,b)\ L(w,b)?L(w,b)上升,產生波動。那是否這個算法就是失效了呢?下面證明,即使L(w,b)\ L(w,b)?L(w,b)不是一直下降,會產生波動,但是經過有限次迭代后,最終還是會收斂到0,可以找到一個將訓練數據集完全正確劃分的分離超平面。
證明的出發點是,證明誤分類的次數k是有上限的,每一次誤分類后(w,b)(w,b)(w,b)都會更新,最多經過有限次(k的上限)次更新后,可以找到訓練數據集完全正確劃分的分離超平面。證明過程不寫了,看其他博主的吧。

感知機算法的收斂證明

3.2對偶形式

對偶形式與原始形式的輸入一樣,但是輸出略有差異,它是將w,bw,bw,b表示為xix_ixi?yiy_iyi?的線性組合,輸出的是α\alphaα和b,而不是直接輸出www的最終值:
和上面更新相同w1=w0+ηyjxj\LARGE w_1= w_0 + \eta y_jx_jw1?=w0?+ηyj?xj? ; b1=b0+ηyj\LARGE b_1 = b_0 +\eta y_jb1?=b0?+ηyj?
那么如果整個迭代過程對誤分類點(xi,yi)(x_i,y_i)(xi?,yi?)更新了nin_ini?次(如果一直分類正確就是0次),這個點對w和bw和bwb的貢獻分別為 ni?ηxiyin_i* \eta x_iy_ini??ηxi?yi?ni?ηyin_i* \eta y_ini??ηyi?,記αi=ni?η\alpha_i=n_i*\etaαi?=ni??η, 最終w,bw,bw,b的結果為:
w=∑i=1Nni?ηyixi=∑i=1Nαiyixi\Large w =\displaystyle\sum_{i=1}^Nn_i*\eta y_ix_i=\displaystyle\sum_{i=1}^N\alpha _iy_ix_iw=i=1N?ni??ηyi?xi?=i=1N?αi?yi?xi?
b=∑i=1Nni?ηyi=∑i=1Nαiyi\Large b =\displaystyle\sum_{i=1}^Nn_i*\eta y_i=\displaystyle\sum_{i=1}^N\alpha_i y_ib=i=1N?ni??ηyi?=i=1N?αi?yi?
所以最終輸出的模型為:f(x)=sign(∑i=1Nαiyixi?x+b)f(x)=sign(\displaystyle\sum_{i=1}^N\alpha _iy_ix_i \centerdot x+b)f(x)=sign(i=1N?αi?yi?xi??x+b)

4.python實現感知機算法

感知機的基本原理就寫完了,但是對于一個機器學習算法,如果只停留在理解但是不會運用這個階段,那是遠遠不夠的,必須要通過一些實例,多敲代碼,在這個過程加深對算法的理解。這里選取sklearn內置數據庫的iris(鳶尾屬植物)數據集進行實戰演練。

import pandas as pd
import numpy as np
from sklearn.datasets import load_iris 
import matplotlib.pyplot as plt
%matplotlib notebook

python有用嗎、將數據存儲到dataframe中:

iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['label'] = iris.target
df

結果如下:
iris 數據表格

總共有4個特征——sepal花萼的長寬以及petal花瓣的長寬,但是為了更直觀的觀察數據,這里只取花萼的長寬這兩個特征進行這次練習,并且感知機是二分類模型,所以只選取前100行(只包含0、1兩類)。

df = df.iloc[:100, [0, 1, -1]]
df.columns = ['sepal_length', 'sepal_width', 'label']
df

結果如下:
在這里插入圖片描述
畫出圖形:

plt.figure()
plt.scatter(df.iloc[:50, 0], df.iloc[:50,1], label='0')
plt.scatter(df.iloc[50:100, 0], df.iloc[50:100,1], label='1')
plt.xlabel('sepal_length')
plt.ylabel('sepal_width')
plt.legend()

在這里插入圖片描述
直觀上感覺是線性可分的。提取出特征與輸出值,將標簽0改為-1。

data = np.array(df)
X, y = data[:,:-1], data[:,-1]
y[y==0] = -1

4.1手寫感知機算法

def perceptron(X,y,eta):w = np.zeros(X.shape[1])   # 初始化w,bb = 0def sign_y(x,w,b):              # 計算w*x+b的值,以便于乘以真實標記y判斷是否誤分類y1 = np.dot(x,w)+breturn y1while True:   # 下面定義了循環結束條件,只要還有誤分類點,就會一直循環下去wrong_count = 0    for i in range(len(X)): # 100個樣本x = X[i]yi_lable = y[i]if yi_lable * sign_y(x,w,b)<=0: # 說明誤分類了,更新w,bw = w + eta*yi_lable*xb = b + eta*yi_lablewrong_count += 1if wrong_count == 0:    # 定義函數結束條件,一次循環下來,誤分類點為0,即所有點都正確分類了return w,b
w,b=perceptron(X,y,eta=0.6) # 解包

計算得到w=[ 31.6 , -40.28],b=-49.6,畫出圖形觀察是否正確分類:

fig = plt.figure()
x_ticks = np.linspace(4.3,7,10)
ax = plt.subplot(1,1,1)
ax.set_xticks(x_ticks)
ax.set_xlim(4.2,7.1)
ax.set_ylim(1.9,4.5)
ax.set_xlabel('sepal_length')
ax.set_ylabel('sepal_width')
plt.scatter(df.iloc[:50, 0], df.iloc[:50,1], label='0')
plt.scatter(df.iloc[50:100, 0], df.iloc[50:100,1], label='1')
plt.plot(df['sepal_length'], (w[0]*df['sepal_length'] + b)/(-w[1]))
plt.legend(loc = 'best')

python爬蟲教程、得到下圖:
在這里插入圖片描述
可以看到分類正確,那兩個看起來在線上的點其實也是分列于兩側,在jupyter notebook圖形操作界面用放大鏡放大后就能看出來。

4.2 scikit-learn實操

手寫只是為了加深對算法的理解,但是一般實操還是調包更快更方便。感知機官方參數介紹可以點擊這里

4.2.1sklearn.linear_model.Perceptron參數解釋

用于創建感知機模型時傳遞的參數。

參數名稱參數取值參數解釋
penalty默認=None,即不加懲罰項,‘l2’(L2正則) or ‘l1’(L1正則) or ‘elasticnet’(混合正則)懲罰項,加上懲罰項主要為了避免模型過擬合風險
alpha默認=0.0001,取值為浮點數如果penalty不為None,則正則化項需要乘上這個數
l1_ratio默認=0.15,取值在[0,1]一般只在penalty=elasticnet時用,當l1_ratio =0就是L2正則,當l1_ratio =1就是L1正則,當在(0,1)之間就是混合正則
fit_interceptbool值,默認=True是否對參數 截距項b進行估計,若為False則數據應是中心化的
max_iterint整數,默認=1000最大迭代次數,哪怕損失函數依舊大于0
tolfloat or None,默認=10^(-3)迭代停止的標準。如果不為None,那么當loss-pre-loss<tol的時候,就會停止迭代。因為當前迭代造成的損失函數下降太小了,迭代下去對loss影響不大了。
shufflebool值,默認=True每輪訓練后是否打亂數據
verbose取值為整數,默認=0verbose = 0 為不在標準輸出流輸出日志信息,verbose = 1 為輸出進度條記錄;verbose = 2 為每個epoch輸出一行記錄
eta0取值雙精度浮點型double,默認=1學習率,決定梯度下降時每次參數變化的幅度
n_jobs取值為 int or None,默認=None在多分類時使用的CPU數量,默認為None(或1),若為-1則使用所有CPU
random_state取值為int, RandomState instance or None,默認=None當 shuffle =True時,用于打亂訓練數據
n_iter_no_change取值int,默認=5在提前停止之前等待驗證分數無改進的迭代次數,用于提前停止迭代
early_stopping取值bool值,默認=False當驗證得分不再提高時是否設置提前停止來終止訓練。若設置此項,當驗證得分在n_iter_no_change輪內沒有提升時提前停止訓練
class_weight取值為dict, {class_label: weight} 或者 “balanced”或者None,默認=None用于擬合參數時,每一類的權重是多少。當為None時,所有類的權重為1,等權重;當為balanced時,某類的權重為該類頻數的反比,當為字典時,則key為類的標簽,值為對應的權重
warm_start取值為bool,默認=False若為True則調用前一次設置的參數,使用新設置的參數

4.2.2sklearn.linear_model.Perceptron屬性解釋

屬性名稱屬性的類型屬性解釋
classes_array 一維數組,shape=(k,) ,k為y的類別數量放著y所有分類的數組,如感知機是array([-1., 1.])
coef_array 二維數組輸出訓練后的模型參數w的數組,不包含截距項b。當為二分類時,該數組shape=(1,n),n為特征數量。當為多分類時shape=(k, n)
intercept_array 一維數組輸出訓練后的模型截距b的數組。當為二分類時,該數組shape=(1,)。當為多分類時shape=(k, )
loss_function_損失函數的類別即用的哪種損失函數來定義模型輸出值與真實值之間的差異
n_iter_整數即模型停止時共迭代的次數
t_整數模型訓練時,權重w更新的總次數,等于n_iter_*樣本數量

4.2.3sklearn.linear_model.Perceptron實戰

from sklearn.linear_model import Perceptron
perceptron = Perceptron(fit_intercept=True, max_iter=1000, shuffle=True)
perceptron.fit(X, y)  # 默認學習率為1
w = perceptron.coef_[0]  # ,注意輸出的是二維數組,加上[0]后, w=[ 23.2 -38.7]
b = perceptron.intercept_  # b=-5

用擬合好的模型畫出圖形

在這里插入圖片描述
參考:李航博士《統計學習方法》
二分類線性分類模型感知機從原理到實例就講完了,請大家多多指教,謝謝閱讀。

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://808629.com/168587.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 86后生记录生活 Inc. 保留所有权利。

底部版权信息