2、感知機(jī)
感知機(jī)是利用超平面對(duì)樣本點(diǎn)進(jìn)行劃分告丢,位于超平面一側(cè)的點(diǎn)設(shè)為正類(lèi)枪蘑,另一側(cè)的點(diǎn)設(shè)為負(fù)類(lèi)。
三要素
模型
輸入空間:
輸出空間:
決策函數(shù):
策略
確定學(xué)習(xí)策略就是定義(經(jīng)驗(yàn))損失函數(shù)并將損失函數(shù)最小化岖免。
注意這里提到了經(jīng)驗(yàn)岳颇,所以學(xué)習(xí)是base在訓(xùn)練數(shù)據(jù)集上的操作
損失函數(shù)選擇
損失函數(shù)的一個(gè)自然選擇是誤分類(lèi)點(diǎn)的總數(shù),但是颅湘,這樣的損失函數(shù)不是參數(shù)w,b的連續(xù)可導(dǎo)函數(shù)话侧,不易優(yōu)化
損失函數(shù)的另一個(gè)選擇是誤分類(lèi)點(diǎn)到超平面S的總距離,這是感知機(jī)所采用的
感知機(jī)學(xué)習(xí)的經(jīng)驗(yàn)風(fēng)險(xiǎn)函數(shù)(損失函數(shù))
其中M是誤分類(lèi)點(diǎn)的集合
給定訓(xùn)練數(shù)據(jù)集T闯参,損失函數(shù)是
和
的連續(xù)可導(dǎo)函數(shù)
算法
原始形式
輸入:
輸出:
- 選取初值
![]()
- 訓(xùn)練集中選取數(shù)據(jù)
![]()
- 如果
![]()
- 轉(zhuǎn)至(2)瞻鹏,直至訓(xùn)練集中沒(méi)有誤分類(lèi)點(diǎn)
注意這個(gè)原始形式中的迭代公式,可以對(duì)x補(bǔ)1鹿寨,將w和b合并在一起新博,合在一起的這個(gè)叫做擴(kuò)充權(quán)重向量,書(shū)上有提到脚草。
對(duì)偶形式
對(duì)偶形式的基本思想是將w和b表示為實(shí)例x_i和標(biāo)記y_i的線(xiàn)性組合的形式赫悄,通過(guò)求解其系數(shù)而求得w和b。
輸入:T={(x_1,y_1),(x_2,y_2),\dots,(x_N,y_N)}\ x_i\in \cal{X}=\bf{R}^n , y_i\in \cal{Y} ={-1,+1}, i=1,2,\dots, N; 0< \eta \leqslant 1
輸出:
- \alpha \leftarrow 0,b\leftarrow 0
- 訓(xùn)練集中選取數(shù)據(jù)(x_i,y_i)
- 如果y_i\left(\sum_{j=1}^N\alpha_jy_jx_j\cdot x+b\right) \leqslant 0
![]()
- 轉(zhuǎn)至(2)馏慨,直至訓(xùn)練集中沒(méi)有誤分類(lèi)點(diǎn)
習(xí)題2.1
Minsky 與 Papert 指出:感知機(jī)因?yàn)槭蔷€(xiàn)性模型埂淮,所以不能表示復(fù)雜的函數(shù),如異或 (XOR)写隶。驗(yàn)證感知機(jī)為什么不能表示異或同诫。
第1步:異或函數(shù)(XOR)的輸入和輸出
??對(duì)于異或函數(shù)(XOR),全部的輸入與對(duì)應(yīng)的輸出如下(若兩個(gè)數(shù)的值相同樟澜,則為-1,不同則為1):
x_1 | x_1 | x_1⊕x_2 |
---|---|---|
0 | 0 | -1 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | -1 |
第2步:使用圖例法證明異或問(wèn)題是線(xiàn)性不可分的
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
# 使用Dataframe表示異或的輸入與輸出數(shù)據(jù)
x1 = [0, 0, 1, 1]
x2 = [0, 1, 0, 1]
y = [-1, 1, 1, -1]
x1 = np.array(x1)
x2 = np.array(x2)
y = np.array(y)
data = np.c_[x1, x2, y]
data = pd.DataFrame(data, index=None, columns=['x1', 'x2', 'y'])
# 獲取正類(lèi)別(y=1)的數(shù)據(jù)
positive = data.loc[data['y'] == 1]
# 獲取負(fù)類(lèi)別(y=-1)的數(shù)據(jù)
negative = data.loc[data['y'] == -1]
# 繪制數(shù)據(jù)圖
# 繪制坐標(biāo)軸
plt.xlim(-0.5, 1.5)
plt.ylim(-0.5, 1.5)
plt.xticks([-0.5, 0, 1, 1.5])
plt.yticks([-0.5, 0, 1, 1.5])
# 添加坐標(biāo)軸文字
plt.xlabel("x1")
plt.ylabel("x2")
# 繪制正叮盘、負(fù)樣本點(diǎn)
plt.plot(positive['x1'], positive['x2'], "ro")
plt.plot(negative['x1'], negative['x2'], "bx")
# 添加圖示
plt.legend(['Positive', 'Negative'])
plt.show()
```python
![習(xí)題2.1.png](https://upload-images.jianshu.io/upload_images/27746358-935ed50517182038.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
## 習(xí)題2.2
模仿例題 2.1秩贰,構(gòu)建從訓(xùn)練數(shù)據(jù)求解感知機(jī)模型的例子.
**注:代碼來(lái)自datawhale**
```python
import numpy as np
from matplotlib import pyplot as plt
%matplotlib tk
class Perceptron:
def __init__(self, X, Y, lr=0.001, plot=True):
"""
初始化感知機(jī)
:param X: 特征向量
:param Y: 類(lèi)別
:param lr: 學(xué)習(xí)率
:param plot: 是否繪制圖形
"""
self.X = X
self.Y = Y
self.lr = lr
self.plot = plot
if plot:
self.__model_plot = self._ModelPlot(self.X, self.Y)
self.__model_plot.open_in()
def fit(self):
# (1)初始化weight, b
weight = np.zeros(self.X.shape[1])
b = 0
# 訓(xùn)練次數(shù)
train_counts = 0
# 分類(lèi)錯(cuò)誤標(biāo)識(shí)
mistake_flag = True
while mistake_flag:
# 開(kāi)始前,將mistake_flag設(shè)置為False柔吼,用于判斷本次循環(huán)是否有分類(lèi)錯(cuò)誤
mistake_flag = False
# (2)從訓(xùn)練集中選取x,y
for index in range(self.X.shape[0]):
if self.plot:
self.__model_plot.plot(weight, b, train_counts)
# 損失函數(shù)
loss = self.Y[index] * (weight @ self.X[index] + b)
# (3)如果損失函數(shù)小于0毒费,則該點(diǎn)是誤分類(lèi)點(diǎn)
if loss <= 0:
# 更新weight, b
weight += self.lr * self.Y[index] * self.X[index]
b += self.lr * self.Y[index]
# 訓(xùn)練次數(shù)加1
train_counts += 1
print("Epoch {}, weight = {}, b = {}, formula: {}".format(
train_counts, weight, b, self.__model_plot.formula(weight, b)))
# 本次循環(huán)有誤分類(lèi)點(diǎn)(即分類(lèi)錯(cuò)誤),置為T(mén)rue
mistake_flag = True
break
if self.plot:
self.__model_plot.close()
# (4)直至訓(xùn)練集中沒(méi)有誤分類(lèi)點(diǎn)
return weight, b
class _ModelPlot:
def __init__(self, X, Y):
self.X = X
self.Y = Y
@staticmethod
def open_in():
# 打開(kāi)交互模式愈魏,用于展示動(dòng)態(tài)交互圖
plt.ion()
@staticmethod
def close():
# 關(guān)閉交互模式觅玻,并顯示最終的圖形
plt.ioff()
plt.show()
def plot(self, weight, b, epoch):
plt.cla()
# x軸表示x1
plt.xlim(0, np.max(self.X.T[0]) + 1)
# y軸表示x2
plt.ylim(0, np.max(self.X.T[1]) + 1)
# 畫(huà)出散點(diǎn)圖想际,并添加圖示
scatter = plt.scatter(self.X.T[0], self.X.T[1], c=self.Y)
plt.legend(*scatter.legend_elements())
if True in list(weight == 0):
plt.plot(0, 0)
else:
x1 = -b / weight[0]
x2 = -b / weight[1]
# 畫(huà)出分離超平面
plt.plot([x1, 0], [0, x2])
# 繪制公式
text = self.formula(weight, b)
plt.text(0.3, x2 - 0.1, text)
plt.title('Epoch %d' % epoch)
plt.pause(0.01)
@staticmethod
def formula(weight, b):
text = 'x1 ' if weight[0] == 1 else '%d*x1 ' % weight[0]
text += '+ x2 ' if weight[1] == 1 else (
'+ %d*x2 ' % weight[1] if weight[1] > 0 else '- %d*x2 ' % -weight[1])
text += '= 0' if b == 0 else ('+ %d = 0' %
b if b > 0 else '- %d = 0' % -b)
return text
X = np.array([[3, 3], [4, 3], [1, 1]])
Y = np.array([1, 1, -1])
model = Perceptron(X, Y, lr=1)
weight, b = model.fit()