所謂的PLA 就是以生物的”神經元模型”為基礎所開發出的演算法,但是只是概念類似於真實的生物神經元傳遞訊號的機制而已,除了這個之外,其實就沒啥太大的關係了,以下是神經元的基本構造 :
(from : wiki : https://zh.wikipedia.org/wiki/%E6%84%9F%E7%9F%A5%E5%99%A8#/media/File:Complete_neuron_cell_diagram_zh.svg)
左邊的突觸是神經接收訊息的地方 (input),如input的訊號強總和強度大於等於某一個值(threshold),這個神經元就會透過軸突(axon)發送訊息到右邊去,並且傳給下一個神經元,舉例來說,當有人K你的膝蓋力道過大時,膝蓋的神經就會發訊息給肌肉內的神經進行所謂的膝跳反應。
而首先,我要說的是,這個Perceptron learning algorithm只有在線性可分的情況下才會正確的分類 ( 演算法才會停止 ),而什麼是線性可分? 我們來補充一點這邊的知識吧,不然,你各位會很難進的去這一篇裡面。
線性 & 非線性 :
線性(linearity)
- 在一個數學的模式中,各變數均以一次指數出現時,通稱為線性,例如直線方程式為ax+by=c,平面方程式形成ax+by+cz=d。
對於一個函數f(或為轉換)而言,若f 具有可加性:f(x+y)=f(x)+f(y),與齊次性:f(αx)=αf(x)(α為純量),則稱為具有線性。例如微分,積分,差分均為線性算子。
在一個物理的系統中,若輸出y 已知為輸入x 的線性函數y=f(x),因為這個系統具有線性 ,因此形成一種疊加(superposition)的性質(參見superpositon)。 - 在數學上來說,是指方程的解滿足線性疊加的原理,也就是方程任意的兩個解的線性疊加,仍然是一個方程式的解。
非線性(non-linear)
- 非線性就是指兩個變數之間的關係,是不成比例(線性)的關係。
- 非線性就是指輸出和輸入不是成正比利的情況。
簡單的補充,我們還是要回到原本的主題Perceptron這個演算法,我們要注意一件事情,那就是這個演算法只有在資料是線性可分的情況下,才能正確的分類(才會停),什麼叫做線性可分? 以2D來說,就是在平面上找一條線,去切出這兩個群,3D的話就是在空間中找一個平面去切出兩群。
講回去原本的生物神經元模型那邊,我們假設左邊的突觸有n個,每一個input以x1,x2,x3,……xn來表示,當w1*x1 + w2*x2 + w3*x3+….wn*xn >某一個定值,就會觸發神經元發送訊號出去 ( W1,W2,….Wn 以及某一個定值都是這個神經元根據過往的經驗學會的數字。
- 這個就是科學家再說train 這個model到底在train甚麼,其實就是找出w1,w2…wn。
import numpy as np
import matplotlib.pyplot as plt
class perceptron:
def __init__(self,dimension):
#size=the dimension of x
self.dimension=dimension
self.w=np.zeros(dimension+1)
def cyclic_train(self,X,Y):
#X should be a list including the tuples storing the inputing x
w=self.w
train_set_size=len(X)
X=np.array([list(x)+[1] for x in X])
error_loc=range(train_set_size)
i=0
while i!=error_loc:
#correct and record the last error location
if sign(np.dot(X[i],w))!=Y[i]:
w=w+X[i]*Y[i]
error_loc=i
#move on and iterate cyclic
if i0:
return 1
elif x<0:
return -1
else:
return 0
#The prepared test data
Xtr=[(2,4),(-1,2),(-3,-1),(-1,-4),(1,-1),(2,-4)]
Ytr=[1,1,1,-1,-1,-1]
#test
p1=perceptron(2)
p1.cyclic_train(Xtr,Ytr)
fig=plt.figure()
axes=fig.add_axes([0.1, 0.1, 0.8, 0.8])
axes.scatter([Xtr[i][0] for i in range(len(Xtr)) if Ytr[i]==1],[Xtr[i][1] for i in range(len(Xtr)) if Ytr[i]==1],color='red')
axes.scatter([Xtr[i][0] for i in range(len(Xtr)) if Ytr[i]==-1],[Xtr[i][1] for i in range(len(Xtr)) if Ytr[i]==-1],color='blue')
k=-p1.w[0]/p1.w[1]
b=-p1.w[2]/p1.w[1]
axes.plot([-10,10],[k*(-10)+b,k*10+b])
axes.spines['right'].set_color('none')
axes.spines['top'].set_color('none')
axes.xaxis.set_ticks_position('bottom')
axes.spines['bottom'].set_position(('data',0))
#set position of x spine to x=0
axes.yaxis.set_ticks_position('left')
axes.spines['left'].set_position(('data',0))
#set position of y spine to y=0
plt.show()