日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

NNDL 作业4:第四章课后题

發(fā)布時間:2024/1/8 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 NNDL 作业4:第四章课后题 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目章

前言

一、習(xí)題4-2? 試設(shè)計一個前饋神經(jīng)網(wǎng)絡(luò)來解決 XOR 問題,要求該前饋神經(jīng)網(wǎng)絡(luò)具有兩個隱藏神經(jīng)元和一個輸出神經(jīng)元,并使用 ReLU 作為激活函數(shù).

4.2.1? 網(wǎng)絡(luò)的構(gòu)建

?4.2.2? ?參數(shù)的設(shè)置

?4.2.3? 訓(xùn)練模型

4.2.4? ?打印訓(xùn)練結(jié)果

4.2.5? 可視化

4.2.6 與感知機(jī)的比較?

二、習(xí)題4-3?試舉例說明“死亡ReLU問題”,并提出解決方法.

好了,廢話說完了,我們來看一下,代碼實(shí)例這個是用ReLU來實(shí)現(xiàn)的。

使用Leaky ReLU進(jìn)行模型訓(xùn)練

三、習(xí)題4-7 為什么在神經(jīng)網(wǎng)絡(luò)模型的結(jié)構(gòu)化風(fēng)險函數(shù)中不對偏置b進(jìn)行正則化??

四、習(xí)題 4-8 為什么在用反向傳播算法進(jìn)行參數(shù)學(xué)習(xí)時要采用隨機(jī)參數(shù)初始化的方式而不是直接令 w= 0, 𝒃 = 0?

五、習(xí)題4-9?梯度消失問題是否可以通過增加學(xué)習(xí)率來緩解?

總結(jié)


前言

? ? ? ?這次我還是寫的很細(xì),有好多東西查了好多資料,有的我給出鏈接,真的學(xué)到很多,而且這次是一口氣寫完的,一口氣寫的真的感覺很連貫,很通暢。

? ? ? ?這次作業(yè)是寫了一下午到這會了,晚飯都沒吃,飯要涼了,但是真的很爽,寫完去吃了(哈哈哈),并且疫情終于要過去了,現(xiàn)在中風(fēng)險了,有大塊的時間來寫這個了,河大加油。??

? ? ? ?最后,我在下邊,提出了我發(fā)現(xiàn)的問題,希望老師和各位大佬幫忙解答一下,去吃飯了(哈哈哈)


?

一、習(xí)題4-2? 試設(shè)計一個前饋神經(jīng)網(wǎng)絡(luò)來解決 XOR 問題,要求該前饋神經(jīng)網(wǎng)絡(luò)具有兩個隱藏神經(jīng)元和一個輸出神經(jīng)元,并使用 ReLU 作為激活函數(shù).

? ? ? ?首先,先說一下,大家都知道咱們用神經(jīng)網(wǎng)絡(luò)來解決異或問題的原因是,感知機(jī)并不能很好的解決。至于這個的證明,我會在下邊放一下(因?yàn)橹翱荚嚨臅r候考過,當(dāng)時想了很長時間,才證明了出來,所以考完之后就寫在書上了)。

? ? ? ?然后,由于神經(jīng)網(wǎng)絡(luò)解決感知機(jī)的問題,訓(xùn)練過程較為簡單,所以我感覺大家其實(shí)都寫的差不多,都是一種寫法,因?yàn)?#xff0c;根本沒有必要去,寫一個runner類進(jìn)行調(diào)用,所以我特意做了可視化,這樣也方便比較,并且來看直觀(可視化真的弄了好長時間,不過這次學(xué)習(xí)了常規(guī)的描繪邊沿的方法,感覺還是很有用的,哈哈哈)。

? ? ? ?好了,下邊說有用的,下邊是一些證明,大家可以看看(寫的確實(shí)有點(diǎn)亂,嗚嗚)

? ? ?然后就要,說一說代碼的實(shí)現(xiàn)了,首先,搭建的神經(jīng)網(wǎng)絡(luò)的大致框圖為:

?? ? 神經(jīng)網(wǎng)絡(luò)就是大致按照,下邊的架子搭的,也就是一個2個神經(jīng)元的隱層,最后一個輸出。

? ? ? ?然后說一下,輸入輸出的數(shù)據(jù),這個從哪來呢,怎么體現(xiàn)異或問題呢,這個從我上邊鉛筆寫的就可以看出,也就是下圖中所表現(xiàn)的。)

? ? ? 由上圖可以看出,我們的數(shù)據(jù)是(0,0)、(0,1)、(1,0)、(1,1),對應(yīng)的標(biāo)簽是0,1,1,0。

