[動(dòng)手學(xué)深度學(xué)習(xí)-PyTorch版]-5.6卷積神經(jīng)網(wǎng)絡(luò)-深度卷積神經(jīng)網(wǎng)絡(luò)(AlexNet)

5.6 深度卷積神經(jīng)網(wǎng)絡(luò)(AlexNet)

在LeNet提出后的將近20年里,神經(jīng)網(wǎng)絡(luò)一度被其他機(jī)器學(xué)習(xí)方法超越咸灿,如支持向量機(jī)谨敛。雖然LeNet可以在早期的小數(shù)據(jù)集上取得好的成績率寡,但是在更大的真實(shí)數(shù)據(jù)集上的表現(xiàn)并不盡如人意。一方面整慎,神經(jīng)網(wǎng)絡(luò)計(jì)算復(fù)雜粱挡。雖然20世紀(jì)90年代也有過一些針對神經(jīng)網(wǎng)絡(luò)的加速硬件层坠,但并沒有像之后GPU那樣大量普及。因此买猖,訓(xùn)練一個(gè)多通道改橘、多層和有大量參數(shù)的卷積神經(jīng)網(wǎng)絡(luò)在當(dāng)年很難完成。另一方面政勃,當(dāng)年研究者還沒有大量深入研究參數(shù)初始化和非凸優(yōu)化算法等諸多領(lǐng)域唧龄,導(dǎo)致復(fù)雜的神經(jīng)網(wǎng)絡(luò)的訓(xùn)練通常較困難兼砖。

我們在上一節(jié)看到奸远,神經(jīng)網(wǎng)絡(luò)可以直接基于圖像的原始像素進(jìn)行分類。這種稱為端到端(end-to-end)的方法節(jié)省了很多中間步驟讽挟。然而懒叛,在很長一段時(shí)間里更流行的是研究者通過勤勞與智慧所設(shè)計(jì)并生成的手工特征。這類圖像分類研究的主要流程是:

  1. 獲取圖像數(shù)據(jù)集耽梅;
  2. 使用已有的特征提取函數(shù)生成圖像的特征薛窥;
  3. 使用機(jī)器學(xué)習(xí)模型對圖像的特征分類。

當(dāng)時(shí)認(rèn)為的機(jī)器學(xué)習(xí)部分僅限最后這一步眼姐。如果那時(shí)候跟機(jī)器學(xué)習(xí)研究者交談诅迷,他們會認(rèn)為機(jī)器學(xué)習(xí)既重要又優(yōu)美。優(yōu)雅的定理證明了許多分類器的性質(zhì)众旗。機(jī)器學(xué)習(xí)領(lǐng)域生機(jī)勃勃罢杉、嚴(yán)謹(jǐn)而且極其有用。然而贡歧,如果跟計(jì)算機(jī)視覺研究者交談滩租,則是另外一幅景象。他們會告訴你圖像識別里“不可告人”的現(xiàn)實(shí)是:計(jì)算機(jī)視覺流程中真正重要的是數(shù)據(jù)和特征利朵。也就是說律想,使用較干凈的數(shù)據(jù)集和較有效的特征甚至比機(jī)器學(xué)習(xí)模型的選擇對圖像分類結(jié)果的影響更大。

5.6.1 學(xué)習(xí)特征表示

既然特征如此重要绍弟,它該如何表示呢技即?

我們已經(jīng)提到,在相當(dāng)長的時(shí)間里樟遣,特征都是基于各式各樣手工設(shè)計(jì)的函數(shù)從數(shù)據(jù)中提取的姥份。事實(shí)上,不少研究者通過提出新的特征提取函數(shù)不斷改進(jìn)圖像分類結(jié)果年碘。這一度為計(jì)算機(jī)視覺的發(fā)展做出了重要貢獻(xiàn)澈歉。

然而,另一些研究者則持異議屿衅。他們認(rèn)為特征本身也應(yīng)該由學(xué)習(xí)得來埃难。他們還相信,為了表征足夠復(fù)雜的輸入,特征本身應(yīng)該分級表示涡尘。持這一想法的研究者相信忍弛,多層神經(jīng)網(wǎng)絡(luò)可能可以學(xué)得數(shù)據(jù)的多級表征,并逐級表示越來越抽象的概念或模式考抄。以圖像分類為例细疚,并回憶5.1節(jié)(二維卷積層)中物體邊緣檢測的例子。在多層神經(jīng)網(wǎng)絡(luò)中川梅,圖像的第一級的表示可以是在特定的位置和?度是否出現(xiàn)邊緣疯兼;而第二級的表示說不定能夠?qū)⑦@些邊緣組合出有趣的模式,如花紋贫途;在第三級的表示中吧彪,也許上一級的花紋能進(jìn)一步匯合成對應(yīng)物體特定部位的模式。這樣逐級表示下去丢早,最終姨裸,模型能夠較容易根據(jù)最后一級的表示完成分類任務(wù)。需要強(qiáng)調(diào)的是怨酝,輸入的逐級表示由多層模型中的參數(shù)決定傀缩,而這些參數(shù)都是學(xué)出來的。

