動(dòng)手學(xué)深度學(xué)習(xí)PyTorch版-Task03/Task04/Task05

過(guò)擬合陶衅、欠擬合及其解決方案

模型復(fù)雜度

為了解釋模型復(fù)雜度灶体,我們以多項(xiàng)式函數(shù)擬合為例晒骇。給定一個(gè)由標(biāo)量數(shù)據(jù)特征x和對(duì)應(yīng)的標(biāo)量標(biāo)簽y組成的訓(xùn)練數(shù)據(jù)集,多項(xiàng)式函數(shù)擬合的目標(biāo)是找一個(gè)K階多項(xiàng)式函數(shù)

\hat{y} = b + \sum_{k=1}^K x^k w_k

來(lái)近似 y浙于。在上式中,w_k是模型的權(quán)重參數(shù)挟纱,b是偏差參數(shù)羞酗。與線性回歸相同,多項(xiàng)式函數(shù)擬合也使用平方損失函數(shù)紊服。特別地檀轨,一階多項(xiàng)式函數(shù)擬合又叫線性函數(shù)擬合。

給定訓(xùn)練數(shù)據(jù)集欺嗤,模型復(fù)雜度和誤差之間的關(guān)系:

權(quán)重衰減

方法

權(quán)重衰減等價(jià)于 L_2 范數(shù)正則化(regularization)参萄。正則化通過(guò)為模型損失函數(shù)添加懲罰項(xiàng)使學(xué)出的模型參數(shù)值較小,是應(yīng)對(duì)過(guò)擬合的常用手段煎饼。

L2 范數(shù)正則化(regularization)

L_2范數(shù)正則化在模型原損失函數(shù)基礎(chǔ)上添加L_2范數(shù)懲罰項(xiàng)讹挎,從而得到訓(xùn)練所需要最小化的函數(shù)。L_2范數(shù)懲罰項(xiàng)指的是模型權(quán)重參數(shù)每個(gè)元素的平方和與一個(gè)正的常數(shù)的乘積吆玖。以線性回歸中的線性回歸損失函數(shù)為例

\ell(w_1, w_2, b) = \frac{1}{n} \sum_{i=1}^n \frac{1}{2}\left(x_1^{(i)} w_1 + x_2^{(i)} w_2 + b - y^{(i)}\right)^2

其中w_1, w_2是權(quán)重參數(shù)筒溃,b是偏差參數(shù),樣本i的輸入為x_1^{(i)}, x_2^{(i)}沾乘,標(biāo)簽為y^{(i)}怜奖,樣本數(shù)為n。將權(quán)重參數(shù)用向量\boldsymbol{w} = [w_1, w_2]表示意鲸,帶有L_2范數(shù)懲罰項(xiàng)的新?lián)p失函數(shù)為

\ell(w_1, w_2, b) + \frac{\lambda}{2n} |\boldsymbol{w}|^2,

其中超參數(shù)\lambda > 0烦周。當(dāng)權(quán)重參數(shù)均為0時(shí),懲罰項(xiàng)最小怎顾。當(dāng)\lambda較大時(shí)读慎,懲罰項(xiàng)在損失函數(shù)中的比重較大,這通常會(huì)使學(xué)到的權(quán)重參數(shù)的元素較接近0槐雾。當(dāng)\lambda設(shè)為0時(shí)夭委,懲罰項(xiàng)完全不起作用。上式中L_2范數(shù)平方|\boldsymbol{w}|^2展開(kāi)后得到w_1^2 + w_2^2募强。
有了L_2范數(shù)懲罰項(xiàng)后株灸,在小批量隨機(jī)梯度下降中崇摄,我們將線性回歸一節(jié)中權(quán)重w_1w_2的迭代方式更改為

\begin{aligned} w_1 &\leftarrow \left(1- \frac{\eta\lambda}{|\mathcal{B}|} \right)w_1 - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}}x_1^{(i)} \left(x_1^{(i)} w_1 + x_2^{(i)} w_2 + b - y^{(i)}\right),\\ w_2 &\leftarrow \left(1- \frac{\eta\lambda}{|\mathcal{B}|} \right)w_2 - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}}x_2^{(i)} \left(x_1^{(i)} w_1 + x_2^{(i)} w_2 + b - y^{(i)}\right). \end{aligned}

