1. 程式人生 > 其它 >深度學習筆記008MultilayerPerceptron多層感知機AssertionError

深度學習筆記008MultilayerPerceptron多層感知機AssertionError

今天學的是感知機,程式碼放在下面,總結了幾個問題。

1. MLP多層感知機與SVM支援向量機的區別:

1.MLP需要設定W和b,但是SVM對引數不敏感,所以相對方便一些;
2.SVM在數學上解釋性更強;
3.SVM優化相對容易。

2.為什麼是深度學習,而不是廣度學習?——直覺解釋,這玩意不會有理論依據

只有一個原因,廣度學習不好訓練,一口氣吃成一個胖子,非常容易過擬合。
學習,應該從簡單的開始學,從和輸入層差不多的地方開始學,慢慢深入深入;
而不是把所有東西複雜的簡單的一起扔到你的大腦。

3.三種函式的本質:

4.單層感知機的侷限性

當初因為單層感知機不能解決XOR問題,導致了AI領域的第一次凜冬。

5. 極大似然估計講的不錯的視訊:

https://www.bilibili.com/video/BV1Hb4y1m7rE/?spm_id_from=333.788.recommend_more_video.-1

原始碼如下:


感知機從0實現

 1 import torch
 2 from torch import nn
 3 from d2l import torch as d2l
 4 
 5 # 感知機從0實現
 6 
 7 batch_size=256
 8 train_iter,test_iter=d2l.load_data_fashion_mnist(batch_size) #又是用這個資料集
9 10 num_inputs,num_outputs,num_hiddens=784,10,256 #輸入輸出是固定的,總畫素784,10類,隱藏層大小自己定 11 # 定義引數,W1是第一層的權重矩陣,行列為輸入層、隱藏層,W2自然就是隱藏層和輸出層了;b則為輸出的偏置矩陣 12 W1=nn.Parameter(torch.randn(num_inputs,num_hiddens,requires_grad=True)*0.01) 13 b1=nn.Parameter(torch.zeros(num_hiddens,requires_grad=True)) 14 W2=nn.Parameter(torch.randn(num_hiddens,num_outputs,requires_grad=True)*0.01)
15 b2=nn.Parameter(torch.zeros(num_outputs,requires_grad=True)) 16 17 params=[W1,b1,W2,b2] 18 19 # 啟用函式,哈哈哈哈哈太簡單沐神都輕蔑的笑了 20 def relu(X): 21 a=torch.zeros_like(X) 22 return torch.max(X,a) 23 24 # 定義網路 25 def net(X): 26 X=X.reshape((-1,num_inputs)) # 這裡這個-1代表我不知道是幾行(其實就是1行) 27 H=relu(X@W1+b1) 28 return H@W2+b2 29 30 num_epochs,lr=10,0.1 31 updater=torch.optim.SGD(params,lr=lr) 32 loss=nn.CrossEntropyLoss() 33 d2l.train_ch3(net,train_iter,test_iter,loss,num_epochs,updater) 34 d2l.plt.show()

感知機簡潔實現

 1 # 感知機簡潔實現
 2 net = nn.Sequential(nn.Flatten(),nn.Linear(784,256),nn.ReLU(),nn.Linear(256,10)) #扁平化,第一層,啟用函式,第二層
 3 
 4 # 權重初始化
 5 def init_weights(m):
 6     if type(m)==nn.Linear:
 7         nn.init.normal_(m.weight,std=0.01)
 8 net.apply(init_weights)
 9 
10 batch_size,lr,num_epochs=256,0.1,10
11 loss=nn.CrossEntropyLoss()
12 trainer=torch.optim.SGD(net.parameters(),lr)
13 
14 train_iter,test_iter=d2l.load_data_fashion_mnist(batch_size)
15 
16 d2l.train_ch3(net,train_iter,test_iter,loss,num_epochs,trainer)
17 d2l.plt.show()

從0實現(左側)與簡潔實現(右側)的結果:

可以發現幾乎沒有什麼區別,但是做簡潔實現的時候我發現了一個問題,就是W不乘以0.01,會讓訓練的loss減小地非常緩慢,以至於在10次迭代中,loss不能降低到0.5,而Torch內部的訓練函式輸出時有一個斷言,assert loss<0.5,這時候輸出影象就會產生斷言錯誤,如下:

解決這個問題的方式有兩個,一個是用try catch將斷言異常丟擲:https://www.cnblogs.com/fanjc/p/10072556.html

另一個就是把loss訓練的再小一些,因為這個斷言本身就是為了我們結果的合理性寫的,所以可以改大epoch增加迭代次數,比如改成30次,可以將loss降低到0.5左右如下:

這才是正解。

但是我個人其實沒有理解透徹為什麼在W上縮小100倍,就能夠加快訓練速度,請看到這裡的大佬在評論區指教一下謝謝哦~