? ? ? 然后,解釋一下,咱們網(wǎng)絡(luò)層的構(gòu)建的公式(其實(shí)就是之前博客上解釋過的過程)

隱含層的表達(dá)式見公式1和公式2所示。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(1)

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (2)

輸出層表達(dá)式如公式3所示。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(3)
?

? ? ? ?下邊就是就是代碼了(前邊我可能有點(diǎn)廢話多了,哈哈哈)

4.2.1? 網(wǎng)絡(luò)的構(gòu)建

# coding=gbk import torch.nn as nn import torch import torch.optim as optim import matplotlib.pyplot as plt import math import numpy as npfrom torch.autograd import Variable import torch.nn.functional as F from torch.nn.init import constant_, normal_, uniform_

? ? ? ? 由于我做了一下可視化,所以相較于別人,我用到的庫可能相對較多,老師和各位大佬,如果有啥更好的可是化的方法,請多交一交我。

? ? ? ? 這個還是我之前說過的問題,注意解碼方式,要不然注釋有可能會報錯,這樣弄起來會很麻煩。

# 異或門模塊由兩個全連接層構(gòu)成 class Model_MLP_L2_V2(nn.Module):def __init__(self, input_size, hidden_size, output_size):super(Model_MLP_L2_V2, self).__init__()# 使用'paddle.nn.Linear'定義線性層。# 其中第一個參數(shù)(in_features)為線性層輸入維度;第二個參數(shù)(out_features)為線性層輸出維度# weight_attr為權(quán)重參數(shù)屬性,這里使用'paddle.nn.initializer.Normal'進(jìn)行隨機(jī)高斯分布初始化# bias_attr為偏置參數(shù)屬性,這里使用'paddle.nn.initializer.Constant'進(jìn)行常量初始化self.fc1 = nn.Linear(input_size, hidden_size)w1 = torch.empty(hidden_size,input_size)b1= torch.empty(hidden_size)self.fc1.weight=torch.nn.Parameter(normal_(w1,mean=0.0, std=1.0))self.fc1.bias=torch.nn.Parameter(constant_(b1,val=0.0))self.fc2 = nn.Linear(hidden_size, output_size)w2 = torch.empty(output_size,hidden_size)b2 = torch.empty(output_size)self.fc2.weight=torch.nn.Parameter(normal_(w2,mean=0.0, std=1.0))self.fc2.bias=torch.nn.Parameter(constant_(b2,val=0.0))# 使用'paddle.nn.functional.sigmoid'定義 Logistic 激活函數(shù)self.act_fn = nn.ReLU()# 前向計算def forward(self, inputs):z1 = self.fc1(inputs)a1 = self.act_fn(z1)z2 = self.fc2(a1)a2 = self.act_fn(z2)return a2

? ? ? 這個網(wǎng)絡(luò)其實(shí)就是,咱們上一邊博客的網(wǎng)絡(luò),我連網(wǎng)絡(luò)的名都沒有改,就是修改了一下激活函數(shù),咱們這個記得激活函數(shù),要用nn.ReLU(),要不然如果用F.relu()的話是會報錯的。

? ? ? 這個問題之前說過好幾次了,是函數(shù)用法的問題,大家有興趣的話,去看一看我之前寫的博客,幫我批評指正一下。

?4.2.2? ?參數(shù)的設(shè)置

# 輸入和輸出數(shù)據(jù) input_x = torch.Tensor([[0, 0], [0, 1], [1, 0], [1, 1]]) input_x1 = input_x.float() real_y = torch.Tensor([[0], [1], [1], [0]]) real_y1 = real_y.float() # 設(shè)置損失函數(shù)和參數(shù)優(yōu)化函數(shù) net = Model_MLP_L2_V2(2,2,1) loss_function = nn.MSELoss(reduction='mean') # 用交叉熵?fù)p失函數(shù)會出現(xiàn)維度錯誤 optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) # 用Adam優(yōu)化參數(shù)選不好會出現(xiàn)計算值超出0-1的范圍 epochs=2000 #訓(xùn)練次數(shù)

? ? ? ?這個就是把數(shù)據(jù)設(shè)置一下,并且設(shè)置一下,相關(guān)的超參數(shù),這個的設(shè)置與調(diào)試,在上邊博客中有大量的討論。

?4.2.3? 訓(xùn)練模型

# 進(jìn)行訓(xùn)練 for epoch in range(epochs):out_y = net(input_x1)loss = loss_function(out_y, real_y1) # 計算損失函數(shù)# print('啦啦啦')optimizer.zero_grad() # 對梯度清零,避免造成累加loss.backward() # 反向傳播optimizer.step() # 參數(shù)更新

