感知機(perceptron)

    感知機屬於有監督的學習,生成的模型稱爲判別模型。其通過特定的函數將輸入的特徵向量,輸出爲實例的類別(+1或-1),該函數即爲將實例劃分爲兩類的分離超平面。爲獲得最優化的超平面,感知機引入了基於誤分類的損失函數。感知機是神經網絡和支持向量機的基礎。


有監督學習分爲生成模型和判別模型兩種。其分別含義如下:

(1)生成模型:通過輸入數據學習聯合概率分佈P(X,Y)得到的條件概率分佈P(Y|X)作爲預測模型;

(2)判別模型:通過輸入數據直接學習得到的決策函數f(x)或條件概率分佈P(Y|X)作爲預測模型。


1.perceptron 定義

在特徵空間中,感知機由輸入空間到輸出空間的函數爲

 f(x)=sign(w · x + b)

其中,參數w叫做權值向量,b稱爲偏置。w·x表示w和x的內積。sign爲符號函數,即

GTG_Y]{W_ZHV46PE$RDEGB3.png

2. perceptron的幾何意義

    感知機模型是線性分類模型,其線性方程 w·x+b=0 對應於特徵空間Rn中的一個超平面S(可以同時存在多個超平面),超平面將特徵空間分成兩部分,位於兩側的點分別爲正負兩類。其中w是超平面的法向量,b是超平面的截距。

wKioL1lUpT_zkvS7AAAdDh2wQxk316.png

3. perceptron 策略

    感知機的數據集必須是線性可分的,即存在至少一個超平面可以把數據完全正確的劃分到兩邊,進而得到參數w和b的值。爲此需要確定一個(經驗)損失函數,並將該損失函數最小化。

    損失函數我們可以考慮誤分類的總數,但是這樣得到的損失函數不是參數w、b的連續可導函數,不宜優化。因此我們選擇以誤分類點到超平面的距離之和作爲損失函數。最終得到損失函數定義爲:


wKioL1laIWWCytkXAAAtOYJh13Q097.png


超平面S的總的誤分類點集合爲M。其中,空間中任意一點到超平面的距離爲(||w||是w的L2範數):

wKioL1lUqLGQjn4xAAAHaSH6yzg990.png

4.perceptron 算法

    感知機學習其實就是損失函數最小化的過程。任意選取一個超平面,採用梯度下降法不斷逼近最小損失函數。逼近過程中並不是一次使用誤分類集合中所有點的梯度下降,而是一次隨機選取一個誤分類點使其梯度下降。

(1) 原始形式

實現過程:

輸入:訓練數據集T={(x1,y1),(x2,y2),(x3,y3),...,(xn,yn)}、學習率η(0 < η ≤ 1)

輸出:感知機模型f(x)=sign(w · x + b)

①選擇初始值w0,b0
②在訓練集中選取數據(xi,yi)
③如果yi(w ·xi+b)0

wKioL1laIc3S7ulHAAAjLVt0EP0976.png

④跳轉至②,直至訓練集中沒有誤分類點

算法解釋:當前存在某個點被誤分類時,則調整w,b的值,使分離超平面向該點一側運動,直到該點被超平面正確分類爲止。

#--*-- coding:utf-8 --*--
#初始化相關參數
w = [0, 0]
b = 0
setp = 0

#參數調整
def adjust(item, study_r=1): #學習率初始化爲1
    global w, b, setp
    for i in range(len(item[0])):
        w[i] += study_r * item[1] * item[0][i]
    b += item[1]
    setp += 1

def mis_value(item):
    #誤分類值計算,該值小於等於時表示當前存在誤分類點
    value = 0
    for i in range(len(item[0])):
        value += item[0][i] * w[i]
    value += b
    value *= item[1]
    return value

def decide(datas):
    flag = False
    for item in datas:
        mis = mis_value(item)
        if mis <= 0:
            flag = True
            adjust(item)
            print setp, item, w, b,mis
    if not flag:
        print setp+1, item, w, b,mis
        print "\n最終得到超平面相關參數:\n w= " + str(w) + ",  b=" + str(b)
    return flag

if __name__ == "__main__":
    training_set = [[(3, 3), 1], [(4, 3), 1], [(1, 1), -1]]  #以書本中的數據集爲例
    print '迭代次數', '誤分類值', '權值w', '截距b', '判斷值'
    while decide(training_set):
        continue

執行結果爲:

迭代次數 誤分類值 權值w 截距b 判斷值
1 [(3, 3), 1] [3, 3] 1 0
2 [(1, 1), -1] [2, 2] 0 -7
3 [(1, 1), -1] [1, 1] -1 -4
4 [(1, 1), -1] [0, 0] -2 -1
5 [(3, 3), 1] [3, 3] -1 -2
6 [(1, 1), -1] [2, 2] -2 -5
7 [(1, 1), -1] [1, 1] -3 -2
8 [(1, 1), -1] [1, 1] -3 1

最終得到超平面相關參數:
 w= [1, 1],  b=-3

(2)對偶形式

實現過程:

輸入:訓練數據集T={(x1,y1),(x2,y2),(x3,y3),...,(xn,yn)}、學習率η(0 < η ≤ 1)

輸出:α,b;感知機模型:

wKiom1laIjXBi9NUAAA5oCy9erI776.png

wKioL1laImvhXpa8AAAjk4eABvE753.png

α0,b0
②在訓練集中選取數據(xi,yi)
③如果wKiom1laJCPwZmeIAAAxwWC5OCM536.png

wKioL1laJFPAOdSQAAAgoNx3xgI824.png

④跳轉至②,直至訓練集中沒有誤分類點

算法解釋:當前存在某個點被誤分類時,則調整,b的值,使分離超平面向該點一側運動,直到該點被超平面正確分類爲止。

    由於對偶形式各訓練實例是以內積的形式存在,因此可以預先計算出實例間的內積,該結果以矩陣的方式存儲,即Gram矩陣(Geam matrix)。

#--*-- coding:utf-8 --*--
from numpy import *
setp = 0
b = 0

#獲取Gram矩陣
def gram_matrix(datas):
    gm = ones((len(datas), len(datas)), int) #生成全爲1的多維數組
    for i in range(len(datas)):
        for j in range(len(datas)):
            gm[i][j] = dot(datas[i][0], datas[j][0])
    return gm

#參數調整
def adjust(i, study_r=1): #學習率初始化爲1
    global alpha, b, setp
    alpha[i] += study_r
    b = b + y[i]
    setp += 1

#誤分類值計算,該值小於等於時表示當前存在誤分類點
def mis_value(i):
    global alpha, b, x, y
    value = dot(alpha * y, Gram[i])
    value = (value + b) * y[i]
    return value

def decide(datas):
    global alpha, b, x, y
    flag = False
    for i in range(len(datas)):
        mis = mis_value(i)
        if mis <= 0:
            flag = True
            adjust(i)
            print setp, alpha[0], alpha[1], alpha[2], b, mis
    if not flag:
        print setp+1, alpha[0], alpha[1], alpha[2], b, mis
        w = dot(alpha * y, x)   #alpha轉化爲w
        print "\n最終得到超平面相關參數:\n a1=" + str(alpha[0]) + " a2=" + str(alpha[1]) + " a3=" + str(alpha[2]) + " b=" + str(b), \
            "\n轉化後相關參數爲:\n w= " + str(w) + ",  b=" + str(b)
        return False
    return True


if __name__ == "__main__":
    training_set = array([[(3, 3), 1], [(4, 3), 1], [(1, 1), -1]])
    alpha = zeros(len(training_set),int)
    Gram = None
    y = array(training_set[:, 1],int)
    x = ones((len(training_set), 2),int)
    for i in range(len(training_set)):
        x[i] = training_set[i][0]
        Gram = gram_matrix(training_set)
    print '迭代次數', 'a1', 'a2', 'a3', '截距b', '判斷值'
    while decide(training_set):
        continue

執行結果爲:

迭代次數 a1 a2 a3 截距b 判斷值
1 1 0 0 1 0
2 1 0 1 0 -7
3 1 0 2 -1 -4
4 1 0 3 -2 -1
5 2 0 3 -1 -2
6 2 0 4 -2 -5
7 2 0 5 -3 -2
8 2 0 5 -3 1

最終得到超平面相關參數:
 a1=2 a2=0 a3=5 b=-3 
轉化後相關參數爲:
 w= [1 1],  b=-3






reference:《統計學習學習方法》




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