手擼機器學習演算法 - 感知機

HoLoong發表於2021-06-11

感知機(Perceptron)是最最最簡單的機器學習演算法(分類),同時也是深度學習中神經元的基礎元件;

演算法介紹

感知機與邏輯迴歸、SVM類似的是同樣是構建一個分割超平面來實現對資料點的分類,不同點在於超平面的查詢過程更加的簡單粗暴,簡單介紹下它的演算法流程:

  1. 假設二分類線性可分問題,x為輸入特徵,y為輸出標籤,y取值為-1+1
  2. 隨機超平面變數,由超平面公式\(w*x+b\)x為輸入資料點,不用管它,因此也就是wb需要隨機初始化;
  3. 遍歷所有資料點,判斷該點在當前超平面下的分類是否準確,可以通過\(w*x_i+b\)\(y_i\)的乘積來判斷,如果二者乘積大於0,說明二者符號一致,即分類正確,反之分類錯誤;
  4. 如果分類錯誤,則需要更新wb,更新公式為:\(w=w+y_i*x_i\)\(b=y_i+b\),這個公式可以這樣理解,對於w來說,需要更新說明\(w*x_i+b\)\(y_i\)的乘積小於0,假設\(y_i\)為-1,則\(w*x_i+b\)大於0,此時我們希望能減小\(w*x_i+b\),此時\(w=w+y_i*x_i\)等價於\(w=w-x_i\),因此滿足調整需求;
  5. 重複上述2,3,4步驟,直到所有點都分類正確為止;

程式碼實現

構建資料集

注意由於感知機只能處理線性可分的情況,因此下面資料集需要滿足線性可分,否則迭代過程無法終止;

X = np.array([[5,2], [3,2], [2,7], [1,4], [6,1], [4,5]])
Y = np.array([-1, -1, 1, 1, -1, 1])

隨機變數初始化

這裡的初始化值也是隨機的,對於w,由於輸入X是二維的,因此它也需要是二維的;

w,b = np.array([0, 0]),0

遍歷資料集及更新引數

run = True
while run:
    run = False
    for x,y in zip(X,Y):
        if y*(np.dot(w,x)+b)<=0:
            w,b = w+y*x,y+b
            run = True
            break

執行結果

完整程式碼

import numpy as np
import matplotlib.pyplot as plt

'''
感知機:線性二分類模型,擬合分割超平面對資料進行分類;
暴力實現:無腦針對每一個錯誤點進行w和b的更新,可以證明線上性可分情況下,有限次迭代可以完成劃分;
'''

# 初始化 w 和 b,np.array 相當於定義向量
w,b = np.array([0, 0]),0 

# 定義 d(x) 函式
def d(x):
    return np.dot(w,x)+b # np.dot 是向量的點積

# 歷史信用卡發行資料
# 這裡的資料集不能隨便修改,否則下面的暴力實現可能停不下來
X = np.array([[5,2], [3,2], [2,7], [1,4], [6,1], [4,5]])
Y = np.array([-1, -1, 1, 1, -1, 1])

run = True
while run:
    run = False
    for x,y in zip(X,Y):
        if y*d(x)<=0:
            w,b = w+y*x,y+b
            run = True
            break

print(w,b)

positive = [x for x,y in zip(X,Y) if y==1]
negative = [x for x,y in zip(X,Y) if y==-1]
line = [(-w[0]*x-b)/w[1] for x in [-100,100]]
plt.title('w='+str(w)+', b='+str(b))
plt.scatter([x[0] for x in positive],[x[1] for x in positive],c='green',marker='o')
plt.scatter([x[0] for x in negative],[x[1] for x in negative],c='red',marker='x')
plt.plot([-100,100],line,c='black')
plt.xlim(min([x[0] for x in X])-1,max([x[0] for x in X])+1)
plt.ylim(min([x[1] for x in X])-1,max([x[1] for x in X])+1)

plt.show()

最後

從演算法上看,感知機無疑是非常簡單的一種,但是它的訓練過程依然是完整的,因此作為機器學習入門演算法非常合適,尤其是在後續很多演算法甚至是深度學習中都能看到它的影子;

相關文章