可見(jiàn),L_2范數(shù)正則化令權(quán)重w_1w_2先自乘小于1的數(shù)慌烧,再減去不含懲罰項(xiàng)的梯度逐抑。因此,L_2范數(shù)正則化又叫權(quán)重衰減屹蚊。權(quán)重衰減通過(guò)懲罰絕對(duì)值較大的模型參數(shù)為需要學(xué)習(xí)的模型增加了限制厕氨,這可能對(duì)過(guò)擬合有效。

丟棄法Dropout

多層感知機(jī)中神經(jīng)網(wǎng)絡(luò)圖描述了一個(gè)單隱藏層的多層感知機(jī)汹粤。其中輸入個(gè)數(shù)為4命斧,隱藏單元個(gè)數(shù)為5,且隱藏單元h_ii=1, \ldots, 5)的計(jì)算表達(dá)式為

h_i = \phi\left(x_1 w_{1i} + x_2 w_{2i} + x_3 w_{3i} + x_4 w_{4i} + b_i\right)

這里\phi是激活函數(shù)嘱兼,x_1, \ldots, x_4是輸入国葬,隱藏單元i的權(quán)重參數(shù)為w_{1i}, \ldots, w_{4i},偏差參數(shù)為b_i芹壕。當(dāng)對(duì)該隱藏層使用丟棄法時(shí)汇四,該層的隱藏單元將有一定概率被丟棄掉。設(shè)丟棄概率為p踢涌,那么有p的概率h_i會(huì)被清零船殉,有1-p的概率h_i會(huì)除以1-p做拉伸。丟棄概率是丟棄法的超參數(shù)斯嚎。具體來(lái)說(shuō)利虫,設(shè)隨機(jī)變量\xi_i為0和1的概率分別為p1-p。使用丟棄法時(shí)我們計(jì)算新的隱藏單元h_i'

h_i' = \frac{\xi_i}{1-p} h_i

由于E(\xi_i) = 1-p堡僻,因此

E(h_i') = \frac{E(\xi_i)}{1-p}h_i = h_i

即丟棄法不改變其輸入的期望值糠惫。讓我們對(duì)之前多層感知機(jī)的神經(jīng)網(wǎng)絡(luò)中的隱藏層使用丟棄法,一種可能的結(jié)果如圖所示钉疫,其中h_2h_5被清零硼讽。這時(shí)輸出值的計(jì)算不再依賴h_2h_5,在反向傳播時(shí)牲阁,與這兩個(gè)隱藏單元相關(guān)的權(quán)重的梯度均為0固阁。由于在訓(xùn)練中隱藏層神經(jīng)元的丟棄是隨機(jī)的,即h_1, \ldots, h_5都有可能被清零城菊,輸出層的計(jì)算無(wú)法過(guò)度依賴h_1, \ldots, h_5中的任一個(gè)备燃,從而在訓(xùn)練模型時(shí)起到正則化的作用,并可以用來(lái)應(yīng)對(duì)過(guò)擬合凌唬。在測(cè)試模型時(shí)并齐,我們?yōu)榱四玫礁哟_定性的結(jié)果,一般不使用丟棄法

梯度消失和梯度爆炸

深度模型有關(guān)數(shù)值穩(wěn)定性的典型問(wèn)題是消失(vanishing)和爆炸(explosion)。

當(dāng)神經(jīng)網(wǎng)絡(luò)的層數(shù)較多時(shí)况褪,模型的數(shù)值穩(wěn)定性容易變差撕贞。

假設(shè)一個(gè)層數(shù)為L的多層感知機(jī)的第l\boldsymbol{H}^{(l)}的權(quán)重參數(shù)為\boldsymbol{W}^{(l)},輸出層\boldsymbol{H}^{(L)}的權(quán)重參數(shù)為\boldsymbol{W}^{(L)}测垛。為了便于討論捏膨,不考慮偏差參數(shù),且設(shè)所有隱藏層的激活函數(shù)為恒等映射(identity mapping)\phi(x) = x食侮。給定輸入\boldsymbol{X}脊奋,多層感知機(jī)的第l層的輸出\boldsymbol{H}^{(l)} = \boldsymbol{X} \boldsymbol{W}^{(1)} \boldsymbol{W}^{(2)} \ldots \boldsymbol{W}^{(l)}。此時(shí)疙描,如果層數(shù)l較大,\boldsymbol{H}^{(l)}的計(jì)算可能會(huì)出現(xiàn)衰減或爆炸讶隐。舉個(gè)例子起胰,假設(shè)輸入和所有層的權(quán)重參數(shù)都是標(biāo)量,如權(quán)重參數(shù)為0.2和5巫延,多層感知機(jī)的第30層輸出為輸入\boldsymbol{X}分別與0.2^{30} \approx 1 \times 10^{-21}(消失)和5^{30} \approx 9 \times 10^{20}(爆炸)的乘積效五。當(dāng)層數(shù)較多時(shí),梯度的計(jì)算也容易出現(xiàn)消失或爆炸炉峰。

