感知機(Perceptron)是最最最簡單的機器學習演算法(分類),同時也是深度學習中神經元的基礎元件;
演算法介紹
感知機與邏輯迴歸、SVM類似的是同樣是構建一個分割超平面來實現對資料點的分類,不同點在於超平面的查詢過程更加的簡單粗暴,簡單介紹下它的演算法流程:
- 假設二分類線性可分問題,x為輸入特徵,y為輸出標籤,y取值為-1和+1;
- 隨機超平面變數,由超平面公式\(w*x+b\),x為輸入資料點,不用管它,因此也就是w和b需要隨機初始化;
- 遍歷所有資料點,判斷該點在當前超平面下的分類是否準確,可以通過\(w*x_i+b\)與\(y_i\)的乘積來判斷,如果二者乘積大於0,說明二者符號一致,即分類正確,反之分類錯誤;
- 如果分類錯誤,則需要更新w和b,更新公式為:\(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\),因此滿足調整需求;
- 重複上述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()
最後
從演算法上看,感知機無疑是非常簡單的一種,但是它的訓練過程依然是完整的,因此作為機器學習入門演算法非常合適,尤其是在後續很多演算法甚至是深度學習中都能看到它的影子;