盡管一直有一群執(zhí)著的研究者不斷鉆研农猬,試圖學(xué)習(xí)視覺數(shù)據(jù)的逐級表征赡艰,然而很長一段時(shí)間里這些野心都未能實(shí)現(xiàn)。這其中有諸多因素值得我們一一分析盛险。

5.6.1.1 缺失要素一:數(shù)據(jù)

包含許多特征的深度模型需要大量的有標(biāo)簽的數(shù)據(jù)才能表現(xiàn)得比其他經(jīng)典方法更好瞄摊。限于早期計(jì)算機(jī)有限的存儲和90年代有限的研究預(yù)算,大部分研究只基于小的公開數(shù)據(jù)集苦掘。例如换帜,不少研究論文基于加州大學(xué)歐文分校(UCI)提供的若干個(gè)公開數(shù)據(jù)集,其中許多數(shù)據(jù)集只有幾百至幾千張圖像鹤啡。這一狀況在2010年前后興起的大數(shù)據(jù)浪潮中得到改善惯驼。特別是,2009年誕生的ImageNet數(shù)據(jù)集包含了1,000大類物體递瑰,每類有多達(dá)數(shù)千張不同的圖像祟牲。這一規(guī)模是當(dāng)時(shí)其他公開數(shù)據(jù)集無法與之相提并論的。ImageNet數(shù)據(jù)集同時(shí)推動(dòng)計(jì)算機(jī)視覺和機(jī)器學(xué)習(xí)研究進(jìn)入新的階段抖部,使此前的傳統(tǒng)方法不再有優(yōu)勢说贝。

5.6.1.2 缺失要素二:硬件

深度學(xué)習(xí)對計(jì)算資源要求很高。早期的硬件計(jì)算能力有限慎颗,這使訓(xùn)練較復(fù)雜的神經(jīng)網(wǎng)絡(luò)變得很困難乡恕。然而言询,通用GPU的到來改變了這一格局。很久以來傲宜,GPU都是為圖像處理和計(jì)算機(jī)游戲設(shè)計(jì)的运杭,尤其是針對大吞吐量的矩陣和向量乘法從而服務(wù)于基本的圖形變換。值得慶幸的是函卒,這其中的數(shù)學(xué)表達(dá)與深度網(wǎng)絡(luò)中的卷積層的表達(dá)類似辆憔。通用GPU這個(gè)概念在2001年開始興起,涌現(xiàn)出諸如OpenCL和CUDA之類的編程框架报嵌。這使得GPU也在2010年前后開始被機(jī)器學(xué)習(xí)社區(qū)使用虱咧。

5.6.2 AlexNet

2012年,AlexNet橫空出世沪蓬。這個(gè)模型的名字來源于論文第一作者的姓名Alex Krizhevsky [1]彤钟。AlexNet使用了8層卷積神經(jīng)網(wǎng)絡(luò)来候,并以很大的優(yōu)勢贏得了ImageNet 2012圖像識別挑戰(zhàn)賽跷叉。它首次證明了學(xué)習(xí)到的特征可以超越手工設(shè)計(jì)的特征,從而一舉打破計(jì)算機(jī)視覺研究的前狀营搅。

image

AlexNet網(wǎng)絡(luò)結(jié)構(gòu)

AlexNet與LeNet的設(shè)計(jì)理念非常相似云挟,但也有顯著的區(qū)別。

第一转质,與相對較小的LeNet相比园欣,AlexNet包含8層變換,其中有5層卷積和2層全連接隱藏層休蟹,以及1個(gè)全連接輸出層沸枯。下面我們來詳細(xì)描述這些層的設(shè)計(jì)。

AlexNet第一層中的卷積窗口形狀是11×11赂弓。因?yàn)镮mageNet中絕大多數(shù)圖像的高和寬均比MNIST圖像的高和寬大10倍以上绑榴,ImageNet圖像的物體占用更多的像素,所以需要更大的卷積窗口來捕獲物體盈魁。第二層中的卷積窗口形狀減小到5×5翔怎,之后全采用3×3。此外杨耙,第一赤套、第二和第五個(gè)卷積層之后都使用了窗口形狀為3×33×3、步幅為2的最大池化層珊膜。而且容握,AlexNet使用的卷積通道數(shù)也大于LeNet中的卷積通道數(shù)數(shù)十倍。
緊接著最后一個(gè)卷積層的是兩個(gè)輸出個(gè)數(shù)為4096的全連接層车柠。這兩個(gè)巨大的全連接層帶來將近1 GB的模型參數(shù)剔氏。由于早期顯存的限制脖旱,最早的AlexNet使用雙數(shù)據(jù)流的設(shè)計(jì)使一個(gè)GPU只需要處理一半模型。幸運(yùn)的是介蛉,顯存在過去幾年得到了長足的發(fā)展萌庆,因此通常我們不再需要這樣的特別設(shè)計(jì)了。