? ? ? ? 這個就是正常的訓(xùn)練步驟,為了,方便就沒有寫runner類了。其實(shí),規(guī)范的話,最好是寫的。

4.2.4? ?打印訓(xùn)練結(jié)果

# 打印計算的權(quán)值和偏置 print('w1 = ', net.fc1.weight.detach().numpy()) print('b1 = ', net.fc1.bias.detach().numpy()) print('w2 = ', net.fc2.weight.detach().numpy()) print('b2 = ', net.fc2.bias.detach().numpy())input_test = input_x1 out_test = net(input_test) print('input_x', input_test.detach().numpy()) print('out_y', out_test.detach().numpy())

這個就是正常的調(diào)用print函數(shù)打印一下結(jié)果。

w1 = ?[[ 1.314425 ?-2.527302 ]
?[-1.0961039 ?1.4463567]]
b1 = ?[ 0.03252467 -0.15060449]
w2 = ?[[0.87763757 0.9123106 ]]
b2 = ?[-0.182134]
input_x [[0. 0.]
?[0. 1.]
?[1. 0.]
?[1. 1.]]
out_y [[0.0000000e+00]
?[9.9999440e-01]
?[9.9999964e-01]
?[7.2270632e-06]]?

可以看出,結(jié)果非常好。

4.2.5? 可視化

# 這里我稍微調(diào)整了下plt.contour中的參數(shù),使得結(jié)果更好看一點(diǎn) def plot_decision_boundary(model, x, y):x_min, x_max = x[:, 0].min() - 0.5, x[:, 0].max() + 0.5y_min, y_max = x[:, 1].min() - 0.5, x[:, 1].max() + 0.5h = 0.01# 繪制網(wǎng)格xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))# 生成與網(wǎng)格上所有點(diǎn)對應(yīng)的分類結(jié)果z = model(np.c_[xx.ravel(), yy.ravel()])z = z.reshape(xx.shape)# 繪制contourplt.contour(xx, yy, z, levels=[0.5], colors=['blue'])plt.scatter(x[:, 0], x[:, 1], c=y)plt.show()def plot_network(x):x = Variable(torch.from_numpy(x).float())x1 = torch.mm(x, net.fc1.weight.T) + net.fc1.bias.Tx1 = F.relu(x1)x2 = torch.mm(x1, net.fc2.weight.T) + net.fc2.bias.Tout = F.relu(x2)out = (out > 0.5) * 1return out.data.numpy()plot_decision_boundary(lambda x: plot_network(x), input_x1.numpy(), real_y1.numpy())

運(yùn)行結(jié)果為:

這個是函數(shù)邊沿的描繪,這個就可以看出,神經(jīng)網(wǎng)絡(luò)的優(yōu)越性了。

4.2.6 與感知機(jī)的比較?

# coding=gbk import numpy as np import matplotlib.pyplot as plt# 載入數(shù)據(jù) x_data = np.array([[1, 0, 0],[1, 0, 1],[1, 1, 0],[1, 1, 1]]) y_data = np.array([[-1],[1],[1],[-1]]) # 設(shè)置權(quán)值,3行1列,取值范圍為-1~1 w = (np.random.random([3, 1]) - 0.5) * 2 print(w) # 學(xué)習(xí)率 lr = 0.11 # 神經(jīng)網(wǎng)絡(luò)輸出 out_rs = 0def update():global x_data, y_data, w, lr # 使用全局變量,當(dāng)然也可以使用一個return返回out_rs = np.sign(np.dot(x_data, w))w_c = lr * (x_data.T.dot(y_data - out_rs)) / int(x_data.shape[0])w = w + w_cfor i in range(100):update() # 權(quán)值更新out_rs = np.sign(np.dot(x_data, w)) # 計算當(dāng)前輸出print("epoch:", i)print("w:", w)if (out_rs == y_data).all(): # 如果當(dāng)前輸出與實(shí)際輸出相當(dāng),模型收斂,循環(huán)結(jié)束(.all是全部相等的意思)print("#####################")print("finished")print("epoch:", i)print("#####################")break # 正樣本 x1 = [0, 1] y1 = [1, 0] # 負(fù)樣本 x2 = [0, 1] y2 = [0, 1]# 計算分界線的斜率以及截距 k = -w[1] / w[2] b = -w[0] / w[2] print("k = ", k) print("b = ", b)# 繪圖,scatter繪點(diǎn)、plot繪制直線 xdata = (0, 5) plt.figure() plt.plot(xdata, xdata * k + b, 'r') plt.scatter(x1, y1, c='b') plt.scatter(x2, y2, c='y') plt.show()

