本文感知機(perceptron)主要講解原理、相關的公式、算法並經過舉例計算來理解感知機算法的過程,最後附上相關的python代碼。若想要詳細的瞭解感知機公式的每一步推導過程及證實,本文不適合您。python
感知機原理公式實例及Python代碼
感知機是二類分類的線性分類模型,其中輸入爲實例的特徵向量,輸出爲它的類別,能夠取-1和+1兩種。固然,輸出也能夠取其餘的兩種值,例如a和b,對和錯,這裏的-1和+1只是一個標籤而已。git
感知機對應於特徵空間(能夠是二維,三維,...,n維)中將實例劃分爲正負兩類的分離超平面,屬於判別模型,是神經網絡與支持向量機的基礎。它是Rosenblatt在1957年提出的。github
本文中包括三部分:一、感知機模型;二、感知機的學習策略;三、感知機學習算法。算法
一、感知機模型
感知機定義:網絡
感知機的幾何解釋:線性方程app
對應於特徵空間中的一個超平面S,其中w是超平面的法向量,b是超平面的截距。這個超平面將特徵空間劃分爲兩個部分。位於兩部分的點分別被分爲正、負兩類。所以,超平面稱爲分離超平面(separating hyperplane),以下圖所示:機器學習
感知機學習,由訓練數據集(實例的特徵向量及類別)函數
二、感知機學習策略
2.1 數據集的線性可分性定義
2.2 感知機學習策略
數據集線性可分是感知機模型構建的前提。感知機學習的目標是求得一個可以將訓練集正負實例點徹底正確分開的分離超平面,即肯定感知機模型參數w和b,那麼須要肯定一個學習策略,定義(經驗)損失函數並將損失函數極小化。學習
損失函數的一個天然選擇是誤分類點的總數,但這樣的損失函數不是參數w和b的連續可導函數,不易優化。損失函數的另外一個選擇是誤分類點到超平面S的總距離,這是感知機所採用的。爲此,首先寫出輸入空間中任意一點x0到超平面的距離(該公式是點到直線間的距離公式):優化
感知機的學習策略是在假設空間中選取使損失函數式最小的模型參數w和b,即感知機模型。
三、感知機學習算法
3.一、感知機學習算法的原始形式
這種學習算法直觀解釋以下:當一個實例點被誤分類,即位於分離超平面的錯誤一側時,則調整w,b的值,使分離超平面向該誤分類點的一側移動,以減少該誤分類點與超平面間的距離,直到超平面越過該誤分類點使其被正確分類。
感知機學習算法的原始形式的代碼以下所示:
import numpy as np; import pandas as pd; import matplotlib.pyplot as plt; df=pd.read_excel("D:\pythondata\perceptrondata.xls");#讀取原題數據 df=pd.DataFrame(df); x=df.values[:,:-1];#x表明全部行的第一列到倒數第二列的數據,即分類實例的全部特徵向量 y=df.values[:,-1];#y表明df的倒數第一列數據,即分類實例的全部類別 a=x.shape; n=a[0];#n表明x特徵向量的行數 m=a[1];#m表明x特徵向量的列數 w=[];#建立空列表,w表明分離超平面中的法向量 for i in range(m): w.append(0);#列表的長度與特徵向量的特徵個數相同 #若直接命令w[0]=0,w[1]=0時,會報錯,直接按照索引向列表內添加東西時,由於空的列表不能直接指定其位置。 b=0;#b表明分離超平面的截距 k=1;#用來判別是否找到最優的超平面。假設值爲1,即未找到 while (k==1): k=0; for i in range(n): t=np.dot(w,x[i]);#用來計算w*x if (y[i]*(t+b)<=0): w=w+np.dot(y[i],x[i]); b=b+y[i]; k=1; print("分離超平面的法向量w={0},截距b={1}".format(w,b)); ########可視化結果 # def plot_and_scatter(df=None,w=0,b=0): xmin=df.values[:,:-1].min(); xmax=df.values[:,:-1].max(); xdiff=(xmax-xmin)*0.5; xx=np.linspace((xmin-xdiff),(xmax+xdiff),100); yy=-b-w[1]*xx; plt.figure(); plt.xlabel("X(1)"); plt.ylabel("X(2)");#設置座標軸的文字標籤 ax=plt.gca();# get current axis 得到座標軸對象 ax.spines["right"].set_color("none"); ax.spines["top"].set_color("none"); # 將右邊 上邊的兩條邊顏色設置爲空 其實就至關於抹掉這兩條邊 ax.xaxis.set_ticks_position("bottom"); ax.yaxis.set_ticks_position("left"); ax.spines["bottom"].set_position(("data",0)); ax.spines["left"].set_position(("data",0));#指定 data設置的bottom(也就是指定的x軸)綁定到y軸的0這個點上 plt.plot(xx,yy,"r"); color_list=["blue","green","black","pink","orange"]; y=df.values[:,-1]; a=set(y); a=list(a); y_num=len(a); t=0; for j in range(y_num): tt=a[j]; y_index=[i for i,y in enumerate(y) if y==tt]; x_group1=df.values[y_index,0]; x_group2=df.values[y_index,1]; plt.scatter(x_group1,x_group2); t=t+1; plot_and_scatter(df,w,b); plt.show();
感知機學習算法因爲採用不一樣的初值或選取不一樣的誤分類點,解能夠不一樣。正如例一圖中所示的那樣,有兩條分離超平面都可以分離正負兩類線性可分的點。
線性可分數據集感知機學習算法原始形式收斂,即通過有限次迭代能夠獲得一個將訓練數據集完整正確劃分的分離超平面及感知機模型,證實過程見李航《統計學習方法》書中第二章所示。
3.3 感知機學習算法的對偶形式
感知機學習算法的對偶形式的代碼以下所示:
import numpy as np; import pandas as pd; import matplotlib.pyplot as plt; df=pd.read_excel("D:\pythondata\perceptrondata.xls"); df=pd.DataFrame(df); x=df.values[:,:-1];#切片,分割特徵向量x和對應的類別y y=df.values[:,-1]; xy=x.shape;#輸出x的行數和列數 n=xy[0];#表明特徵向量x的行數 m=xy[1];#表明特徵向量x的列數 a=[]; b=0; for i in range(n): a.append(0); g=np.zeros((n,n)); for i in range(n): for j in range(n): for l in range(m): g[i][j]=g[i][j]+x[i][l]*x[j][l];#計算Gram矩陣 k=1; while (k==1):#當樣本中存在誤分點時 k=0;#本次循環中樣本假設不存在誤分點 for i in range(n): t=0; for j in range(n): t=t+g[i][j]*y[j]*a[j]; if (y[i]*(t+b)<=0): a[i]=a[i]+1;#計算a[i]的值 b=b+y[i];#計算b的值 k=1;#樣本中存在誤分點 w=[]; for j in range(m): w.append(0); for j in range(m): for i in range(n): w[j]=w[j]+a[i]*x[i][j]*y[i]; print("分離超平面的法向量w=",w,",截距b=",b) def plot_and_scatter(df=None,w=0,b=0): xmin=df.values[:,:-1].min(); xmax=df.values[:,:-1].max(); xdiff=(xmax-xmin)*0.5; xx=np.linspace((xmin-xdiff),(xmax+xdiff),100); yy=-b-w[1]*xx; plt.figure(); plt.xlabel("X(1)"); plt.ylabel("X(2)");#設置座標軸的文字標籤 ax=plt.gca();# get current axis 得到座標軸對象 ax.spines["right"].set_color("none"); ax.spines["top"].set_color("none"); # 將右邊 上邊的兩條邊顏色設置爲空 其實就至關於抹掉這兩條邊 ax.xaxis.set_ticks_position("bottom"); ax.yaxis.set_ticks_position("left"); ax.spines["bottom"].set_position(("data",0)); ax.spines["left"].set_position(("data",0));#指定 data設置的bottom(也就是指定的x軸)綁定到y軸的0這個點上 plt.plot(xx,yy,"r"); color_list=["blue","green","black","pink","orange"]; y=df.values[:,-1]; a=set(y); a=list(a); y_num=len(a); t=0; for j in range(y_num): tt=a[j]; y_index=[i for i,y in enumerate(y) if y==tt]; x_group1=df.values[y_index,0]; x_group2=df.values[y_index,1]; plt.scatter(x_group1,x_group2); t=t+1; plot_and_scatter(df,w,b); plt.show();
結果和例1一致,迭代步驟也是相互對應的。與原始形式同樣,感知機學習算法對偶形式的迭代也是收斂的,存在多個解。
感知機學習算法數據和代碼相關的github連接
參考文獻:
[1] 李航. 《統計學習方法》第二版
[2] Rosenblatt, Frank (1957). "The Perceptron—a perceiving and recognizing automaton". Report 85-460-1. Cornell Aeronautical Laboratory.
本文中的理論知識和例題主要來自於李航《統計學習方法》第二版第二章中,若是您須要系統的學習機器學習的理論知識,強烈推薦您看該書。主要的創新點在於代碼徹底是本身寫的,理論部分加入了一點點本身的理解。