【深度學習實踐】03. 多層感知機

模型的復雜度決定了模型的擬合上限,這里的復雜度通常指模型的深度和每層的神經(jīng)元的個數(shù)。當感知機隱藏層的個數(shù)大于等于1層時,則稱為多層感知機。

前面我們介紹了線性模型,線性意味著單調(diào)假設(shè): 任何特征的增大都會導致模型輸出的增大(如果對應的權(quán)重為正), 或者導致模型輸出的減?。ㄈ绻麑臋?quán)重為負)。 有時這是有道理的。 例如,如果我們試圖預測一個人是否會償還貸款。 我們可以認為,在其他條件不變的情況下, 收入較高的申請人總是比收入較低的申請人更有可能償還貸款。 但是,雖然收入與還款概率存在單調(diào)性,但它們不是線性相關(guān)的。 收入從0增加到5萬,可能比從100萬增加到105萬帶來更大的還款可能性。 處理這一問題的一種方法是對我們的數(shù)據(jù)進行預處理, 使線性變得更合理,如使用收入的對數(shù)作為我們的特征。然而我們可以很容易找出違反單調(diào)性的例子。 例如,我們想要根據(jù)體溫預測死亡率。 對于體溫高于37攝氏度的人來說,溫度越高風險越大。 然而,對于體溫低于37攝氏度的人來說,溫度越高風險就越低。 在這種情況下,我們也可以通過一些巧妙的預處理來解決問題。 例如,我們可以使用與37攝氏度的距離作為特征。但是,如何對貓和狗的圖像進行分類呢? 增加位置 (13,17) 處像素的強度是否總是增加(或降低)圖像描繪狗的似然? 對線性模型的依賴對應于一個隱含的假設(shè), 即區(qū)分貓和狗的唯一要求是評估單個像素的強度。 在一個倒置圖像后依然保留類別的世界里,這種方法注定會失敗。與我們前面的例子相比,這里的線性很荒謬, 而且我們難以通過簡單的預處理來解決這個問題。 這是因為任何像素的重要性都以復雜的方式取決于該像素的上下文(周圍像素的值)。

處理這種問題的方式是將原先感知機的模型增加隱藏層,并且引入非線性,這樣模型能夠處理更普遍的函數(shù)關(guān)系模型,而不僅僅是線性關(guān)系。


多層感知機

這個多層感知機有4個輸入,3個輸出,其隱藏層包含5個隱藏單元。 輸入層不涉及任何計算,因此使用此網(wǎng)絡產(chǎn)生輸出只需要實現(xiàn)隱藏層和輸出層的計算。 因此,這個多層感知機中的層數(shù)為2。 注意,這兩個層都是全連接的。 每個輸入都會影響隱藏層中的每個神經(jīng)元, 而隱藏層中的每個神經(jīng)元又會影響輸出層中的每個神經(jīng)元。

全連接層的參數(shù)數(shù)量很多

引入非線性

由于線性模型相加或者復合都為線性模型,所以如果僅僅是增加隱藏層,模型最后仍然是屬于線性模型。證明如下:
\mathbf{O} = (\mathbf{X} \mathbf{W}^{(1)} + \mathbf^{(1)})\mathbf{W}^{(2)} + \mathbf^{(2)} = \mathbf{X} \mathbf{W}^{(1)}\mathbf{W}^{(2)} + \mathbf^{(1)} \mathbf{W}^{(2)} + \mathbf^{(2)} = \mathbf{X} \mathbf{W}+\mathbf

所以,除了在隱藏層中添加額外的神經(jīng)元意外,還需要在每個神經(jīng)元后架設(shè)引入非線性的激活函數(shù)(activation function)\sigma。引入激活函數(shù)后,多層感知機則不會退化為線性模型:
\begin{aligned} \mathbf{H} & = \sigma(\mathbf{X} \mathbf{W}^{(1)} + \mathbf^{(1)}), \\ \mathbf{O} & = \mathbf{H}\mathbf{W}^{(2)} + \mathbf^{(2)}.\\ \end{aligned}

為了構(gòu)建更通用的多層感知機, 我們可以繼續(xù)堆疊這樣的隱藏層, 例如\mathbf{H}^{(1)} =\sigma_1(\mathbf{X} \mathbf{W}^{(1)} + \mathbf^{(1)})\mathbf{H}^{(2)} = \sigma_2(\mathbf{H}^{(1)} \mathbf{W}^{(2)} + \mathbf^{(2)}), 一層疊一層,從而產(chǎn)生更有表達能力的模型。

通用近似定理

多層感知機可以通過隱藏神經(jīng)元,捕捉到輸入之間復雜的相互作用, 這些神經(jīng)元依賴于每個輸入的值。 我們可以很容易地設(shè)計隱藏節(jié)點來執(zhí)行任意計算。 例如,在一對輸入上進行基本邏輯操作,多層感知機是通用近似器。 即使是網(wǎng)絡只有一個隱藏層,給定足夠的神經(jīng)元和正確的權(quán)重, 我們可以對任意函數(shù)建模,盡管實際中學習該函數(shù)是很困難的。 你可能認為神經(jīng)網(wǎng)絡有點像C語言。 C語言和任何其他現(xiàn)代編程語言一樣,能夠表達任何可計算的程序。 但實際上,想出一個符合規(guī)范的程序才是最困難的部分。

而且,雖然一個單隱層網(wǎng)絡能學習任何函數(shù), 但并不意味著我們應該嘗試使用單隱藏層網(wǎng)絡來解決所有問題。 事實上,通過使用更深(而不是更廣)的網(wǎng)絡,我們可以更容易地逼近許多函數(shù)。

激活函數(shù)

最受歡迎的激活函數(shù)是修正線性單元(Rectified linear unit,ReLU), 因為它實現(xiàn)簡單,同時在各種預測任務中表現(xiàn)良好。 [ReLU提供了一種非常簡單的非線性變換]。 給定元素x,ReLU函數(shù)被定義為該元素與0的最大值:
\operatorname{ReLU}(x) = \max(x, 0).

通俗地說,ReLU函數(shù)通過將相應的活性值設(shè)為0,僅保留正元素并丟棄所有負元素。 為了直觀感受一下,我們可以畫出函數(shù)的曲線圖。 正如從圖中所看到,激活函數(shù)是分段線性的。

Relu

使用ReLU的原因是,它求導表現(xiàn)得特別好:要么讓參數(shù)消失,要么讓參數(shù)通過。
這使得優(yōu)化表現(xiàn)的更好,并且ReLU減輕了困擾以往神經(jīng)網(wǎng)絡的梯度消失問題(稍后將詳細介紹)。

ReLU函數(shù)有許多變體,包括參數(shù)化ReLU 該變體為ReLU添加了一個線性項,因此即使參數(shù)是負的,某些信息仍然可以通過:
\operatorname{pReLU}(x) = \max(0, x) + \alpha \min(0, x).

pytorch 實現(xiàn)

import torch
from torch import nn
from d2l import torch as d2l

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.01)

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)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容