運(yùn)行結(jié)果為:

? ? ? ? 從結(jié)果中就可以看,神經(jīng)網(wǎng)絡(luò)的優(yōu)越性??梢暬蟾鼮橹苯?#xff0c;從圖像中就可以看出神經(jīng)網(wǎng)絡(luò)的優(yōu)越性。

二、習(xí)題4-3?試舉例說明“死亡ReLU問題”,并提出解決方法.

? ? 這里先要說一下,什么叫“死亡ReLU問題”

? ? 死亡ReLU問題:?ReLU激活函數(shù)可以一定程度上改善梯度消失問題,但是ReLU函數(shù)在某些情況下容易出現(xiàn)死亡 ReLU問題,使得網(wǎng)絡(luò)難以訓(xùn)練。這是由于當(dāng)x<0x<0時,ReLU函數(shù)的輸出恒為0。在訓(xùn)練過程中,如果參數(shù)在一次不恰當(dāng)?shù)母潞?#xff0c;某個ReLU神經(jīng)元在所有訓(xùn)練數(shù)據(jù)上都不能被激活(即輸出為0),那么這個神經(jīng)元自身參數(shù)的梯度永遠(yuǎn)都會是0,在以后的訓(xùn)練過程中永遠(yuǎn)都不能被激活。

? ? 由于上邊說到了,就不得不提一下,梯度消失的問題了,這個下邊也會提到。

? ? ??梯度消失:其實(shí),最直接的原因就是sigmoid型函數(shù)的導(dǎo)數(shù),是小于1的,當(dāng)層數(shù)過多,相乘會越來越趨于零,這就是上課老師說的核心意思,如上圖

? ? ?好了,廢話說完了,我們來看一下,代碼實(shí)例這個是用ReLU來實(shí)現(xiàn)的。

# 定義多層前饋神經(jīng)網(wǎng)絡(luò) class Model_MLP_L5(torch.nn.Module):def __init__(self, input_size, output_size, act='sigmoid'):super(Model_MLP_L5, self).__init__()self.fc1 = torch.nn.Linear(input_size, 3)normal_(self.fc1.weight,mean=0.0, std=0.01)constant_(self.fc1.bias,val=-8.0)self.fc2 = torch.nn.Linear(3, 3)normal_(self.fc2.weight,mean=0.0, std=0.01)constant_(self.fc2.bias,val=-8.0)self.fc3 = torch.nn.Linear(3, 3)normal_(self.fc3.weight,mean=0.0, std=0.01)constant_(self.fc3.bias,val=-8.0)self.fc4 = torch.nn.Linear(3, 3)normal_(self.fc4.weight,mean=0.0, std=0.01)constant_(self.fc4.bias,val=-8.0)self.fc5 = torch.nn.Linear(3, output_size)normal_(self.fc5.weight,mean=0.0, std=0.01)constant_(self.fc5.bias,val=-8.0)# 定義網(wǎng)絡(luò)使用的激活函數(shù)if act == 'sigmoid':self.act = F.sigmoidelif act == 'relu':self.act = F.reluelif act == 'lrelu':self.act = F.leaky_reluelse:raise ValueError("Please enter sigmoid relu or lrelu!")# 初始化線性層權(quán)重和偏置參數(shù)def init_weights(self, w_init, b_init):# 使用'named_sublayers'遍歷所有網(wǎng)絡(luò)層for n, m in self.named_sublayers():# 如果是線性層,則使用指定方式進(jìn)行參數(shù)初始化if isinstance(m, nn.Linear):w_init(m.weight)b_init(m.bias)def forward(self, inputs):outputs = self.fc1(inputs)outputs = self.act(outputs)outputs = self.fc2(outputs)outputs = self.act(outputs)outputs = self.fc3(outputs)outputs = self.act(outputs)outputs = self.fc4(outputs)outputs = self.act(outputs)outputs = self.fc5(outputs)outputs = F.sigmoid(outputs)return outputs

? ? 運(yùn)行結(jié)果為:

