感知机的详解
一.感知機的主要思想
1.1感知機定義
感知機是二分類的線性模型,其輸入為實例的特征向量,輸出為實例的類別,取+1或-1.
通過大量訓練集來訓練模型,最后得出最佳分離超平面,使所有樣本點能夠正確分類。
1.2 感知機原理
在對應輸入空間(特征空間)中,將實例線性劃分為正負兩類的分離超平面,屬于判別模型;若不是線性劃分的數據集,則無法獲得超平面。
數據集的線性可分
在給定數據集
?
其中?能夠將數據集的正實例和負實例完全正確地劃分到超平面的兩側,即對所有 yi=1的xi,有w*xi+b>0;對所有yi=-1的xi,有w*xi+b<=0,則稱該數據集線性可分,否則線性不可分。
那什么是超平面呢?
超平面是在空間Rn中的一個子空間Rn?1;在2維空間中的超平面是一條線,在3維空間中的超平面是一個平面。
在二維空間中,超平面?將特征空間劃分為兩部分,位于其中的點被分為正、負兩類,這樣的超平面??稱為分離超平面。
分離超平面:

數學中求點到線的距離
公式中的直線方程為Ax+By+C=0,點P的坐標為(x0,y0)。

樣本到超平面距離
我們假設超平面是h=w?x+b,其中w=(w0,w1,...wm),x=(x0,x1,...xm),樣本點x′到超平面的距離如下:

?
二.感知機的過程
假設輸入空間(特征空間)是X∈Rn,輸出空間是y={+1,-1}其中,X表示實例的特征向量,對應輸入特征空間的點;輸出y表示實例的類別。
感知機學習的目標是求得一個能夠將訓練集正實數例點和負實例點完全正確線性分開的分離超平面。為了找出這樣的超平面,即確定感知模型參數W,b。
?
三.數學模型
感知機從輸入空間到輸出空間的模型如下:
四.感知機的學習策略
由樣本點到超平面的距離公式可知:當輸入空間Rn中任意一點x到超平面的距離如下
其中??||w||是w??的?范數(即根號系數的平方和)
由于感知機的目的是逐漸訓練模型,使誤分類點歸為正確分類的位置,最后確定系數w,b得出最佳模型;那怎么判斷所有的樣本點已經歸為正確分類呢?下面是兩種方法:
自然選擇:可以通過誤分類點的數目判斷,但是損失函數不是w,b 連續可導,不宜優化(舍去)
另一選擇:求所有的誤分類點到超平面的總距離,當所有誤分類點的總距離變為0時,就判斷不存在誤分類了。
對于所有誤分類的數據點(xi,yi)來說都有:
? ? ? ? ? ? ? ?-yi(w.xi+b)>0
因為當(w.xi+b)>0時,本來正確的點應該yi>0,但是誤分類點的yi<0,所以-yi(w.xi+b)>0
當w.xi+b)<0時,本來正確的點應該yi<0,但是誤分類點的yi>0,所以-yi(w.xi+b)>0
因此求誤分類點x0(xi,yi)到超平面的距離:
去絕對值,引入-yi,因為yi只能+1,-1,且?-yi(w.xi+b)>0,得到:
最后所有誤分點集合到超平面的總距離為:(其中m為所有的誤分類點的集合)
不考慮1/(||w||),就是感知機的損失函數
?
五.感知機的學習算法
輸入:訓練數據集T=(x1,y1),(x2,y2),...,(xN,yN),yi∈{?1,+1},學習率η(0<η<1)
輸出:w,b;感知機模型f(x)=sign(w.x+b)
所有誤分點集合到超平面的總距離為s:(其中m為所有的誤分類點的集合)
不考慮,就是感知機的損失函數
顯然損失函數為非負數,如果沒有誤分類點,則損失函數是0;誤分類點越少,損失函數數值越小。
感知機學習策略:選取使損失函數最小的模型參數w,b?,即為感知機模型
至于為什么不考慮,可能有以下原因:
①不影響-yi(w?xi+b)正負的判斷,即不影響學習算法的中間過程。因為感知機學習算法是誤分類驅動的,這里需要注意的是所謂的“誤分類驅動”指的是我們只需要判斷??????yi(w?xi+b)的正負來判斷分類的正確與否,而并不影響正負值的判斷;??因為誤分類點始終要?yi(w?xi+b)>0,正確分類點?yi(w?xi+b)<0所以對感知機學習算法的中間過程可以不考慮。
②不影響感知機學習算法的最終結果。因為感知機學習算法最終的終止條件是所有的輸入都被正確分類,即不存在誤分類的點,所有誤分點集合到超平面的總距離為0,即此時損
失函數為0. 對應于的分子為0.則可以看出對最終結果也無影響。
?
感知機學習算法
是對上述損失函數進行極小化,得w和b。
但是用普通的基于所有樣本的梯度和的均值的批量梯度下降法(BGD)是行不通的,原因在于我們的損失函數里面有限定,只有誤分類的M集合里面的樣本才能參與損失函數的優化。所以我們不能用最普通的批量梯度下降,只能采用隨機梯度下降(SGD)。
目標函數:

