1. 單層感知機
1.1 感知機
① 線性回歸輸出的是一個實數,感知機輸出的是一個離散的類。
1.2 訓練感知機
① 如果分類正確的話y<w,x>為正數,負號后變為一個負數,max后輸出為0,則梯度不進行更新。
② 如果分類錯了,y<w,x>為負數,下圖中的if判斷就成立了,就有梯度進行更新。
1.3 收斂半徑
1.4 XOR問題
1.5 總結
2. 多層感知機
2.1 學習XOR
① 先用藍色的線分,再用黃色的線分。
② 再對藍色的線和黃色的線分出來的結果做乘法。
2.2 單隱藏層
① 不用激活函數的話,所以全連接層連接在一起依舊可以用一個最簡單的線性函數來表示。
2.3 Sigmoid 函數
2.4 Tanh函數
2.5 ReLU
① ReLU的好處在于不需要執行指數運算。
② 在CPU上一次指數運算相當于上百次乘法運算。
2.6 多類分類
2.7 總結
1. 多層感知機(使用自定義)
import torch
from torch import nn
from d2l import torch as d2lbatch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)# 實現一個具有單隱藏層的多層感知機,它包含256個隱藏單元
num_inputs, num_outputs, num_hiddens = 784, 10, 256 # 輸入、輸出是數據決定的,256是調參自己決定的
W1 = nn.Parameter(torch.randn(num_inputs, num_hiddens, requires_grad=True))
b1 = nn.Parameter(torch.zeros(num_hiddens, requires_grad=True))
W2 = nn.Parameter(torch.randn(num_hiddens, num_outputs, requires_grad=True))
b2 = nn.Parameter(torch.zeros(num_outputs, requires_grad=True))
params = [W1,b1,W2,b2]# 實現 ReLu 激活函數
def relu(X):a = torch.zeros_like(X) # 數據類型、形狀都一樣,但是值全為 0return torch.max(X,a)# 實現模型
def net(X):#print("X.shape:",X.shape)X = X.reshape((-1, num_inputs)) # -1為自適應的批量大小#print("X.shape:",X.shape)H = relu(X @ W1 + b1)#print("H.shape:",H.shape)#print("W2.shape:",W2.shape)return (H @ W2 + b2)# 損失
loss = nn.CrossEntropyLoss() # 交叉熵損失# 多層感知機的訓練過程與softmax回歸的訓練過程完全一樣
num_epochs ,lr = 30, 0.1
updater = torch.optim.SGD(params, lr=lr)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, updater)
2. 多層感知機(使用框架)
① 調用高級API更簡潔地實現多層感知機。
import torch
from torch import nn
from d2l import torch as d2l# 隱藏層包含256個隱藏單元,并使用了ReLU激活函數
net = nn.Sequential(nn.Flatten(),nn.Linear(784,256),nn.ReLU(),nn.Linear(256,10))def init_weights(m):if type(m) == nn.Linear:nn.init.normal_(m.weight,std=0,)net.apply(init_weights)# 訓練過程
batch_size, lr, num_epochs = 256, 0.1, 10
loss = nn.CrossEntropyLoss()
trainer = torch.optim.SGD(net.parameters(), lr=lr)train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer)
# 單層感知機函數
%matplotlib inline
import torch
from torch import nn
from d2l import torch as d2l# 數據集
batch_size = 256
train_iter,test_iter = d2l.load_data_fashion_mnist(batch_size)# 初始化模型參數
num_inputs = 784
num_outputs = 10
num_hiddens = 256W1 = nn.Parameter(torch.randn(num_inputs, num_hiddens, requires_grad=True) * 0.01)
b1 = nn.Parameter(torch.zeros(num_hiddens, requires_grad=True))params = [W1, b1]def relu(X):a = torch.zeros_like(X)return torch.max(X, a)# 定義網絡
def net(X):X = X.reshape((-1, num_inputs))H = relu(X @ W1 + b1)return H# loss = nn.CrossEntropyLoss(reduction='none')
loss = nn.CrossEntropyLoss()num_epochs, lr = 10, 0.1
# updater = torch.optim.SGD(params, lr=lr)
updater = torch.optim.Adam(params, lr=lr)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, updater)
# 3層感知機函數
%matplotlib inline
import torch
from torch import nn
from d2l import torch as d2l# 數據集
batch_size = 256
train_iter,test_iter = d2l.load_data_fashion_mnist(batch_size)# 初始化模型參數
num_inputs = 784
num_outputs = 10
num_hiddens1 = 256
num_hiddens2 = 128W1 = nn.Parameter(torch.randn(num_inputs, num_hiddens1, requires_grad=True) * 0.01)
b1 = nn.Parameter(torch.zeros(num_hiddens, requires_grad=True))
W2 = nn.Parameter(torch.randn(num_hiddens1, num_hiddens2, requires_grad=True) * 0.01)
b2 = nn.Parameter(torch.zeros(num_hiddens2, requires_grad=True))
W3 = nn.Parameter(torch.randn(num_hiddens2, num_outputs, requires_grad=True) * 0.01)
b3 = nn.Parameter(torch.zeros(num_outputs, requires_grad=True))params = [W1, b1,W2,b2,W3,b3]def relu(X):a = torch.zeros_like(X)return torch.max(X, a)# 定義網絡
def net(X):X = X.reshape((-1, num_inputs))H1 = relu(X @ W1 + b1)H2 = relu(H1 @ W2 + b2)return (H2 @ W3 + b3)# loss = nn.CrossEntropyLoss(reduction='none')
loss = nn.CrossEntropyLoss()
# 三層 學習率修改為0.01 效果會好一些
num_epochs, lr = 10, 0.01
# updater = torch.optim.SGD(params, lr=lr)
updater = torch.optim.Adam(params, lr=lr)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, updater)
d2l.predict_ch3(net, test_iter)
感知機(Perceptron)簡介
感知機(Perceptron)是最簡單的神經網絡模型之一,最早由 Frank Rosenblatt 在 1958 年提出。它是一個二分類模型,能夠根據輸入的特征,判斷一個樣本屬于哪一類。盡管感知機本身非常簡單,但它為后來的深度學習模型奠定了基礎,尤其是多層感知機(MLP)和其他神經網絡。
感知機是 線性分類器,意味著它只能對線性可分的任務進行有效的分類。對于無法用直線(或超平面)劃分的任務,單層感知機是無法處理的,但通過將其擴展到多層神經網絡,問題得到了很好的解決。
感知機的結構
感知機由以下幾個部分組成:
- 輸入層:感知機接受一個輸入向量 x=[x1,x2,...,xn]\mathbf{x} = [x_1, x_2, ..., x_n]x=[x1?,x2?,...,xn?],表示樣本的特征。
- 權重(Weights):每個輸入特征 xix_ixi? 都有一個對應的權重 wiw_iwi?。
- 偏置項(Bias):為了使模型更具有表達能力,感知機還有一個偏置項 bbb。
- 激活函數:感知機通常使用一個階躍函數(step function)作為激活函數,根據加權和與閾值的比較來決定輸出。
感知機的數學表示
感知機的輸出 yyy 是通過以下步驟計算的:
-
加權和:
z=∑i=1nwixi+b z = \sum_{i=1}^{n} w_i x_i + b z=i=1∑n?wi?xi?+b
其中,xix_ixi? 是輸入特征,wiw_iwi? 是與 xix_ixi? 對應的權重,bbb 是偏置項。
-
激活函數(階躍函數):
y={1if?z≥00if?z<0 y = \begin{cases} 1 & \text{if } z \geq 0 \\ 0 & \text{if } z < 0 \end{cases} y={10?if?z≥0if?z<0?
這里,階躍函數(step function)會將加權和 zzz 映射為一個二值輸出 yyy。
感知機的推理過程
推理過程是指給定輸入特征,感知機如何輸出分類結果。其推理過程可以通過以下幾個步驟來描述:
-
輸入:將樣本的特征 x=[x1,x2,...,xn]\mathbf{x} = [x_1, x_2, ..., x_n]x=[x1?,x2?,...,xn?] 輸入到感知機中。
-
加權和計算:感知機首先計算輸入特征和權重的加權和(即 z=∑i=1nwixi+bz = \sum_{i=1}^{n} w_i x_i + bz=∑i=1n?wi?xi?+b)。
-
激活函數應用:然后,感知機將加權和 zzz 傳遞給階躍激活函數,決定輸出是 1 還是 0。
- 如果 z≥0z \geq 0z≥0,則輸出 1,表示樣本屬于一類。
- 如果 z<0z < 0z<0,則輸出 0,表示樣本屬于另一類。
-
輸出:感知機的最終輸出 yyy 是二值化的分類結果(0 或 1)。
感知機的推理示例
假設我們有以下輸入特征 x=[x1,x2]\mathbf{x} = [x_1, x_2]x=[x1?,x2?],并且給定權重 w=[w1,w2]\mathbf{w} = [w_1, w_2]w=[w1?,w2?] 和偏置 bbb,感知機的輸出通過以下步驟計算:
- 輸入向量:x=[x1,x2]=[1.0,2.0]\mathbf{x} = [x_1, x_2] = [1.0, 2.0]x=[x1?,x2?]=[1.0,2.0]
- 權重:w=[w1,w2]=[0.5,0.5]\mathbf{w} = [w_1, w_2] = [0.5, 0.5]w=[w1?,w2?]=[0.5,0.5]
- 偏置項:b=?1.0b = -1.0b=?1.0
首先,計算加權和 zzz:
z=w1?x1+w2?x2+b=0.5?1.0+0.5?2.0?1.0=0.5+1.0?1.0=0.5 z = w_1 \cdot x_1 + w_2 \cdot x_2 + b = 0.5 \cdot 1.0 + 0.5 \cdot 2.0 - 1.0 = 0.5 + 1.0 - 1.0 = 0.5 z=w1??x1?+w2??x2?+b=0.5?1.0+0.5?2.0?1.0=0.5+1.0?1.0=0.5
然后,使用階躍激活函數對 zzz 進行處理:
y={1if?z≥00if?z<0 y = \begin{cases} 1 & \text{if } z \geq 0 \\ 0 & \text{if } z < 0 \end{cases} y={10?if?z≥0if?z<0?
由于 z=0.5≥0z = 0.5 \geq 0z=0.5≥0,所以 y=1y = 1y=1。
感知機的訓練過程
感知機的訓練過程采用 感知機算法,該算法通過調整權重和偏置,使感知機的輸出盡量接近實際目標。
-
初始化權重和偏置:權重和偏置通常被初始化為小的隨機值。
-
預測輸出:對于每個訓練樣本,計算感知機的預測輸出。
-
計算誤差:根據實際標簽和預測輸出之間的差異計算誤差:
誤差=ytrue?ypredicted \text{誤差} = y_{\text{true}} - y_{\text{predicted}} 誤差=ytrue??ypredicted?
-
權重更新:使用感知機學習規則來調整權重和偏置。如果預測錯誤,權重會根據誤差進行調整。更新公式如下:
wi=wi+η?誤差?xi w_i = w_i + \eta \cdot \text{誤差} \cdot x_i wi?=wi?+η?誤差?xi?
b=b+η?誤差 b = b + \eta \cdot \text{誤差} b=b+η?誤差
其中 η\etaη 是學習率,控制更新的步長。
-
重復:通過迭代多個訓練樣本,直到誤差為零或達到最大迭代次數。
感知機的局限性
感知機有以下幾個限制:
-
線性可分性:感知機只能解決線性可分的問題。如果數據集是非線性可分的,感知機就無法準確分類。例如,無法分類像 XOR 問題那樣的非線性數據。
-
單層感知機:單層感知機是一個線性分類器,如果要處理更復雜的問題,我們需要將感知機擴展為多層感知機(MLP),即深度神經網絡。
總結
- 感知機 是一種簡單的二分類模型,基于加權和和階躍激活函數進行推理。
- 推理過程:通過計算輸入特征的加權和,然后使用階躍函數決定輸出類別(0 或 1)。
- 訓練過程:通過感知機算法迭代調整權重和偏置,使得模型能夠正確分類訓練數據。
- 局限性:感知機只能處理線性可分問題,無法解決復雜的非線性問題。
感知機的工作原理為后續的深度學習模型,如多層感知機(MLP)和卷積神經網絡(CNN),提供了基本的啟示。