The weights of the Layers:
-->name: fc1.weight ?-->grad_value: tensor([[0., 0.],
? ? ? ? [0., 0.],
? ? ? ? [0., 0.]])
---------------------------------
-->name: fc1.bias ?-->grad_value: tensor([0., 0., 0.])
---------------------------------
-->name: fc2.weight ?-->grad_value: tensor([[0., 0., 0.],
? ? ? ? [0., 0., 0.],
? ? ? ? [0., 0., 0.]])
---------------------------------
-->name: fc2.bias ?-->grad_value: tensor([0., 0., 0.])
---------------------------------
-->name: fc3.weight ?-->grad_value: tensor([[0., 0., 0.],
? ? ? ? [0., 0., 0.],
? ? ? ? [0., 0., 0.]])
---------------------------------
-->name: fc3.bias ?-->grad_value: tensor([0., 0., 0.])
---------------------------------
-->name: fc4.weight ?-->grad_value: tensor([[0., 0., 0.],
? ? ? ? [0., 0., 0.],
? ? ? ? [0., 0., 0.]])
---------------------------------
-->name: fc4.bias ?-->grad_value: tensor([0., 0., 0.])
---------------------------------
-->name: fc5.weight ?-->grad_value: tensor([[0., 0., 0.]])
---------------------------------
-->name: fc5.bias ?-->grad_value: tensor([-0.5106])
---------------------------------
[Evaluate] best accuracy performence has been updated: 0.00000 --> 0.52500

使用Leaky ReLU進(jìn)行模型訓(xùn)練

將激活函數(shù)更換為Leaky ReLU進(jìn)行模型訓(xùn)練,觀察梯度情況。代碼實(shí)現(xiàn)如下:

# 重新定義網(wǎng)絡(luò),使用Leaky ReLU激活函數(shù) model = Model_MLP_L5(input_size=2, output_size=1, act='lrelu')# 實(shí)例化Runner類 runner = RunnerV2_2(model, optimizer, metric, loss_fn)# 啟動訓(xùn)練 runner.train([X_train, y_train], [X_dev, y_dev],num_epochs=1, log_epochps=None,save_path="best_model.pdparams",custom_print_log=custom_print_log)

運(yùn)行結(jié)果為:

The weights of the Layers:
-->name: fc1.weight ?-->grad_value: tensor([[-2.2568e-16, ?3.5508e-17],
? ? ? ? [ 1.1090e-16, -1.7448e-17],
? ? ? ? [ 1.9872e-16, -3.1266e-17]])
---------------------------------
-->name: fc1.bias ?-->grad_value: tensor([-2.2717e-16, ?1.1163e-16, ?2.0003e-16])
---------------------------------
-->name: fc2.weight ?-->grad_value: tensor([[-1.6787e-14, -1.6798e-14, -1.6811e-14],
? ? ? ? [ 1.1792e-14, ?1.1799e-14, ?1.1809e-14],
? ? ? ? [-1.3686e-13, -1.3695e-13, -1.3706e-13]])
---------------------------------
-->name: fc2.bias ?-->grad_value: tensor([ 2.1013e-13, -1.4761e-13, ?1.7131e-12])
---------------------------------
-->name: fc3.weight ?-->grad_value: tensor([[-6.6518e-10, -6.6498e-10, -6.6517e-10],
? ? ? ? [-1.2666e-10, -1.2662e-10, -1.2666e-10],
? ? ? ? [ 1.0642e-09, ?1.0639e-09, ?1.0642e-09]])
---------------------------------
-->name: fc3.bias ?-->grad_value: tensor([ 8.3144e-09, ?1.5832e-09, -1.3302e-08])
---------------------------------
-->name: fc4.weight ?-->grad_value: tensor([[-6.6640e-07, -6.6628e-07, -6.6627e-07],
? ? ? ? [-2.9873e-06, -2.9867e-06, -2.9867e-06],
? ? ? ? [-5.7090e-06, -5.7080e-06, -5.7080e-06]])
---------------------------------
-->name: fc4.bias ?-->grad_value: tensor([8.3289e-06, 3.7336e-05, 7.1353e-05])
---------------------------------
-->name: fc5.weight ?-->grad_value: tensor([[0.0401, 0.0401, 0.0401]])
---------------------------------
-->name: fc5.bias ?-->grad_value: tensor([-0.5012])
---------------------------------
[Evaluate] best accuracy performence has been updated: 0.00000 --> 0.55000
[Train] epoch: 0/1, loss: 4.011898994445801?

? ? ? ?從輸出結(jié)果可以看到,將激活函數(shù)更換為Leaky ReLU后,死亡ReLU問題得到了改善,梯度恢復(fù)正常,參數(shù)也可以正常更新。但是由于 Leaky ReLU 中,x<0x<0 時的斜率默認(rèn)只有0.01,所以反向傳播時,隨著網(wǎng)絡(luò)層數(shù)的加深,梯度值越來越小。如果想要改善這一現(xiàn)象,將 Leaky ReLU 中,x<0x<0 時的斜率調(diào)大即可。?
? ? ? 下邊說一下我的理解,因?yàn)槲覈L試過輸出,好幾前千次的結(jié)果,所以在這說一下總結(jié)。(也是根據(jù)老師上課講的)