原始形式算法
輸入:訓練數據集T=(x1,y1),(x2,y2),...,(xN,yN),yi∈{?1,+1},學習率η(0<η<1)
輸出:w,b;感知機模型f(x)=sign(w?x+b)
? ? ?4.??轉至(2),直至沒有誤分類點為止
直觀解釋:當一個實例點被誤分類,即位于分離超平面的錯誤一側,則調整 w,b的值,使分離超平面向該誤分類點的一側移動,以減少該誤分類點與超平面的距離,直至超平面越過該分類點使其被分類正確。
假設誤分類點集合m是固定的,那么對損失函數L(w,b)的梯度下降:
?
六.感知機原始形式實現(python)
完整代碼github:https://github.com/xucancan1617608769/machine-learning.git
主要代碼如下:(缺少部分plot文件代碼)
import numpy as np from sklearn.model_selection import train_test_split from sklearn.datasets import load_iris from plot import plot_decision_regions class perception(object):def __init__(self,alpha=0.01,loop=50): #初始化參數self.alpha=alphaself.loop=loopdef train(self,x,y): #訓練模型,x為m×n的矩陣,是多個數據集,y是m×1數據集標簽self.w=np.zeros(x.shape[1]) #初始化w,bself.b=0self.erros=[]err=0for _ in range(self.loop):for xi,yi in zip(x,y): #把它變成[(x1,y1),(x2,y2),..]的形式self.w=self.w+self.alpha*(yi-self.predict(xi))*xi #用了梯度下降算法upd=yi-self.predict(xi)self.b=self.b+self.alpha*upderr+=int(upd) #統計更新和,以便知道什么時候w,b趨向于穩定狀態if(err==0):breakself.erros.append(err)return selfdef predict(self,x): #預測值t=np.dot(x,self.w)+self.b #對每一個數據進行w*x+b線性轉化return np.where(t>0.0,1,-1) #預測值def main():iris = load_iris()X = iris.data[:100, [0, 2]] #提取100個帶有兩個特征值的數據集y = iris.target[:100] #提取100個標簽#print(y)y = np.where(y == 1, 1, -1) #構建正規標簽X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3) #用來隨機劃分樣本數據為訓練集和測試集的ppn = perception(alpha=0.1, loop=10)ppn.train(X_train, y_train) #訓練集訓練模型plot_decision_regions(ppn, X, y)#打印模型main()運行結果:
?
七.對偶形式算法
對偶形式的基本想法是:將w和b表示為實例xi和標簽yi的線性組合的形式,通過求解其系數而求得w和b.
原始形式的w,b梯度更新公式為:
w=w+ηyixi
b=b+ηyi
初始w,b均為0,我們的w,b經過了n次修改后的,參數可以變化為下公式,其中αi=ni*μ:
為了減少計算量,我們可以預先計算式中的內積,得到Gram矩陣
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? G=[xi,xj]N×N
?
八.對偶形式算法的實現
完整代碼github:https://github.com/xucancan1617608769/machine-learning.git
主要代碼如下:(缺少部分plot文件代碼)
from sklearn.datasets import load_iris import numpy as np from sklearn.model_selection import train_test_split from plot import plot_decision_regionsclass perception(object):def __init__(self,eta=0.1,loop=100):self.eta=etaself.loop=loop#構建gram矩陣def gram(self,X_train):n_sample= X_train.shape[0] #樣本的個數self.gramer=np.zeros((n_sample,n_sample)) #初始化gram矩陣for m in range(n_sample):for n in range(n_sample):self.gramer[m][n]=np.dot(X_train[m],X_train[n]) #內積矩陣def panduan(self,x,y,i): #判斷是否是誤分類點,遍歷其中一個樣本點看是否是誤分類點temp=self.bn_sample=x.shape[0]for m in range(n_sample): #遍歷其中一個樣本點,檢查是否是誤分類點temp+=self.alpha[m]*y[m]*self.gramer[i][m]return y[i]*tempdef fit(self,x_train,y_train): #訓練模型i=0x_sample=x_train.shape[0]self.alpha=[0]*x_sample #初始化alphaself.w = np.zeros(x_train.shape[1]) #初始化wself.b=0 #初始化bself.gram(x_train) #構建gram矩陣while(i<x_sample): #遍歷所有的樣本點if self.panduan(x_train,y_train,i)<=0: #判斷每個點是否是誤分類點self.alpha[i]+=self.eta #如果是,更新alpha[i]self.b+=y_train[i]*self.eta #更新 bi=0 #說明還有誤分類點,繼續檢查else:i+=1for j in range(self.loop): #更新wself.w+=self.alpha[j]*x_train[j]*y_train[j]return selfdef predict(self,x): #測試data,預測值targett=np.dot(x,self.w)+self.breturn(np.where(t>0.0,1,-1))def main():load=load_iris()x=load.data[:100,:2]y=load.target[:100]y=np.where(y==1,1,-1)x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.3)clf=perception(eta=0.1,loop=30)clf.fit(x_train,y_train) #訓練模型plot_decision_regions(clf, x, y)if __name__ == '__main__':main()運行結果:
?
總結
- 上一篇: 开灯变形问题(枚举法)
- 下一篇: oj 合并有序序列