李航統計學習方法——感知機的實現

筆者,即將大四了,面臨秋招的挑戰,筆者以後想從事數據分析的相關工作,暑假實習自己在一家小公司做數據分析的工作,但是所接觸到的工作內容都是比較偏業務方向的,偏技術的比重並沒有我想象中的那麼高,因此我想抓緊時間複習一下,加上之前看過臺灣林軒田教授的機器學習視頻,因此現在想試着去實現一下李航統計學習方法上面設計到的機器學習算法。

正文

感知機

假設輸入空間是χ⊆Rn,輸出空間是γ=(+1,−1)。輸入χ∈X表示實例的特徵向量,對應於輸入空間的點;輸出y∈γ表示實例的類別。由輸入空間到輸出空間的如下函數:
f(x)=sign(wx+b)
稱爲感知機。其中,w和b爲感知機模型的參數,sign是符號函數,即:在這裏插入圖片描述

sign好像很簡單,當x大於等於0,sign輸出1,否則輸出-1。那麼往前遞歸一下,wx+b如果大於等於0,f(x)就等於1,反之f(x)等於-1。我們再回頭看一下感知機的函數f(x),簡而言之,就是我們要找到那條線,wx+b,能夠完美的將我們的數據集劃分出來。
得出結論:
如果一條直線能夠不分錯一個點,那就是一條好的直線
進一步來說:
如果我們把所有分錯的點和直線的距離求和,讓這段求和的舉例最小(最好是0,這樣就表示沒有分錯的點了),這條直線就是我們要找的。

感知機的學習策略
在這裏插入圖片描述
就是說,我們要找到一條直線,就算這條直線不能將數據集完美切分,那麼也要使錯誤分類的點到這條線上的距離之後最小,因此我們就要求每個點到線上的距離。
距離公式
在這裏插入圖片描述
其實,我們對誤分的點可以這樣理解,例如實際應該屬於線的右側,y>0,但實際上預測出來是在左側(wx+b<0),那就是分錯了,結果是負,這時候再加個符號,結果就是正了,再除以w的模長,就是單個誤分類的點到超平面的舉例。舉例總和就是所有誤分類的點相加。

感知機的原始形式
在這裏插入圖片描述
感知機的對偶形式
在這裏插入圖片描述
在這裏插入圖片描述
具體算法實現:

import numpy as np
def perceptron(dataSet,eta):
    # 獲取到訓練集的數據
    dataMat = dataSet[:, 0:2]
    # 獲取標籤數據
    labelMat = dataSet[:, -1]
    # 獲取訓練數據集的shape
    m,n=dataMat.shape
    # 初始化權重爲0,樣本長度保持一致
    w=np.zeros(n)
    # 初始化步長爲0
    b=0
    flag=True
    while flag:
        for i in range(m):
            # 獲取當前樣本的向量,當前樣本所對應的標籤,以及判斷是否是誤分標籤
            # 如果是誤分標籤,就進行梯度下降,更新w和b
            if  np.any(labelMat[i] * (np.dot(w, dataMat[i]) + b) <= 0):
                w = w + eta * labelMat[i] * dataMat[i].T
                b = b + eta * labelMat[i]
                print("weight, bias: ", end="")
                print(w, end="  ")
                print(b)
                flag = True
                break
            else:
                flag = False

    return w,b

def perceptron_dual(dataSet,eta):
    # 獲取到訓練集的數據
    dataMat = dataSet[:, 0:2]
    # 獲取標籤數據
    labelMat = dataSet[:, -1].reshape((-1,1))
    # 獲取訓練數據集的shape
    m, n = dataMat.shape
    w=np.zeros((m,1))
    b=0
    flag = True
    while flag:
        for i in range(m):
            if (labelMat[i, 0] * (np.sum((w * labelMat * np.dot(dataMat, dataMat[i].T).reshape((m, 1)))) + b)) <= 0:
                w[i] = w[i] + eta
                b = b + eta * labelMat[i]
                flag = True
                break
            else:
                flag = False
    w = np.dot(dataMat.T, w * labelMat)
    return w, b

if __name__ == '__main__':
    # 定義樣本數據集,與課本P29上的例題數據一樣
    dataSet = np.array([[3, 3, 1], [4, 3, 1], [1, 1, -1]])
    w, b = perceptron_dual(dataSet,1)
    print(w,b)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章