? ? ? ?dead relu problem是一個動態(tài)的問題,而并不是一個永久性問題只要不是所有輸入都小于0,神經(jīng)元就可以保持活躍,權(quán)重可以更新,網(wǎng)絡(luò)可以繼續(xù)學(xué)習(xí)。因此,dead的relu也是可以復(fù)活的。

? ? ? ?之所以可能會出現(xiàn)較長的dead relu problem主要原因在于前面提到過的,relu activation之前的layer的梯度得不到更新,因此relu activation之前的layer的權(quán)重保持不變,而我們的輸入數(shù)據(jù)本身是不會發(fā)生變化的,這就導(dǎo)致了在每一個epoch中,輸入的數(shù)據(jù)不變還是training數(shù)據(jù)集,relu activation之后的計算結(jié)果一直是0;?

? ? ? ? 如果要徹底避免dead relu problem,則我們使用prelu,leaky relu 等relu的簡單變體就可以了。但是老師上課說了一句話,并沒有任何證明,來證明后邊的變體,在實(shí)際操作是會明顯優(yōu)于relu,有時還并不會優(yōu)于,所以大家一定要注意這個,不要像我以前一樣,經(jīng)驗(yàn)主義。

? ? ? ?最后,放一下各個函數(shù)的圖像,方便大家理解

三、習(xí)題4-7 為什么在神經(jīng)網(wǎng)絡(luò)模型的結(jié)構(gòu)化風(fēng)險函數(shù)中不對偏置b進(jìn)行正則化??

首先,咱們來看一下神書花書的原文

?

