目錄
本章節根據統計學習方法,分爲模型、策略、算法三個方面來介紹感知機模型。 首先介紹感知機模型,接着介紹感知機的學習策略,也就是最小化損失函數,最後介紹感知機學習的算法,分爲原始形式和對偶形式(當中也介紹了算法的收斂性)【PS:算法也就是隨機梯度下降算法】
一、感知機模型
首先感知機(perceptron)模型是一個二類分類的線性分類模型,屬於判別模型。其輸入爲實例的特徵向量,輸出 爲實例的類別,取+1和–1二值。我是不喜歡看定義,倒不如用幾何模型來的直觀。
以上就是感知機模型的作用,旨在求出將訓練數據進行線性劃分分離超平面,爲此,導入基於誤分類的損失函數,利用梯度下降法對損失函數進行極小化, 求得感知機模型,利用學習得到的感知機模型對新的輸入實例進行分類。(做的就是分類的事情,塵歸塵土歸土!)。但是既然有了幾何模型,總得來點數學公式吧,不然怎麼寫代碼進行計算,是吧?
2.1, 2.2 兩個數學表達式,麻煩記住,劃重點!(滑稽!)
插個廣告,你學感知機就是想學神經網絡,是不是,來看看西瓜書上的感知機模型吧:
二、感知機的學習策略
學習策略,通過別人的講解,一般來說,學習策略就是指的損失函數(咱也不知道這句話對不對,姑且就這樣相信吧!)定義2.2首先來了一個數據集的線性可分性,說白了就是說,感知機只能解決線性可分的問題,不能解決非線性可分的問題。(啥?你不懂啥線不線性可分,還想知道爲什麼不能解決?什麼才能解決非線性可分?我不知道!你看看西瓜書的解釋吧!)
(什麼?看不懂?我也不懂,不看了!next!) 假設訓練數據集是線性可分的,感知機學習的目標是求得一個能夠將訓練集正實例點 和負實例點完全正確分開的分離超平面。爲了找出一個超平面(你就認爲是找一條線)也即確定感知機模型參數 w,b,需要確定一個學習策略,即定義(經驗)損失函數並將損失函數極小化。(通俗說,就是要找到一個方法求得一個最佳的w,b)。
這裏對於損失函數選擇,我的理解就是使得誤分類點到超平面的距離之和最小,如果距離爲 0 ,那就說明恭喜你,找到了一個可以完美分類的超平面了。以下給出一個大神的解釋。(還看不明白,那就繼續next,不要放棄,總有一天會搞明白的!)
我們從最初的要求有個f(x),引申到能只輸出1和-1的sign(x),再到現在的wx+b,看起來越來越簡單了,只要能找到最合適的wx+b,就能完成感知機的搭建了。前文說過,讓誤分類的點距離和最大化來找這個超平面,首先我們要放出單獨計算一個點與超平面之間距離的公式,這樣才能將所有的點的距離公式求出來對不?
先看wx+b,在二維空間中,我們可以認爲它是一條直線,同時因爲做過轉換,整張圖旋轉後wx+b是x軸,那麼所有點到x軸的距離其實就是wx+b的值對不?當然了,考慮到x軸下方的點,得加上絕對值->|wx+b|,求所有誤分類點的距離和,也就是求|wx+b|的總和,讓它最小化。很簡單啊,把w和b等比例縮小就好啦,比如說w改爲0.5w,b改爲0.5b,線還是那條線,但是值縮小兩倍啦!你還不滿意?我可以接着縮!縮到0去!所以啊,我們要加點約束,讓整個式子除以w的模長。啥意思?就是w不管怎麼樣,要除以它的單位長度。如果我w和b等比例縮小,那||w||也會等比例縮小,值一動不動,很穩。沒有除以模長之前,|wx+b|叫函數間隔,除模長之後叫幾何間隔,幾何間隔可以認爲是物理意義上的實際長度,管你怎麼放大縮小,你物理距離就那樣,不可能改個數就變。在機器學習中求距離時,通常是使用幾何間隔的,否則無法求出解。
然後我們來看看李航老師書上的解釋:
至於這裏爲什麼不考慮這個1/w,這個好像涉及一個函數間隔和幾何間隔,反正就是考不考慮,都不會影響分類效果,爲了簡化計算就不考慮了。
最後記住損失函數長啥樣就行了:
三、感知機學習算法
感知機學習算法採用的是隨機梯度下降算法,說白了,來看一段官方的解釋:
然後我這裏就只解釋感知機算法的原始形式和對偶形式,至於算法收斂性的證明我就不寫,(別問,問就是懶得證明!^_^,好吧,我就是不會,打我啊!)
感知機算法的原始形式
在這裏請允許我偷一個懶,我實在是不可能比原書的內容解釋的更好,因爲個人看來無論怎麼講,無論誰來講,自己不動手推一遍,根本就弄不清楚(可能是我自己太笨,B站上的講解視頻看了幾遍,別人的博客看了幾遍,數學表達式我都認識,就是感覺不像個人,最後自己按李航的書老老實實推一遍,把例題一步步做一遍,豁然開朗^_^,騷年,你還看?趕緊動手推啊!)
所以這裏我只擺出算法的解釋和算法的具體過程,具體內容大家可以參看原書:
上面我們說過,算法解決的問題就是使得損失函數最小化,求得合適的參數 w,b。這裏請大家記住以下的2.5, 2.6,2.7,別問爲什麼,記住理解就行了,劃重點,謝謝!
然後,解決問題的方法就是隨機梯度下降法:
(看不懂,我也看不懂,就這樣吧!next!)
Python實現代碼如下:
'''
author:SingGuo
datetime:2020年6月30日22:45:16
感知機模型的原始形式
'''
import numpy as np
# 初始化數據
def createData():
x = np.array([[3, 3], [4, 3], [1, 1]])
y = [1, 1, -1]
w = [0, 0]
b = 0
# lr = 1 # learning_rate
return x, y, w, b
# 感知機模型
# def sign(w, b, x):
# f = np.dot(x, w) + b # x .w + b
# return int(f)
# 更新系數w, b
def update(x, y, w, b, i):
w = w + y[i] * x[i]
b = b + y[i]
return w, b
def optimization(x, y, w, b):
misclassification = False
while not misclassification:
count = 0
for i in range(len(y)):
# f = sign(w, b, x)
if y[i] * (np.dot(w, x[i]) + b) <= 0: # 如果是一個誤分類實例點
print('誤分類點爲:', x[i], '此時的w和b爲:', w, b)
count += 1
w, b = update(x, y, w, b, i)
if count == 0:
print('最終訓練得到的w和b爲:', w, b)
misclassification = True
return w, b
if __name__ == '__main__':
x, y, w, b= createData()
optimization(x=x, y=y, w=w, b=b)
運行結果:
感知機模型的對偶形式
關於對偶形式,我第一反應就是啥叫對偶,在李航老師的書上僅僅只是說:
但是這個意思我懂,就是換種方法解題的意思,在周志華老師的西瓜書中支持向量機這一張對於對偶問題是這樣解釋的:
(凸二次規劃? 沒學過啊!過幾天百度看看!拉格朗日?……哎!西瓜書更不懂,於是我找到博客)博客上的解釋是這樣的:
(假裝看的懂的樣子,好吧,現在我還是值理解對偶就是換一種更簡單的方法簡化計算方便求解。至於爲啥會有這個形式,可能涉及凸優化的內容,咱也沒學,也不會瞎說,那就這樣吧!)下面是對偶形式的算法解釋:
別問我爲啥現在開始貼圖了,別問,問就是要睡覺!來吧,直接看代碼:
'''
author:SingGuo
datetime:2020年7月1日00:33:39
感知機模型的原始形式
'''
import numpy as np
def creatDataSet():
group = np.array([[3, 3], [4, 3], [1, 1]])
label = [1, 1, -1]
return group, label
def update(x, y, i):
global a, b, G
a[i] += 1
b = b + y
def cal(x, label, row):
global a, b, G
result = 0
for i in range(len(G[row])):
result += label[i] * a[i] * G[row][i]
result += b
result *= label[row]
return result
print(result)
def perceptron_func(group, label):
global a, b, G
isFind = False
n = group.shape[0]
x_col = group.shape[1]
a = np.zeros(n, dtype=np.int) # 初始化
b = 0
G = np.zeros((n, n), dtype=np.int)
# 計算Gam矩陣
for i in range(n):
for j in range(n):
G[i][j] = group[i][0] * group[j][0] + group[i][1] * group[j][1]
while isFind == False:
for i in range(n):
if cal(group[i], label, i) <= 0:
update(group[i], label[i], i)
print('誤分類點爲:', group[i], '此時的a1, a2, a3和b爲:', a, b)
break
elif i == n - 1:
print('最後迭代的結果爲:', a, b)
isFind = True
if __name__ == '__main__':
g, l = creatDataSet()
perceptron_func(g, l)
運行結果爲:
這個時候有人問了,爲啥兩個代碼風格不一樣?(哎!水平垃圾,對偶形式借鑑別人的,自己寫的過程中有一個錯誤解決不了!我下去慢慢解決)
(同桌:別找理由,你就是編程太垃圾了!)
(我:……)
參考文獻
【1】李航:《統計學習方法》
【2】周志華:《機器學習》
【3】感知機學習算法的對偶形式
【4】感知機對偶問題
【5】感知器、感知器對偶形式(含作業)||《統計學習方法》李航_第1章_藍皮(學習筆記)
【6】感知機的對偶形式
【8】感知機對偶形式手算過程
【9】統計學習方法(2)——感知機原始形式、對偶形式及Python實現
【10】李航統計學習方法之感知機學習(含感知機原始形式和對偶形式Python代碼實現)
完結,撒花!!!!!