隨機(jī)初始化模型參數(shù)

在神經(jīng)網(wǎng)絡(luò)中畏妖,通常需要隨機(jī)初始化模型參數(shù)。具體原因如下:

回顧多層感知機(jī)一節(jié)描述的多層感知機(jī)疼阔。為了方便解釋?zhuān)僭O(shè)輸出層只保留一個(gè)輸出單元o_1(刪去o_2o_3以及指向它們的箭頭)戒劫,且隱藏層使用相同的激活函數(shù)。如果將每個(gè)隱藏單元的參數(shù)都初始化為相等的值婆廊,那么在正向傳播時(shí)每個(gè)隱藏單元將根據(jù)相同的輸入計(jì)算出相同的值迅细,并傳遞至輸出層。在反向傳播中淘邻,每個(gè)隱藏單元的參數(shù)梯度值相等茵典。因此,這些參數(shù)在使用基于梯度的優(yōu)化算法迭代后值依然相等宾舅。之后的迭代也是如此统阿。在這種情況下,無(wú)論隱藏單元有多少筹我,隱藏層本質(zhì)上只有1個(gè)隱藏單元在發(fā)揮作用扶平。因此,正如在前面的實(shí)驗(yàn)中所做的那樣蔬蕊,我們通常將神經(jīng)網(wǎng)絡(luò)的模型參數(shù)蜻直,特別是權(quán)重參數(shù),進(jìn)行隨機(jī)初始化。

image

(1)PyTorch的默認(rèn)隨機(jī)初始化

隨機(jī)初始化模型參數(shù)的方法有很多概而。在線性回歸的簡(jiǎn)潔實(shí)現(xiàn)中呼巷,我們使用torch.nn.init.normal_()使模型net的權(quán)重參數(shù)采用正態(tài)分布的隨機(jī)初始化方式。不過(guò)赎瑰,PyTorch中nn.Module的模塊參數(shù)都采取了較為合理的初始化策略(不同類(lèi)型的layer具體采樣的哪一種初始化方法的可參考源代碼)王悍,因此一般不用我們考慮。

(2)Xavier隨機(jī)初始化

還有一種比較常用的隨機(jī)初始化方法叫作Xavier隨機(jī)初始化餐曼。
假設(shè)某全連接層的輸入個(gè)數(shù)為a压储,輸出個(gè)數(shù)為b,Xavier隨機(jī)初始化將使該層中權(quán)重參數(shù)的每個(gè)元素都隨機(jī)采樣于均勻分布

U\left(-\sqrt{\frac{6}{a+b}}, \sqrt{\frac{6}{a+b}}\right).

它的設(shè)計(jì)主要考慮到源譬,模型參數(shù)初始化后集惋,每層輸出的方差不該受該層輸入個(gè)數(shù)影響,且每層梯度的方差也不該受該層輸出個(gè)數(shù)影響踩娘。

卷積神經(jīng)網(wǎng)絡(luò)

卷積層與全連接層的對(duì)比

二維卷積層經(jīng)常用于處理圖像刮刑,與此前的全連接層相比,它主要有兩個(gè)優(yōu)勢(shì):

一是全連接層把圖像展平成一個(gè)向量养渴,在輸入圖像上相鄰的元素可能因?yàn)檎蛊讲僮鞑辉傧噜徖拙睿W(wǎng)絡(luò)難以捕捉局部信息。而卷積層的設(shè)計(jì)理卑,天然地具有提取局部信息的能力翘紊。

二是卷積層的參數(shù)量更少。不考慮偏置的情況下藐唠,一個(gè)形狀為(c_i, c_o, h, w)的卷積核的參數(shù)量是c_i \times c_o \times h \times w帆疟,與輸入圖像的寬高無(wú)關(guān)。假如一個(gè)卷積層的輸入和輸出形狀分別是(c_1, h_1, w_1)(c_2, h_2, w_2)宇立,如果要用全連接層進(jìn)行連接鸯匹,參數(shù)數(shù)量就是c_1 \times c_2 \times h_1 \times w_1 \times h_2 \times w_2。使用卷積層可以以較少的參數(shù)數(shù)量來(lái)處理更大的圖像泄伪。

