感知機(perceptron)
模型:
簡答的說由輸入空間(特征空間)到輸出空間的如下函數:
稱為感知機,其中,\(w\)和\(b\)表示的是感知機模型參數,\(w \in R^n\)叫做權值,\(b \in R\)叫做偏置(bias)
感知機是一種線性分類模型屬於判別模型。
感知機的幾何解釋:線性方程:$$w \cdot x + b = 0$$對應於特征空間\(R^n\)中的一個超平面S,這個超平面將特征空間分為兩個部分,位於兩部分的點(特征向量)分別被分為正負兩類,超平面S被稱為分離超平面。
策略
首先感知機的數據集是對線性可分的數據集的,所謂線性可分就是存在這么一個超平面可以把數據完全正確的划分到兩邊。
感知機學習的目標就是要得出\(w \quad b\),需要確定一個(經驗)損失函數,並將損失函數最小化。對於這個損失函數我們最容易想到的就是誤分類的總數,但是我們也要注意到這個不能夠是\(w \quad b\)的可導連續函數,所以我們選擇點誤分類的點到超平面的距離作為損失函數。最終得到損失函數定義為:
算法
這里我們用的是隨機梯度下降法,思想是:首先隨機選擇一個分離超平面\(w_0,b_0\)然后用隨機梯度下降不斷最小化目標函數,最終得到完全正確的分類效果
感知機學習算法的原始形式
1.選擇初始值\(w_0,b_0\)
2.在訓練集中選取數據\((x_i,y_i)\)
3.如果\(y_i(w \cdot x_i+b)\le 0\)
4.跳轉至2,直至訓練集中沒有誤分類點
代碼實現:
w = [0, 0]
b = 0
def createDataSet():
"""
create dataset for test
"""
return [[(3, 3), 1], [(4, 3), 1], [(1, 1), -1]]
def update(item):
"""
update with stochastic gradient descent
"""
global w, b
w[0] += item[1] * item[0][0]
w[1] += item[1] * item[0][1]
b += item[1]
def cal(item):
"""
calculate the functional distance between 'item' an the dicision surface. output yi(w*xi+b).
"""
res = 0
for i in range(len(item[0])):
res += item[0][i] * w[i]
res += b
res *= item[1]
return res
def check():
"""
check if the hyperplane can classify the examples correctly
"""
flag = False
for item in training_set:
if cal(item) <= 0:
flag = True
update(item)
if not flag:
print "RESULT: w: " + str(w) + " b: " + str(b)
return flag
if __name__ == "__main__":
training_set = createDataSet()
while check():
pass
感知機學習算法的對偶形式:
1.\(\alpha \gets 0,b \gets 0\)
2.在訓練集中選取數據\((x_i,y_i)\)
3.如果\(y_i(\sum_{j=1}^{N}\alpha_jy_ix_j\cdot x_i+b) \le 0\)
4.轉至2,直到沒有誤分類的數據
代碼實現
這里主要是有一個叫做gram矩陣的東西,因為我們發現下面的計算過程中都是以內積的形式存在的,所以說這部分的值可以先算出來。\(G=[x_i*x_j]\)
import numpy as np
def createDataSet():
"""
create data set for test
"""
return np.array([[[3, 3], 1], [[4, 3], 1], [[1, 1], -1]])
def cal_gram():
"""
calculate the Gram matrix
"""
g = np.empty((len(training_set), len(training_set)), np.int)
for i in range(len(training_set)):
for j in range(len(training_set)):
g[i][j] = np.dot(training_set[i][0], training_set[j][0])
return g
def update(i):
"""
update parameters using stochastic gradient descent
"""
global alpha, b
alpha[i] += 1
b = b + y[i]
def cal(i):
"""
cal
"""
global alpha, b, x, y
res = np.dot(alpha * y, Gram[i])
res = (res + b) * y[i]
return res
def check():
"""
check if the hyperplane can classify the examples correctly
"""
global alpha, b, x, y
flag = False
for i in range(len(training_set)):
if cal(i) <= 0:
flag = True
update(i)
if not flag:
w = np.dot(alpha * y, x)
print "RESULT: w: " + str(w) + " b: " + str(b)
return False
return True
if __name__ == "__main__":
training_set = createDataSet()
alpha = np.zeros(len(training_set), np.float)
b = 0.0
Gram = None
y = np.array(training_set[:, 1])
x = np.empty((len(training_set), 2), np.float)
for i in range(len(training_set)):
x[i] = training_set[i][0]
Gram = cal_gram()
while check():
pass
本文鏈接
以上內容參考自《統計學習方法》