第二币旧,AlexNet將sigmoid激活函數(shù)改成了更加簡單的ReLU激活函數(shù)践险。一方面,ReLU激活函數(shù)的計(jì)算更簡單吹菱,例如它并沒有sigmoid激活函數(shù)中的求冪運(yùn)算巍虫。另一方面,ReLU激活函數(shù)在不同的參數(shù)初始化方法下使模型更容易訓(xùn)練鳍刷。這是由于當(dāng)sigmoid激活函數(shù)輸出極接近0或1時(shí)占遥,這些區(qū)域的梯度幾乎為0,從而造成反向傳播無法繼續(xù)更新部分模型參數(shù)输瓜;而ReLU激活函數(shù)在正區(qū)間的梯度恒為1瓦胎。因此,若模型參數(shù)初始化不當(dāng)尤揣,sigmoid函數(shù)可能在正區(qū)間得到幾乎為0的梯度搔啊,從而令模型無法得到有效訓(xùn)練。

第三北戏,AlexNet通過丟棄法(參見3.13節(jié))來控制全連接層的模型復(fù)雜度负芋。而LeNet并沒有使用丟棄法。

第四嗜愈,AlexNet引入了大量的圖像增廣旧蛾,如翻轉(zhuǎn)、裁剪和顏色變化蠕嫁,從而進(jìn)一步擴(kuò)大數(shù)據(jù)集來緩解過擬合锨天。我們將在后面的9.1節(jié)(圖像增廣)詳細(xì)介紹這種方法。

下面我們實(shí)現(xiàn)稍微簡化過的AlexNet拌阴。

import time
import torch
from torch import nn, optim
import torchvision