卷積層的簡(jiǎn)潔實(shí)現(xiàn)

我們使用Pytorch中的nn.Conv2d類(lèi)來(lái)實(shí)現(xiàn)二維卷積層殴蓬,主要關(guān)注以下幾個(gè)構(gòu)造函數(shù)參數(shù):

  • in_channels (python:int) – Number of channels in the input imag
  • out_channels (python:int) – Number of channels produced by the convolution
  • kernel_size (python:int or tuple) – Size of the convolving kernel
  • stride (python:int or tuple, optional) – Stride of the convolution. Default: 1
  • padding (python:int or tuple, optional) – Zero-padding added to both sides of the input. Default: 0
  • bias (bool, optional) – If True, adds a learnable bias to the output. Default: True

forward函數(shù)的參數(shù)為一個(gè)四維張量,形狀為(N, C_{in}, H_{in}, W_{in})蟋滴,返回值也是一個(gè)四維張量染厅,形狀為(N, C_{out}, H_{out}, W_{out}),其中N是批量大小津函,C, H, W分別表示通道數(shù)肖粮、高度、寬度尔苦。

代碼講解

X = torch.rand(4, 2, 3, 5)
print(X.shape)

conv2d = nn.Conv2d(in_channels=2, out_channels=3, kernel_size=(3, 5), stride=1, padding=(1, 2))
Y = conv2d(X)
print('Y.shape: ', Y.shape)
print('weight.shape: ', conv2d.weight.shape)
print('bias.shape: ', conv2d.bias.shape)

全連接層和卷積層

使用全連接層的局限性:

  • 圖像在同一列鄰近的像素在這個(gè)向量中可能相距較遠(yuǎn)涩馆。它們構(gòu)成的模式可能難以被模型識(shí)別行施。
  • 對(duì)于大尺寸的輸入圖像,使用全連接層容易導(dǎo)致模型過(guò)大魂那。

使用卷積層的優(yōu)勢(shì):

  • 卷積層保留輸入形狀蛾号。
  • 卷積層通過(guò)滑動(dòng)窗口將同一卷積核與不同位置的輸入重復(fù)計(jì)算,從而避免參數(shù)尺寸過(guò)大涯雅。

LeNet 模型

LeNet分為卷積層塊和全連接層塊兩個(gè)部分柑贞。下面我們分別介紹這兩個(gè)模塊描函。

image

卷積層塊里的基本單位是卷積層后接平均池化層:卷積層用來(lái)識(shí)別圖像里的空間模式咙边,如線條和物體局部剪决,之后的平均池化層則用來(lái)降低卷積層對(duì)位置的敏感性。

卷積層塊由兩個(gè)這樣的基本單位重復(fù)堆疊構(gòu)成蔗候。在卷積層塊中怒允,每個(gè)卷積層都使用5 \times 5的窗口,并在輸出上使用sigmoid激活函數(shù)锈遥。第一個(gè)卷積層輸出通道數(shù)為6纫事,第二個(gè)卷積層輸出通道數(shù)則增加到16。

全連接層塊含3個(gè)全連接層迷殿。它們的輸出個(gè)數(shù)分別是120、84和10咖杂,其中10為輸出的類(lèi)別個(gè)數(shù)庆寺。

#net
class Flatten(torch.nn.Module):  #展平操作
    def forward(self, x):
        return x.view(x.shape[0], -1)

class Reshape(torch.nn.Module): #將圖像大小重定型
    def forward(self, x):
        return x.view(-1,1,28,28)      #(B x C x H x W)
    
net = torch.nn.Sequential(     #Lelet                                                  
    Reshape(),
    nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5, padding=2), #b*1*28*28  =>b*6*28*28
    nn.Sigmoid(),                                                       
    nn.AvgPool2d(kernel_size=2, stride=2),                              #b*6*28*28  =>b*6*14*14
    nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5),           #b*6*14*14  =>b*16*10*10
    nn.Sigmoid(),
    nn.AvgPool2d(kernel_size=2, stride=2),                              #b*16*10*10  => b*16*5*5
    Flatten(),                                                          #b*16*5*5   => b*400
    nn.Linear(in_features=16*5*5, out_features=120),
    nn.Sigmoid(),
    nn.Linear(120, 84),
    nn.Sigmoid(),
    nn.Linear(84, 10)
)
LeNet交替使用卷積層和最大池化層后接全連接層來(lái)進(jìn)行圖像分類(lèi)

