感知器PLA是一種最簡單,最基本的線性分類算法(二分類)。其前提是數(shù)據(jù)本身是線性可分的。
模型可以定義為,sign函數(shù)是階躍函數(shù),閾值決定取0或1。模型選擇的策略,利用經(jīng)驗(yàn)損失函數(shù)衡量算法性能,由于該算法最后得到一個(gè)分離超平面,所以損失函數(shù)可以定義為,由于對于誤分類點(diǎn),yi和wx+b的正負(fù)屬性相反,所以,所以加一個(gè)符號,來表征樣例點(diǎn)與超平面的距離。
算法選擇,最終的目標(biāo)是求損失函數(shù)的最小值,利用機(jī)器學(xué)習(xí)中最常用的梯度下降GD或者隨機(jī)梯度下降SGD來求解。
SGD算法的流程如下:輸入訓(xùn)練集和學(xué)習(xí)率
1、初始化w0,b0,確定初始化超平面,并確定各樣例點(diǎn)是否正確分類(利用yi和wx+b的正負(fù)性關(guān)系);
2、隨機(jī)在誤分類點(diǎn)中選擇一個(gè)樣例點(diǎn),計(jì)算L關(guān)于w和b在該點(diǎn)處的梯度值;
3、更新w,b,按照如下方向;
4、迭代運(yùn)行,直到滿足停止條件(限定迭代次數(shù)或者定義可接受誤差最大值);
如上所述,初值的選擇,誤分類點(diǎn)的選擇順序都影響算法的性能和運(yùn)行時(shí)間。PLA是一個(gè)很基本的算法,應(yīng)用場景很受限,只是作為一個(gè)引子來了解機(jī)器學(xué)習(xí),后面有很多高級的算法,比如SVM和MLP,以及大熱的deep learning,都是感知器的擴(kuò)展。
對于PLA,還有一個(gè)對偶問題,此處,簡單介紹一下對偶問題相關(guān)的知識。
對偶問題:
每一個(gè)線性規(guī)劃問題,我們稱之為原始問題,都有一個(gè)與之對應(yīng)的線性規(guī)劃問題我們稱之為對偶問題。原始問題與對偶問題的解是對應(yīng)的,得出一個(gè)問題的解,另一個(gè)問題的解也就得到了。并且原始問題與對偶問題在形式上存在很簡單的對應(yīng)關(guān)系:目標(biāo)函數(shù)對原始問題是極大化,對對偶問題則是極小化。
原始問題目標(biāo)函數(shù)中的收益系數(shù)(優(yōu)化函數(shù)中變量前面的系數(shù))是對偶問題約束不等式中的右端常數(shù),而原始問題約束不等式中的右端常數(shù)則是對偶問題中目標(biāo)函數(shù)的收益系數(shù);原始問題和對偶問題的約束不等式的符號方向相反;原始問題約束不等式系數(shù)矩陣轉(zhuǎn)置后即為對偶問題的約束不等式的系數(shù)矩陣;原始問題的約束方程數(shù)對應(yīng)于對偶問題的變量數(shù),而原始問題的變量數(shù)對應(yīng)于對偶問題的約束方程數(shù);對偶問題的對偶問題是原始問題。
總之他們存在著簡單的矩陣轉(zhuǎn)置,系數(shù)變換的關(guān)系。當(dāng)問題通過對偶變換后經(jīng)常會呈現(xiàn)許多便利,如約束條件變少、優(yōu)化變量變少,使得問題的求解證明更加方便計(jì)算可能更加方便。
對偶問題中,此處將w和b看成是x和y的函數(shù),w和b可表示為,ni表示更新次數(shù),模型,算法流程如下:輸入訓(xùn)練集,學(xué)習(xí)率
1、;
2、隨機(jī)選取誤分類點(diǎn)對,并更新計(jì)算,具體更新,依據(jù)上面的表達(dá)式;
3、直至沒有誤分類點(diǎn),停止計(jì)算,返回相應(yīng)的參數(shù);
原始問題和對偶問題都是嚴(yán)格可收斂的,在線性可分的條件下,一定可以停止算法運(yùn)行,會達(dá)到結(jié)果,存在多個(gè)解。
如果線性不可分,可以利用口袋算法,每次迭代更新錯(cuò)誤最小的權(quán)值,且規(guī)定迭代次數(shù)??诖惴ɑ谪澬牡乃枷搿K偸亲層龅降淖詈玫木€拿在自己的手上。 就是我首先手里有一條分割線wt,發(fā)現(xiàn)他在數(shù)據(jù)點(diǎn)(xn,yn)上面犯了錯(cuò)誤,那我們就糾正這個(gè)分割線得到wt+1,我們?nèi)缓笞寃t與wt+1遍歷所有的數(shù)據(jù),看哪條線犯的錯(cuò)誤少。
如果wt+1犯的錯(cuò)誤少,那么就讓wt+1替代wt,否則wt不變。 那怎樣讓算法停下來呢??——–我們就 自己規(guī)定迭代的次數(shù) 由于口袋算法得到的線越來越好(PLA就不一定了,PLA是最終結(jié)果最好,其他情況就說不準(zhǔn)了),所以我們就 自己規(guī)定迭代的次數(shù) 。
感知機(jī)python實(shí)現(xiàn)代碼
#coding = utf-8
import numpy as np
import matplotlib.pyplot as plt
class showPicture:
def __init__(self,data,w,b):
self.b = b
self.w = w
plt.figure(1)
plt.title(‘Plot 1’, size=14)
plt.xlabel(‘x-axis’, size=14)
plt.ylabel(‘y-axis’, size=14)
xData = np.linspace(0, 5, 100)
yData = self.expression(xData)
plt.plot(xData, yData, color=‘r’, label=‘y1 data’)
plt.scatter(data[0][0],data[0][1],s=50)
plt.scatter(data[1][0],data[1][1],s=50)
plt.scatter(data[2][0],data[2][1],marker=‘x’,s=50,)
plt.savefig(‘2d.png’,dpi=75)
def expression(self,x):
y = (-self.b - self.w[0]*x)/self.w[1]
return y
def show(self):
plt.show()
class perceptron:
def __init__(self,x,y,a=1):
self.x = x
self.y = y
self.w = np.zeros((x.shape[1],1))
self.b = 0
self.a = 1
def sign(self,w,b,x):
result = 0
y = np.dot(x,w)+b
return int(y)
def train(self):
flag = True
length = len(self.x)
while flag:
count = 0
for i in range(length):
tmpY = self.sign(self.w,self.b,self.x[i,:])
if tmpY*self.y[i]0:
tmp = self.y[i]*self.a*self.x[i,:]
tmp = tmp.reshape(self.w.shape)
self.w = tmp +self.w
self.b = self.b + self.y[i]
count +=1
if count == 0:
flag = False
return self.w,self.b
#原始數(shù)據(jù)
data = [[3,3],[4,3],[1,1]]
xArray = np.array([3,3,4,3,1,1])
xArray = xArray.reshape((3,2))
yArray = np.array([1,1,-1])
#感知機(jī)計(jì)算權(quán)值
myPerceptron = perceptron(x=xArray,y=yArray)
weight,bias = myPerceptron.train()
#畫圖
picture = showPicture(data,w=weight,b=bias)
picture.show()
責(zé)任編輯:ct
評論
查看更多