import sys
sys.path.append("..") 
import d2lzh_pytorch as d2l
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來使得輸入與輸出的高和寬一致,且增大輸出通道數(shù)
            nn.Conv2d(96, 256, 5, 1, 2),
            nn.ReLU(),
            nn.MaxPool2d(3, 2),
            # 連續(xù)3個(gè)卷積層迟赃,且使用更小的卷積窗口陪拘。除了最后的卷積層外,進(jìn)一步增大了輸出通道數(shù)纤壁。
            # 前兩個(gè)卷積層后不使用池化層來減小輸入的高和寬
            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ù)倍左刽。使用丟棄層來緩解過擬合
        self.fc = nn.Sequential(
            nn.Linear(256*5*5, 4096),
            nn.ReLU(),
            nn.Dropout(0.5),
            nn.Linear(4096, 4096),
            nn.ReLU(),
            nn.Dropout(0.5),
            # 輸出層。由于這里使用Fashion-MNIST酌媒,所以用類別數(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

打印看看網(wǎng)絡(luò)結(jié)構(gòu)迄靠。

net = AlexNet()
print(net)

輸出:

AlexNet(
  (conv): Sequential(
    (0): Conv2d(1, 96, kernel_size=(11, 11), stride=(4, 4))
    (1): ReLU()
    (2): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
    (3): Conv2d(96, 256, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
    (4): ReLU()
    (5): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
    (6): Conv2d(256, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (7): ReLU()
    (8): Conv2d(384, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (9): ReLU()
    (10): Conv2d(384, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (11): ReLU()
    (12): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (fc): Sequential(
    (0): Linear(in_features=6400, out_features=4096, bias=True)
    (1): ReLU()
    (2): Dropout(p=0.5)
    (3): Linear(in_features=4096, out_features=4096, bias=True)
    (4): ReLU()
    (5): Dropout(p=0.5)
    (6): Linear(in_features=4096, out_features=10, bias=True)
  )
)

5.6.3 讀取數(shù)據(jù)

雖然論文中AlexNet使用ImageNet數(shù)據(jù)集,但因?yàn)镮mageNet數(shù)據(jù)集訓(xùn)練時(shí)間較長喇辽,我們?nèi)杂们懊娴腇ashion-MNIST數(shù)據(jù)集來演示AlexNet掌挚。讀取數(shù)據(jù)的時(shí)候我們額外做了一步將圖像高和寬擴(kuò)大到AlexNet使用的圖像高和寬224。這個(gè)可以通過torchvision.transforms.Resize實(shí)例來實(shí)現(xiàn)菩咨。也就是說吠式,我們在ToTensor實(shí)例前使用Resize實(shí)例,然后使用Compose實(shí)例來將這兩個(gè)變換串聯(lián)以方便調(diào)用抽米。

# 本函數(shù)已保存在d2lzh_pytorch包中方便以后使用
def load_data_fashion_mnist(batch_size, resize=None, root='~/Datasets/FashionMNIST'):
    """Download the fashion mnist dataset and then load into memory."""
    trans = []
    if resize:
        trans.append(torchvision.transforms.Resize(size=resize))
    trans.append(torchvision.transforms.ToTensor())

    transform = torchvision.transforms.Compose(trans)
    mnist_train = torchvision.datasets.FashionMNIST(root=root, train=True, download=True, transform=transform)
    mnist_test = torchvision.datasets.FashionMNIST(root=root, train=False, download=True, transform=transform)

    train_iter = torch.utils.data.DataLoader(mnist_train, batch_size=batch_size, shuffle=True, num_workers=4)
    test_iter = torch.utils.data.DataLoader(mnist_test, batch_size=batch_size, shuffle=False, num_workers=4)

    return train_iter, test_iter

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

5.6.4 訓(xùn)練

這時(shí)候我們可以開始訓(xùn)練AlexNet了。相對于LeNet云茸,由于圖片尺寸變大了而且模型變大了是目,所以需要更大的顯存,也需要更長的訓(xùn)練時(shí)間了标捺。

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)

輸出:

training on  cuda
epoch 1, loss 0.0047, train acc 0.770, test acc 0.865, time 128.3 sec
epoch 2, loss 0.0025, train acc 0.879, test acc 0.889, time 128.8 sec
epoch 3, loss 0.0022, train acc 0.898, test acc 0.901, time 130.4 sec
epoch 4, loss 0.0019, train acc 0.908, test acc 0.900, time 131.4 sec
epoch 5, loss 0.0018, train acc 0.913, test acc 0.902, time 129.9 sec

小結(jié)

  • AlexNet跟LeNet結(jié)構(gòu)類似懊纳,但使用了更多的卷積層和更大的參數(shù)空間來擬合大規(guī)模數(shù)據(jù)集ImageNet。它是淺層神經(jīng)網(wǎng)絡(luò)和深度神經(jīng)網(wǎng)絡(luò)的分界線宜岛。
  • 雖然看上去AlexNet的實(shí)現(xiàn)比LeNet的實(shí)現(xiàn)也就多了幾行代碼而已长踊,但這個(gè)觀念上的轉(zhuǎn)變和真正優(yōu)秀實(shí)驗(yàn)結(jié)果的產(chǎn)生令學(xué)術(shù)界付出了很多年功舀。

參考文獻(xiàn)

[1] Krizhevsky, A., Sutskever, I., & Hinton, G. E. (2012). Imagenet classification with deep convolutional neural networks. In Advances in neural information processing systems (pp. 1097-1105).


注:除代碼外本節(jié)與原書此節(jié)基本相同萍倡,原書傳送門

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市辟汰,隨后出現(xiàn)的幾起案子列敲,更是在濱河造成了極大的恐慌,老刑警劉巖帖汞,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件戴而,死亡現(xiàn)場離奇詭異,居然都是意外死亡翩蘸,警方通過查閱死者的電腦和手機(jī)所意,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來催首,“玉大人扶踊,你說我怎么就攤上這事±扇危” “怎么了秧耗?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長舶治。 經(jīng)常有香客問我分井,道長车猬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任尺锚,我火速辦了婚禮珠闰,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瘫辩。我一直安慰自己铸磅,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布杭朱。 她就那樣靜靜地躺著阅仔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪弧械。 梳的紋絲不亂的頭發(fā)上八酒,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天,我揣著相機(jī)與錄音刃唐,去河邊找鬼羞迷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛画饥,可吹牛的內(nèi)容都是我干的衔瓮。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼抖甘,長吁一口氣:“原來是場噩夢啊……” “哼热鞍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起衔彻,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤薇宠,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后艰额,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體澄港,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年柄沮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了回梧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,727評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡祖搓,死狀恐怖狱意,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情棕硫,我是刑警寧澤髓涯,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站哈扮,受9級特大地震影響纬纪,放射性物質(zhì)發(fā)生泄漏蚓再。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一包各、第九天 我趴在偏房一處隱蔽的房頂上張望摘仅。 院中可真熱鬧,春花似錦问畅、人聲如沸娃属。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽矾端。三九已至,卻和暖如春卵皂,著一層夾襖步出監(jiān)牢的瞬間秩铆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工灯变, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留殴玛,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓添祸,卻偏偏與公主長得像滚粟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子刃泌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評論 2 354

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