AlexNet

首次證明了學(xué)習(xí)到的特征可以超越??設(shè)計(jì)的特征,從而?舉打破計(jì)算機(jī)視覺(jué)研究的前狀诉字。
特征:

  1. 8層變換懦尝,其中有5層卷積和2層全連接隱藏層,以及1個(gè)全連接輸出層壤圃。
  2. 將sigmoid激活函數(shù)改成了更加簡(jiǎn)單的ReLU激活函數(shù)陵霉。
  3. 用Dropout來(lái)控制全連接層的模型復(fù)雜度。
  4. 引入數(shù)據(jù)增強(qiáng)伍绳,如翻轉(zhuǎn)踊挠、裁剪和顏色變化,從而進(jìn)一步擴(kuò)大數(shù)據(jù)集來(lái)緩解過(guò)擬合冲杀。
image
import time
import torch
from torch import nn, optim
import torchvision
import numpy as np
import sys
sys.path.append("/home/kesci/input/") 
import d2lzh1981 as d2l
import os
import torch.nn.functional as F

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

class AlexNet(nn.Module):
    def __init__(self):
        super(AlexNet, self).__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(1, 96, 11, 4), # in_channels, out_channels, kernel_size, stride, padding
            nn.ReLU(),
            nn.MaxPool2d(3, 2), # kernel_size, stride
            # 減小卷積窗口效床,使用填充為2來(lái)使得輸入與輸出的高和寬一致,且增大輸出通道數(shù)
            nn.Conv2d(96, 256, 5, 1, 2),
            nn.ReLU(),
            nn.MaxPool2d(3, 2),
            # 連續(xù)3個(gè)卷積層权谁,且使用更小的卷積窗口剩檀。除了最后的卷積層外,進(jìn)一步增大了輸出通道數(shù)旺芽。
            # 前兩個(gè)卷積層后不使用池化層來(lái)減小輸入的高和寬
            nn.Conv2d(256, 384, 3, 1, 1),
            nn.ReLU(),
            nn.Conv2d(384, 384, 3, 1, 1),
            nn.ReLU(),
            nn.Conv2d(384, 256, 3, 1, 1),
            nn.ReLU(),
            nn.MaxPool2d(3, 2)
        )
         # 這里全連接層的輸出個(gè)數(shù)比LeNet中的大數(shù)倍沪猴。使用丟棄層來(lái)緩解過(guò)擬合
        self.fc = nn.Sequential(
            nn.Linear(256*5*5, 4096),
            nn.ReLU(),
            nn.Dropout(0.5),
            #由于使用CPU鏡像辐啄,精簡(jiǎn)網(wǎng)絡(luò),若為GPU鏡像可添加該層
            #nn.Linear(4096, 4096),
            #nn.ReLU(),
            #nn.Dropout(0.5),

            # 輸出層运嗜。由于這里使用Fashion-MNIST壶辜,所以用類(lèi)別數(shù)為10,而非論文中的1000
            nn.Linear(4096, 10),
        )

    def forward(self, img):

        feature = self.conv(img)
        output = self.fc(feature.view(img.shape[0], -1))
        return output

* 使用重復(fù)元素的網(wǎng)絡(luò)(VGG)

VGG:通過(guò)重復(fù)使?簡(jiǎn)單的基礎(chǔ)塊來(lái)構(gòu)建深度模型洗出。
Block:數(shù)個(gè)相同的填充為1士复、窗口形狀為3\times 3的卷積層,接上一個(gè)步幅為2、窗口形狀為2\times 2的最大池化層翩活。
卷積層保持輸入的高和寬不變阱洪,而池化層則對(duì)其減半。

VGG11的簡(jiǎn)單實(shí)現(xiàn)
def vgg_block(num_convs, in_channels, out_channels): #卷積層個(gè)數(shù)菠镇,輸入通道數(shù)冗荸,輸出通道數(shù)
    blk = []
    for i in range(num_convs):
        if i == 0:
            blk.append(nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1))
        else:
            blk.append(nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1))
        blk.append(nn.ReLU())
    blk.append(nn.MaxPool2d(kernel_size=2, stride=2)) # 這里會(huì)使寬高減半
    return nn.Sequential(*blk)
