這是我參加mlhub123組織的書(shū)籍共讀計(jì)劃的讀書(shū)筆記,活動(dòng)見(jiàn)mlhub第一期讀書(shū)計(jì)劃
- 閱讀章節(jié):第二章:感知機(jī)
- 開(kāi)始時(shí)間:2018-09-18
- 結(jié)束時(shí)間:2018-09-21
- 目標(biāo):讀完第二章,掌握基本概念,產(chǎn)出一篇筆記
- 博客地址
本章主要介紹了二類分類的線性分類模型:感知機(jī):
- 感知機(jī)模型
- 感知機(jī)學(xué)習(xí)策略
- 感知機(jī)學(xué)習(xí)算法
說(shuō)明:個(gè)人感覺(jué)這本書(shū)偏理論化,講究的是一招定天下,好處是內(nèi)功深厚自然無(wú)敵,一通百通,但難處是語(yǔ)言有點(diǎn)晦澀,這章可以考慮結(jié)合我之前的一篇關(guān)于感知器的筆記,或許能加深理解,見(jiàn)這里
感知機(jī)模型
感知機(jī)(perceptron):是一個(gè)二類分類的線性判斷模型,其輸入為實(shí)例的特征向量,輸出為實(shí)例的類別,取+1
和–1
值,屬于判別模型
注:+1 -1 分別代表正負(fù)類,有的可能用 1 0 表示
在介紹感知機(jī)定義之前,下面幾個(gè)概念需要說(shuō)明一下:
- 輸入空間:輸入所有可能取值的集合
- 輸出空間:輸出所有可能取值的集合
- 特征空間:每個(gè)具體的輸入是一個(gè)實(shí)例,由特征向量表示
所以對(duì)于一個(gè)感知機(jī)模型,可以這樣表示:
- 輸入空間(特征空間):
- 輸出空間:
那么感知機(jī)就是由輸入空間到輸出空間的函數(shù):
其中:
-
: 符號(hào)函數(shù)
-
: 權(quán)值(weight)或權(quán)值向量(weight vector)
-
: 偏置(bias)
感知機(jī)的幾何解釋如下:線性方程
如果是二維空間,感知機(jī)就是一個(gè)線性函數(shù),將正負(fù)樣本一分為二,如何是三維空間,那么感知機(jī)就是一個(gè)平面將類別一切為二,上升到n維空間的話,其對(duì)應(yīng)的是特征空間的一個(gè)超平面
:
-
: 超平面的法向量
-
: 超平面的截距
感知機(jī)學(xué)習(xí)策略
數(shù)據(jù)集的線性可分性
什么是數(shù)據(jù)集的線性可分性,很簡(jiǎn)單,對(duì)于一個(gè)數(shù)據(jù)集:
如果存在上面一節(jié)說(shuō)的超平面:
,能夠?qū)?shù)據(jù)集的正實(shí)例點(diǎn)和負(fù)實(shí)例點(diǎn)完全正確地劃分到超平面的兩側(cè),則稱數(shù)據(jù)集T為線性可分?jǐn)?shù)據(jù)集(linearly separable data set),否則,稱數(shù)據(jù)集T線性不可分
感知機(jī)學(xué)習(xí)策略
找出超平面,其實(shí)就是確定感知機(jī)模型參數(shù):
,根據(jù)統(tǒng)計(jì)學(xué)習(xí)方法三要素,此時(shí)我們需要確定一個(gè)學(xué)習(xí)策略,比如前面所說(shuō)的損失函數(shù)(經(jīng)驗(yàn)函數(shù)),并使其最小化(猜也猜得到策略講完,后面就是說(shuō)學(xué)習(xí)算法了哈哈)
上一章以線性代數(shù)為例子,用損失函數(shù)來(lái)度量預(yù)測(cè)錯(cuò)誤的程度,這里的損失函數(shù)可以用誤分類點(diǎn)到超平面的總距離,輸入空間
中任一點(diǎn)
到超平面
的距離:
其中,是
的
范數(shù),假設(shè)超平面S的誤分類點(diǎn)集合為
,那么所有誤分類點(diǎn)到超平面
的總距離為:
最終推導(dǎo)出感知機(jī)學(xué)習(xí)的損失函數(shù):
感知機(jī)學(xué)習(xí)算法
上面一節(jié)已經(jīng)確定了學(xué)習(xí)策略,按照統(tǒng)計(jì)學(xué)習(xí)方法三要素,目前需要一個(gè)算法來(lái)求解,目前最優(yōu)化的方法是隨機(jī)梯度下降法
感知機(jī)學(xué)習(xí)算法的原始形式
現(xiàn)在感知機(jī)學(xué)習(xí)算法就是對(duì)下面最優(yōu)化問(wèn)題的算法:
現(xiàn)在的問(wèn)題就轉(zhuǎn)化成,求出參數(shù)和
,使得上列損失函數(shù)達(dá)到極小化,這里我直接貼出書(shū)中的算法,后面的例子我會(huì)用
Python
代碼實(shí)現(xiàn):
有了解題方法怎么能沒(méi)有題目呢?李杭老師自然是考慮到了,請(qǐng)聽(tīng)題:
借用Linus Torvalds
大佬的一句話:Talk less, show me your code,所以直接看代碼吧:
#!/usr/bin/env python
"""
Created by howie.hu at 2018/9/20.
"""
import numpy as np
class Perceptron:
"""
李航老師統(tǒng)計(jì)學(xué)習(xí)方法第二章感知機(jī)例2.1代碼實(shí)現(xiàn)
"""
def __init__(self, input_nums=2):
# 權(quán)重 已經(jīng)確定只會(huì)有兩個(gè)二進(jìn)制輸入
self.w = np.zeros(input_nums)
# 偏置項(xiàng)
self.b = 0.0
def fit(self, input_vectors, labels, learn_nums=10, rate=1):
"""
訓(xùn)練出合適的 w 和 b
:param input_vectors: 樣本訓(xùn)練數(shù)據(jù)集
:param labels: 標(biāo)記值
:param learn_nums: 學(xué)習(xí)多少次
:param rate: 學(xué)習(xí)率
"""
for i in range(learn_nums):
for index, input_vector in enumerate(input_vectors):
label = labels[index]
delta = label * (sum(self.w * input_vector) + self.b)
if delta <= 0:
self.w += label * input_vector * rate
self.b += rate * label
break
print("最終結(jié)果:此時(shí)感知器權(quán)重為{0},偏置項(xiàng)為{1}".format(self.w, self.b))
return self
def predict(self, input_vector):
if isinstance(input_vector, list):
input_vector = np.array(input_vector)
y = sum(self.w * input_vector) + self.b
return 1 if y > 0 else -1
if __name__ == '__main__':
input_vectors = np.array([[3, 3], [4, 3], [1, 1]])
labels = np.array([1, 1, -1])
p = Perceptron()
model = p.fit(input_vectors, labels)
print(model.predict([3, 3]))
print(model.predict([4, 3]))
print(model.predict([1, 1]))
輸出如下:
最終結(jié)果:此時(shí)感知器權(quán)重為[ 1. 1.],偏置項(xiàng)為-3.0
1
1
-1
算法的收斂性
對(duì)于線性可分?jǐn)?shù)據(jù)集感知機(jī)學(xué)習(xí)算法原始形式收斂,即經(jīng)過(guò)有限次迭代可以得到一個(gè)將訓(xùn)練數(shù)據(jù)集完全正確劃分的分離超平面及感知機(jī)模型,定理2.1
如下:
假設(shè)訓(xùn)練數(shù)據(jù)集是線性可分的,其中
,
,
,則有:
感知機(jī)學(xué)習(xí)算法的對(duì)偶形式
為什么要介紹感知機(jī)學(xué)習(xí)算法的對(duì)偶形式,主要目的就是減少運(yùn)算量,這里一個(gè)知乎回答得挺好:
代碼實(shí)現(xiàn)如下:
#!/usr/bin/env python
"""
Created by howie.hu at 2018/9/21.
"""
import numpy as np
class Perceptron:
"""
李航老師統(tǒng)計(jì)學(xué)習(xí)方法第二章感知機(jī)例2.2對(duì)偶形式代碼實(shí)現(xiàn)
"""
def __init__(self, alpha_length=3):
self.alpha = np.zeros(alpha_length)
# 權(quán)重
self.w = np.zeros(2)
# 偏置項(xiàng)
self.b = 0.0
def fit(self, input_vectors, labels, learn_nums=7):
"""
訓(xùn)練出合適的 w 和 b
:param input_vectors: 樣本訓(xùn)練數(shù)據(jù)集
:param labels: 標(biāo)記值
:param learn_nums: 學(xué)習(xí)多少次
"""
gram = np.matmul(input_vectors, input_vectors.T)
for i in range(learn_nums):
for input_vector_index, input_vector in enumerate(input_vectors):
label = labels[input_vector_index]
delta = 0.0
for alpha_index, a in enumerate(self.alpha):
delta += a * labels[alpha_index] * gram[input_vector_index][alpha_index]
delta = label * delta + self.b
if delta <= 0:
self.alpha[input_vector_index] += 1
self.b += label
break
self.w = sum([j * input_vectors[i] * labels[i] for i, j in enumerate(self.alpha)])
print("最終結(jié)果:此時(shí)感知器權(quán)重為{0},偏置項(xiàng)為{1}".format(self.w, self.b))
return self
def predict(self, input_vector):
if isinstance(input_vector, list):
input_vector = np.array(input_vector)
y = sum(self.w * input_vector) + self.b
return 1 if y > 0 else -1
if __name__ == '__main__':
input_vectors = np.array([[3, 3], [4, 3], [1, 1]])
labels = np.array([1, 1, -1])
p = Perceptron()
model = p.fit(input_vectors, labels)
print(model.predict([3, 3]))
print(model.predict([4, 3]))
print(model.predict([1, 1]))
最終結(jié)果:此時(shí)感知器權(quán)重為[ 1. 1.],偏置項(xiàng)為-3.0
1
1
-1
說(shuō)明
一些概念的詳細(xì)解釋: