[臺大機器學習筆記整理]perceptron learning algorithm

Machine Learning的基本模型是


A takes D and H to get g


其中A是Algorithm,D是Data,H是Hypothesis,g是goal


其總體的運行結構如圖所示






接下來以最簡單的感知器舉例說明


感知器模型


最簡單的二分線性感知器,由各維度乘以其權重,相加後,得到的結果與閾值進行比較,並得出結論。


用公式描述,則是如下:




在這裏我們將與閾值比較的這一過程直接放在了算式中,得到結果後判斷結果與0的大小關係即可


將以上式子向量化,可以得到
h(x)=sign(w.T*x)


在這裏,上面的式子即是Hypothesis,是我們用於模擬實際情況的一個假設模型。


感知器學習算法(Perceptron Learning Algorithm)


容易看到,一個假設一般有參數(如上面式子中的w)供我們進行調整,這樣我們能根據Data對其進行調整,最後得到一個儘可能接近實際的映射(f)的一個映射關係g。
既然是machine learning,那麼調整這一步當然是交給machine了。machine如何到達這一目的的方式,就是我們需要的learning algorithm。


用最簡單的輸入兩個維度的perceptron(Hypothesis: h(x)=sign(w1x1+w2x2+w0))進行舉例




如果令x1,x2爲座標軸,f(x)(即實際結果)以o或x的形式表現,那麼我們需要的learning algorithm應該可以找到一條直線,像右圖一樣將兩種結果分開,即一邊爲正,一邊爲負。右圖中的分割直線可以認爲f(x),即理想的映射關係。


如果我們需要得到一個近似於f的映射關係g,那麼g首先應該能將我們手上的數據集中的數據準確的分開。


在這裏採用的辦法是使用一個隨機的g0作爲起始,根據它判斷錯誤的點對g進行修正




在這裏,我們的修正方式是將原先的權重向量加上結果向量與維度向量的乘積。


當y=+1,那麼類似於第一個圖,w+yx將使得新的w更加偏向於x,以使得修正後的結果爲h(x)>0,而類似有第二圖的修正。


以算式進行說明,則是


(由correct的關係式可以推出)
理想情況下yw.T*x應該大於零,因此在需要進行correct的情況下(yw.T*x<0)並經過correct以後,yw.T*x比之前增加


Cyclic PLA:如此循環,直到跑了一圈(記錄下最後一次出錯的data的下標)後沒有出現錯誤,則得到了我們的結果式子g
(當然,在這個算法中假設了所有數據是線性可分的,否則會陷入死循環)


這個即是在開頭時所描述的我們令假設hypothesis接近於理想映射f所使用的learning algorithm,在運行完成後我們會得到一個形式類似假設hypothesis但w等參數均已經“學習”好了的映射關係g


(在PLA的運行過程中爲了進行向量運算,會給x向量增加一個x0=1)


證明:在線性可分的前提下,PLA總是能夠停下,得到最終將數據集中所有結果準確分開的一組w,作爲goal


線性可分,因此存在一組w令對所有y與x均有




則yw.T*x>0對於所有點均成立



代入以下算式,得到



(對於每次update均能使當前的w更接近於理想的w)


第二個式子




(w的模的增長是有限的)
第二個式子確保了wt不會增長過快


另外,由第一個式子的藍色部分與第二個式子的紅色部分(均令當前w的下標爲T且一直推到w0=0時),最終可以得到




左邊即爲理想的w與第T次修正後的w的內角cos值。因此,左邊總是小於等於1


而後將左邊置爲1,可以得到T小於等於橙色式子中常數平方的倒數,因此通過有限的次數我們可以得到一個能成功將data按正確的結果切分開的w。


對Cyclic PLA的優化


以上對Cyclic PLA的介紹中可以明確看出其優缺點


有點:模型與算法簡單,易於實現


缺點:僅適用於線性可分的數據,而且由於T與最終的理想w有關,其訓練步數(在這裏是correction)也是不確定的


首先考慮線性不可分的情況


理想狀況下應該找到一個w,使得






然而這是一個NP-hard問題,因此不考慮這一方式


因此採用pocket algorithm進行優化


pocket:保存當前得到的最理想的w,進行修正後如果得到的mistake數量更少,則更換爲新的w


設置iteration的上限,在進行足夠多次的循環後終止,並返回pocket中的w作爲最終的結果


總結:


用perceptron learning algorithm爲例子,介紹了機器學習的基本模型,即A takes D and H to get g


其中A是Algorithm,D是Data,H是Hypothesis,g是goal


在PLA中,A即爲perceptron learning algorithm(precisely, Cyclic PLA),Hypothesis是線性模型




通過A的學習逐步修正H中的w參數最終得到目標g


PLA的證明可以由correction的式子及假設一個最終的目標w通過一系列推導得到,在推導過程中還得到了性質(1)每次correct後w均會更接近於理想的w(2)w的模小於等於某個常數,這個常數與數據集有關


簡單的Cyclic PLA存在(1)不適用於線性不可分問題(2)循環次數未知兩個缺點,可以考慮使用pocket algorithm進行優化

附錄:

python的簡單pla實現


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 i<train_set_size-1:
                i+=1
            else:
                i=0
        self.w=w


    def predict(self,x):
        return sign(np.dot(self.w,x))


def sign(x):
    if x>0:
        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()












發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章