conv_arch = ((1, 1, 64), (1, 64, 128), (2, 128, 256), (2, 256, 512), (2, 512, 512))
# 經(jīng)過(guò)5個(gè)vgg_block, 寬高會(huì)減半5次, 變成 224/32 = 7
fc_features = 512 * 7 * 7 # c * w * h
fc_hidden_units = 4096 # 任意
net = vgg(conv_arch, fc_features, fc_hidden_units)
X = torch.rand(1, 1, 224, 224)

# named_children獲取一級(jí)子模塊及其名字(named_modules會(huì)返回所有子模塊,包括子模塊的子模塊)
for name, blk in net.named_children(): 
    X = blk(X)
    print(name, 'output shape: ', X.shape)
ratio = 8
small_conv_arch = [(1, 1, 64//ratio), (1, 64//ratio, 128//ratio), (2, 128//ratio, 256//ratio), 
                   (2, 256//ratio, 512//ratio), (2, 512//ratio, 512//ratio)]
net = vgg(small_conv_arch, fc_features // ratio, fc_hidden_units // ratio)
print(net)

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

Sequential(
  (vgg_block_1): Sequential(
    (0): Conv2d(1, 8, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (1): ReLU()
    (2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (vgg_block_2): Sequential(
    (0): Conv2d(8, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (1): ReLU()
    (2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (vgg_block_3): Sequential(
    (0): Conv2d(16, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (1): ReLU()
    (2): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (3): ReLU()
    (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (vgg_block_4): Sequential(
    (0): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (1): ReLU()
    (2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (3): ReLU()
    (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (vgg_block_5): Sequential(
    (0): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (1): ReLU()
    (2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (3): ReLU()
    (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (fc): Sequential(
    (0): FlattenLayer()
    (1): Linear(in_features=3136, out_features=512, bias=True)
    (2): ReLU()
    (3): Dropout(p=0.5, inplace=False)
    (4): Linear(in_features=512, out_features=512, bias=True)
    (5): ReLU()
    (6): Dropout(p=0.5, inplace=False)
    (7): Linear(in_features=512, out_features=10, bias=True)
  )
)
batchsize=16
#batch_size = 64
# 如出現(xiàn)“out of memory”的報(bào)錯(cuò)信息,可減小batch_size或resize
# train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize=224)

lr, num_epochs = 0.001, 5
optimizer = torch.optim.Adam(net.parameters(), lr=lr)
d2l.train_ch5(net, train_iter, test_iter, batch_size, optimizer, device, num_epochs)

* ?絡(luò)中的?絡(luò)(NiN)

LeNet利耍、AlexNet和VGG:先以由卷積層構(gòu)成的模塊充分抽取空間特征蚌本,再以由全連接層構(gòu)成的模塊來(lái)輸出分類(lèi)結(jié)果。
NiN:串聯(lián)多個(gè)由卷積層和“全連接”層構(gòu)成的小?絡(luò)來(lái)構(gòu)建?個(gè)深層?絡(luò)隘梨。
?了輸出通道數(shù)等于標(biāo)簽類(lèi)別數(shù)的NiN塊程癌,然后使?全局平均池化層對(duì)每個(gè)通道中所有元素求平均并直接?于分類(lèi)。

image

1×1卷積核作用
(1).放縮通道數(shù):通過(guò)控制卷積核的數(shù)量達(dá)到通道數(shù)的放縮轴猎。
(2).增加非線性嵌莉。1×1卷積核的卷積過(guò)程相當(dāng)于全連接層的計(jì)算過(guò)程,并且還加入了非線性激活函數(shù)捻脖,從而可以增加網(wǎng)絡(luò)的非線性锐峭。
(3).計(jì)算參數(shù)少

def nin_block(in_channels, out_channels, kernel_size, stride, padding):
    blk = nn.Sequential(nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding),
                        nn.ReLU(),
                        nn.Conv2d(out_channels, out_channels, kernel_size=1),
                        nn.ReLU(),
                        nn.Conv2d(out_channels, out_channels, kernel_size=1),
                        nn.ReLU())
    return blk
# 已保存在d2lzh_pytorch
class GlobalAvgPool2d(nn.Module):
    # 全局平均池化層可通過(guò)將池化窗口形狀設(shè)置成輸入的高和寬實(shí)現(xiàn)
    def __init__(self):
        super(GlobalAvgPool2d, self).__init__()
    def forward(self, x):
        return F.avg_pool2d(x, kernel_size=x.size()[2:])

net = nn.Sequential(
    nin_block(1, 96, kernel_size=11, stride=4, padding=0),
    nn.MaxPool2d(kernel_size=3, stride=2),
    nin_block(96, 256, kernel_size=5, stride=1, padding=2),
    nn.MaxPool2d(kernel_size=3, stride=2),
    nin_block(256, 384, kernel_size=3, stride=1, padding=1),
    nn.MaxPool2d(kernel_size=3, stride=2), 
    nn.Dropout(0.5),
    # 標(biāo)簽類(lèi)別數(shù)是10
    nin_block(384, 10, kernel_size=3, stride=1, padding=1),
    GlobalAvgPool2d(), 
    # 將四維的輸出轉(zhuǎn)成二維的輸出,其形狀為(批量大小, 10)
    d2l.FlattenLayer())
X = torch.rand(1, 1, 224, 224)
for name, blk in net.named_children(): 
    X = blk(X)
    print(name, 'output shape: ', X.shape)
batch_size = 128
# 如出現(xiàn)“out of memory”的報(bào)錯(cuò)信息可婶,可減小batch_size或resize
#train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize=224)

lr, num_epochs = 0.002, 5
optimizer = torch.optim.Adam(net.parameters(), lr=lr)
d2l.train_ch5(net, train_iter, test_iter, batch_size, optimizer, device, num_epochs)
NiN特點(diǎn)

NiN重復(fù)使?由卷積層和代替全連接層的1×1卷積層構(gòu)成的NiN塊來(lái)構(gòu)建深層?絡(luò)沿癞。
NiN去除了容易造成過(guò)擬合的全連接輸出層,而是將其替換成輸出通道數(shù)等于標(biāo)簽類(lèi)別數(shù) 的NiN塊和全局平均池化層矛渴。
NiN的以上設(shè)計(jì)思想影響了后??系列卷積神經(jīng)?絡(luò)的設(shè)計(jì)椎扬。

* GoogLeNet

  1. 由Inception基礎(chǔ)塊組成。
  2. Inception塊相當(dāng)于?個(gè)有4條線路的??絡(luò)具温。它通過(guò)不同窗口形狀的卷積層和最?池化層來(lái)并?抽取信息盗舰,并使?1×1卷積層減少通道數(shù)從而降低模型復(fù)雜度。
  3. 可以?定義的超參數(shù)是每個(gè)層的輸出通道數(shù)桂躏,我們以此來(lái)控制模型復(fù)雜度钻趋。
image
class Inception(nn.Module):
    # c1 - c4為每條線路里的層的輸出通道數(shù)
    def __init__(self, in_c, c1, c2, c3, c4):
        super(Inception, self).__init__()
        # 線路1,單1 x 1卷積層
        self.p1_1 = nn.Conv2d(in_c, c1, kernel_size=1)
        # 線路2剂习,1 x 1卷積層后接3 x 3卷積層
        self.p2_1 = nn.Conv2d(in_c, c2[0], kernel_size=1)
        self.p2_2 = nn.Conv2d(c2[0], c2[1], kernel_size=3, padding=1)
        # 線路3蛮位,1 x 1卷積層后接5 x 5卷積層
        self.p3_1 = nn.Conv2d(in_c, c3[0], kernel_size=1)
        self.p3_2 = nn.Conv2d(c3[0], c3[1], kernel_size=5, padding=2)
        # 線路4较沪,3 x 3最大池化層后接1 x 1卷積層
        self.p4_1 = nn.MaxPool2d(kernel_size=3, stride=1, padding=1)
        self.p4_2 = nn.Conv2d(in_c, c4, kernel_size=1)

    def forward(self, x):
        p1 = F.relu(self.p1_1(x))
        p2 = F.relu(self.p2_2(F.relu(self.p2_1(x))))
        p3 = F.relu(self.p3_2(F.relu(self.p3_1(x))))
        p4 = F.relu(self.p4_2(self.p4_1(x)))
        return torch.cat((p1, p2, p3, p4), dim=1)  # 在通道維上連結(jié)輸出
GoogLeNet模型

完整模型結(jié)構(gòu)

image
b1 = nn.Sequential(nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3),
                   nn.ReLU(),
                   nn.MaxPool2d(kernel_size=3, stride=2, padding=1))

b2 = nn.Sequential(nn.Conv2d(64, 64, kernel_size=1),
                   nn.Conv2d(64, 192, kernel_size=3, padding=1),
                   nn.MaxPool2d(kernel_size=3, stride=2, padding=1))

b3 = nn.Sequential(Inception(192, 64, (96, 128), (16, 32), 32),
                   Inception(256, 128, (128, 192), (32, 96), 64),
                   nn.MaxPool2d(kernel_size=3, stride=2, padding=1))

b4 = nn.Sequential(Inception(480, 192, (96, 208), (16, 48), 64),
                   Inception(512, 160, (112, 224), (24, 64), 64),
                   Inception(512, 128, (128, 256), (24, 64), 64),
                   Inception(512, 112, (144, 288), (32, 64), 64),
                   Inception(528, 256, (160, 320), (32, 128), 128),
                   nn.MaxPool2d(kernel_size=3, stride=2, padding=1))

b5 = nn.Sequential(Inception(832, 256, (160, 320), (32, 128), 128),
                   Inception(832, 384, (192, 384), (48, 128), 128),
                   d2l.GlobalAvgPool2d())

net = nn.Sequential(b1, b2, b3, b4, b5, 
                    d2l.FlattenLayer(), nn.Linear(1024, 10))

net = nn.Sequential(b1, b2, b3, b4, b5, d2l.FlattenLayer(), nn.Linear(1024, 10))

X = torch.rand(1, 1, 96, 96)

for blk in net.children(): 
    X = blk(X)
    print('output shape: ', X.shape)

#batchsize=128
batch_size = 16
# 如出現(xiàn)“out of memory”的報(bào)錯(cuò)信息,可減小batch_size或resize
#train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize=96)

lr, num_epochs = 0.001, 5
optimizer = torch.optim.Adam(net.parameters(), lr=lr)
d2l.train_ch5(net, train_iter, test_iter, batch_size, optimizer, device, num_epochs)

這篇文字對(duì)Word2Vec的數(shù)學(xué)原理講解的不錯(cuò)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末失仁,一起剝皮案震驚了整個(gè)濱河市尸曼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌萄焦,老刑警劉巖控轿,帶你破解...
    沈念sama閱讀 221,406評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異拂封,居然都是意外死亡茬射,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,395評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門(mén)冒签,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)在抛,“玉大人,你說(shuō)我怎么就攤上這事萧恕「账螅” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,815評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵票唆,是天一觀的道長(zhǎng)朴读。 經(jīng)常有香客問(wèn)我,道長(zhǎng)走趋,這世上最難降的妖魔是什么衅金? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,537評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮吆视,結(jié)果婚禮上典挑,老公的妹妹穿的比我還像新娘酥宴。我一直安慰自己啦吧,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,536評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布拙寡。 她就那樣靜靜地躺著授滓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪肆糕。 梳的紋絲不亂的頭發(fā)上般堆,一...
    開(kāi)封第一講書(shū)人閱讀 52,184評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音诚啃,去河邊找鬼淮摔。 笑死,一個(gè)胖子當(dāng)著我的面吹牛始赎,可吹牛的內(nèi)容都是我干的和橙。 我是一名探鬼主播仔燕,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼魔招!你這毒婦竟也來(lái)了晰搀?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,668評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤办斑,失蹤者是張志新(化名)和其女友劉穎外恕,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體乡翅,經(jīng)...
    沈念sama閱讀 46,212評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鳞疲,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,299評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了峦朗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片建丧。...
    茶點(diǎn)故事閱讀 40,438評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖波势,靈堂內(nèi)的尸體忽然破棺而出翎朱,到底是詐尸還是另有隱情,我是刑警寧澤尺铣,帶...
    沈念sama閱讀 36,128評(píng)論 5 349
  • 正文 年R本政府宣布拴曲,位于F島的核電站,受9級(jí)特大地震影響凛忿,放射性物質(zhì)發(fā)生泄漏澈灼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,807評(píng)論 3 333
  • 文/蒙蒙 一店溢、第九天 我趴在偏房一處隱蔽的房頂上張望叁熔。 院中可真熱鬧,春花似錦床牧、人聲如沸荣回。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,279評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)心软。三九已至,卻和暖如春著蛙,著一層夾襖步出監(jiān)牢的瞬間删铃,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,395評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工踏堡, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留猎唁,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,827評(píng)論 3 376
  • 正文 我出身青樓顷蟆,卻偏偏與公主長(zhǎng)得像诫隅,于是被迫代替她去往敵國(guó)和親缎患。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,446評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容