神書花書中7.1節(jié),7.5節(jié)都寫到了中寫到:

  • “在神經(jīng)網(wǎng)絡(luò)中,參數(shù)包括每一層仿射變換的權(quán)重和偏置,我們通常只對權(quán)重做懲罰而不對偏置做正則懲罰
  • “正則化偏置參數(shù)可能會導(dǎo)致明顯的欠擬合”
  • 可以通過如下圖來理解,例如我們想要通過wx+b的仿射變換擬合下列散點(diǎn):

    ?

    • 如果同時對權(quán)重w和偏置b進(jìn)行正則,那么擬合的直線很有可能是一條斜率較小、經(jīng)過原點(diǎn)的直線,這樣會導(dǎo)致欠擬合問題(正如書中所說);
    • 相對的,如果只對w進(jìn)行正則而不對b進(jìn)行正則,即使w很小(斜率較小),也可以通過調(diào)整偏置b(即平移)來使得直線較好的擬合數(shù)據(jù)點(diǎn),從而避免了欠擬合問題。

    上課老師也是說過的,并且以前我也問過老師,老師的大致意思是:

    ? ? ? ?這個正則化其實(shí)是一種懲罰策略,是為了防止過擬合的,如果把所有的參數(shù)都進(jìn)行懲罰的話,這樣懲罰會太過,會導(dǎo)致欠擬合,并且參數(shù)是沒有必要進(jìn)行懲罰的。(我感覺這么理解是非常直觀的,好理解的)

    ? ? ? ?達(dá)哥以前講的時候,沒注意,確實(shí)是我的問題,嗚嗚。

    ?下邊有個從數(shù)學(xué)上解釋的,大家要是有興趣看一看吧(感覺不直觀明白,達(dá)哥和老師都是我上邊寫的意思,神書花書也是有數(shù)學(xué)推導(dǎo)的比較直觀,拜一拜)

    ? ? ? 從貝葉斯的角度來講,正則化項通常都包含一定的先驗(yàn)信息,神經(jīng)網(wǎng)絡(luò)傾向于較小的權(quán)重以便更好地泛化,但是對偏置就沒有這樣一致的先驗(yàn)知識。另外,很多神經(jīng)網(wǎng)絡(luò)更傾向于區(qū)分方向信息(對應(yīng)于權(quán)重),而不是位置信息(對應(yīng)于偏置),所以對偏置加正則化項對控制過擬合的作用是有限的,相反很可能會因?yàn)椴磺‘?dāng)?shù)恼齽t強(qiáng)度影響神經(jīng)網(wǎng)絡(luò)找到最優(yōu)點(diǎn)。


    四、習(xí)題 4-8 為什么在用反向傳播算法進(jìn)行參數(shù)學(xué)習(xí)時要采用隨機(jī)參數(shù)初始化的方式而不是直接令 w= 0, 𝒃 = 0?

    ? ? 首先,咱們先說一下這個問題叫什么,然后在舉個例子,然后咱們再看一下代碼,然后咱們說一下解決方案。

    ? ? 首先,這個問題的名字是:

    ? ? 如果對每一層的權(quán)重和偏置都用0初始化,那么通過第一遍前向計算,所有隱藏層神經(jīng)元的激活值都相同;在反向傳播時,所有權(quán)重的更新也都相同,這樣會導(dǎo)致隱藏層神經(jīng)元沒有差異性,出現(xiàn)對稱權(quán)重現(xiàn)象

    ? ? ?那么,咱們像反向傳播那樣,代數(shù)試試。

    ? ? ?設(shè)有一個多層感知機(jī)模型,假設(shè)輸出層只保留一個輸出單元o1o_1o1,且隱藏層使用相同的激活函數(shù)。如果將每個隱藏單元的 參數(shù)都初始化為相等的值,那么在正向傳播時每個隱藏單元將根據(jù)相同的輸入計算出相同的值,并傳遞至輸出層。

    ? ? ?在反向傳播中,每個隱藏單元的參數(shù)梯度值相等。因此,這些參數(shù)在使用基于梯度的優(yōu)化算法迭代后值依然相等。之后的迭代 也是如此。在這種情況下,無論隱藏單元有多少,隱藏層本質(zhì)上只有一個隱藏單元在發(fā)揮作用。

    ? ? ?這樣就比較清楚了,然后咱們看一下代碼。

    class Model_MLP_L2_V4(nn.Module):def __init__(self, input_size, hidden_size, output_size):super(Model_MLP_L2_V4, self).__init__()# 使用'paddle.nn.Linear'定義線性層。# 其中第一個參數(shù)(in_features)為線性層輸入維度;第二個參數(shù)(out_features)為線性層輸出維度# weight_attr為權(quán)重參數(shù)屬性,這里使用'paddle.nn.initializer.Normal'進(jìn)行隨機(jī)高斯分布初始化# bias_attr為偏置參數(shù)屬性,這里使用'paddle.nn.initializer.Constant'進(jìn)行常量初始化self.fc1 = nn.Linear(input_size, hidden_size)w1 = torch.empty(hidden_size,input_size)b1= torch.empty(hidden_size)self.fc1.weight=torch.nn.Parameter(constant_(w1,val=0.0))self.fc1.bias=torch.nn.Parameter(constant_(b1,val=0.0))self.fc2 = nn.Linear(hidden_size, output_size)w2 = torch.empty(output_size,hidden_size)b2 = torch.empty(output_size)self.fc2.weight=torch.nn.Parameter(constant_(w2,val=0.0))self.fc2.bias=torch.nn.Parameter(constant_(b2,val=0.0))# 使用'paddle.nn.functional.sigmoid'定義 Logistic 激活函數(shù)self.act_fn = F.sigmoid# 前向計算def forward(self, inputs):z1 = self.fc1(inputs)a1 = self.act_fn(z1)z2 = self.fc2(a1)a2 = self.act_fn(z2)return a2

    運(yùn)行結(jié)果為:

    ? ? ? ? 從輸出結(jié)果看,二分類準(zhǔn)確率為50%左右,說明模型沒有學(xué)到任何內(nèi)容。訓(xùn)練和驗(yàn)證loss幾乎沒有怎么下降。

    ? ? ? ? 為了避免對稱權(quán)重現(xiàn)象,可以使用高斯分布或均勻分布初始化神經(jīng)網(wǎng)絡(luò)的參數(shù)。

    解決方案

    ? ? ? ?因此,通常對神經(jīng)網(wǎng)絡(luò)的模型參數(shù),特別是權(quán)重參數(shù)進(jìn)行隨機(jī)初始化。隨機(jī)初始化模型參數(shù)的方法有很多,可以使用正態(tài)分布 的隨機(jī)初始化方式。

    ? ? ? ?還有一種比較常用的隨機(jī)初始化方法叫做Xavier隨機(jī)初始化。假設(shè)某全連接層的輸入個數(shù)為a,輸出個數(shù)為b,Xavier隨機(jī)初始 化將使該層中權(quán)重參數(shù)的每個元素都隨機(jī)采樣于均勻分布,它的設(shè)計主要考慮到,模型參數(shù)初始化后,每層輸出的方差不該受該層輸入個數(shù)影響,且每層梯度的方差也不該受該層 輸出個數(shù)影響。

    ? ? ? ?咱們之前試了第一種,但是看達(dá)哥的視頻,達(dá)哥說了后邊的更好一點(diǎn),那必然是后邊的更狠一點(diǎn)了呀。

    五、習(xí)題4-9?梯度消失問題是否可以通過增加學(xué)習(xí)率來緩解?

    ? ? ? ?首先,這個問題我看了好多資料,然后達(dá)哥沒有重點(diǎn)講過,他只是稍微說過一點(diǎn),而且我之前,因?yàn)椴桓艺{(diào)lr,出現(xiàn)了問題,所以也和老師涉及到過,所以先說一下我的理解。

    ? ? ? ?首先,直觀上說他是可以緩解的,但也只是緩解,因?yàn)閺闹庇^上看,迭代的時候是lr乘以梯度,所以如果梯度過小,增大lr會有可能稍微緩解,但是這種情況下,會導(dǎo)致在尋找最小值上出問題,這就和之前說過的情況正好相反了(很有可能是從全局最小,變到了局部最小)。

    ? ? ? ?并且梯度并不會因此而增大,這就會導(dǎo)致每次學(xué)到的,特征會非常少,會導(dǎo)致網(wǎng)絡(luò)極難訓(xùn)練,因?yàn)楦镜脑?#xff0c;并沒有解決,所以我說只會是稍微的緩解,而并不會真正的解決問題。

    ? ? ? ? 然后我看資料,感覺確實(shí)有用,下邊是一個英文版的(還是老師說的對呀,這些好的文章好多都是英文版的

    最后,得出的結(jié)論是:

    ? ? ? ? 不行,因?yàn)樘荻认Р皇侵柑荻忍?#xff0c;而是指的是梯度在最后一層往前傳的過程中不斷減小,這個消失,指的是最底層的梯度和最高層的梯度量級的差別。

    ? ? ? ? 如果你增大了lr,底層的學(xué)習(xí)可能確實(shí)更加有效了,高層的梯度就可能炸了。

    ? ? ? ? 那能不能每層設(shè)置不一樣的lr呢,當(dāng)然可以,adagrad就是這么做的,也確實(shí)有一定效果。(這個上邊文章中寫的)


    總結(jié)

    ? ? ? 首先,先說一下感受,終于有時間拿出一個下午來寫這個了,查了好多東西,寫了一下午,雖然感覺很累,但是我相信這都是值得的(并且這寫完感覺真的很爽,解決了好多問題,哈哈哈)

    ? ? ? 其次,說一下,遇到的問題,我在寫可視化的時候,寫了好長時間,一個是注意matplotlib庫,這個庫不能直接輸入tensor變量,所以這里又要重寫網(wǎng)絡(luò),學(xué)到了常用的方法。(據(jù)說是經(jīng)典網(wǎng)絡(luò)的常用方法,哈哈哈)

    ? ? ? ? 可以看一下,下邊的鏈接,結(jié)合我寫的,對應(yīng)就好明白了

    可視化技巧:分類問題中的決策面畫法 (直觀理解plt.contour的用法)_此人姓于名叫罩百靈的博客-CSDN博客_plt.contour? ? ? ?

    ? ? ??

    ? ? ? ?然后,說一下,我發(fā)現(xiàn)的問題,希望老師和各位大佬可以教我一下,我可視化在畫圖時發(fā)現(xiàn),如果全用relu作為激活函數(shù),效果并不是太好,但是可以第一個用relu函數(shù),第二個用sigmoid函數(shù),損失函數(shù)用交叉熵(也可以用均方誤差,這個影響不太大,幾乎沒區(qū)別),這樣效果會好一點(diǎn),但是也不能保證百分之百訓(xùn)練正確,但是出錯率會比之前小,也就是會比之前全用relu(),好一點(diǎn),因?yàn)?#xff0c;我后來想了想,其實(shí)這個有點(diǎn)偏向與分類的問題。

    ? ? ?

    ? ? ? ? 然后,說一下,感覺之前好多都沒想具體過,也就是沒啥感覺,就是當(dāng)時可能聽達(dá)哥說過,但是沒啥感覺,沒有注意到,就像這次b的正則化那個,要是這次不寫就快忘了。

    ? ? ? ?其次,又深入了一下之前寫過的那幾個問題,又看了好多新的理解,感覺又有了新的理解。

    ? ? ? ?最后,終于變成中風(fēng)險了,終于快要線下見面了,這幾天統(tǒng)計的表也少了不少,終于快要和老師線下見面了(哈哈哈)。

    ? ? ? ?最后,當(dāng)然是謝謝老師,感謝老師在學(xué)習(xí)和生活上的關(guān)心(哈哈哈)

    ? ? ??

    總結(jié)

    以上是生活随笔為你收集整理的NNDL 作业4:第四章课后题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。