經(jīng)典分類(lèi)網(wǎng)絡(luò) ResNet 論文閱讀及PYTORCH示例代碼

上一篇說(shuō)要嘗試一下用 se_ResNeXt 來(lái)給 WS-DAN 網(wǎng)絡(luò)提取特征,在此之前需要先搞懂 ResNeXt 的原理戈锻,而 ResNeXt 則是在 ResNet 基礎(chǔ)上的改進(jìn),所以繞了一大圈,還得從 ResNet 開(kāi)始。說(shuō)來(lái)慚愧佃迄,之前只是用過(guò) ResNet 來(lái)做分類(lèi)任務(wù),論文還真沒(méi)有仔細(xì)讀過(guò)竿音,正好趁這個(gè)機(jī)會(huì)讀一讀這篇“神作”和屎。

論文地址: https://arxiv.org/pdf/1512.03385.pdf

論文閱讀

其實(shí)論文的思想在今天看來(lái)是不難的拴驮,不過(guò)在當(dāng)時(shí) ResNet 提出的時(shí)候可是橫掃了各大分類(lèi)任務(wù)春瞬,這個(gè)網(wǎng)絡(luò)解決了隨著網(wǎng)絡(luò)的加深,分類(lèi)的準(zhǔn)確率不升反降的問(wèn)題套啤。通過(guò)一個(gè)名叫“殘差”的網(wǎng)絡(luò)結(jié)構(gòu)(如下圖所示)宽气,使作者可以只通過(guò)簡(jiǎn)單的網(wǎng)絡(luò)深度堆疊便可達(dá)到提升準(zhǔn)確率的目的。

殘差結(jié)構(gòu)

殘差結(jié)構(gòu)的處理過(guò)程分成兩個(gè)部分潜沦,左邊的 與右邊的 萄涯,最后結(jié)果為兩者相加。其中右邊那根線不會(huì)對(duì) 做任何處理唆鸡,所以沒(méi)有可學(xué)習(xí)的參數(shù)涝影; 為網(wǎng)絡(luò)中負(fù)責(zé)學(xué)習(xí)特征的部分,把整個(gè)殘差結(jié)構(gòu)看做是一個(gè) 函數(shù)的話争占,則負(fù)責(zé)學(xué)習(xí)的部分可以表示為 燃逻,這個(gè)結(jié)構(gòu)學(xué)習(xí)的其實(shí)是輸出結(jié)果與輸入的差值序目,這也是殘差名字的由來(lái)。完整的 ResNet 網(wǎng)絡(luò)由多個(gè)上圖中所示的殘差結(jié)構(gòu)組成伯襟,每個(gè)結(jié)構(gòu)學(xué)習(xí)的都是輸出與輸入之間的差值猿涨,通過(guò)步步逼近,達(dá)到了比直接學(xué)習(xí)輸入好得多的效果姆怪。

文中殘差結(jié)構(gòu)的具體實(shí)現(xiàn)分為兩種叛赚,首先介紹 ResNet-18 與 ResNet-34 使用的殘差結(jié)構(gòu)稱(chēng)為 Basic Block,如下圖所示稽揭,圖中的結(jié)構(gòu)包含了兩個(gè)卷積操作用于提取特征俺附。

Basic Block

對(duì)應(yīng)到代碼中,這是 Pytorch 自帶的 ResNet 實(shí)現(xiàn)中的一部分溪掀,跟上圖對(duì)應(yīng)起來(lái)看更加好理解昙读,我個(gè)人比較喜歡論文與代碼結(jié)合起來(lái)看,因?yàn)槲页诵枰涝碇馀蚯牛惨廊绾稳ナ褂寐耄a更給我一種一目了然的感覺(jué):

class BasicBlock(nn.Module):
    expansion = 1

    def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1,
                 base_width=64, dilation=1, norm_layer=None):
        super(BasicBlock, self).__init__()
        if norm_layer is None:
            norm_layer = nn.BatchNorm2d
        if groups != 1 or base_width != 64:
            raise ValueError('BasicBlock only supports groups=1 and base_width=64')
        if dilation > 1:
            raise NotImplementedError("Dilation > 1 not supported in BasicBlock")
        # Both self.conv1 and self.downsample layers downsample the input when stride != 1
        self.conv1 = conv3x3(inplanes, planes, stride)
        self.bn1 = norm_layer(planes)
        self.relu = nn.ReLU(inplace=True)
        self.conv2 = conv3x3(planes, planes)
        self.bn2 = norm_layer(planes)
        self.downsample = downsample
        self.stride = stride

    def forward(self, x):
        identity = x

        out = self.conv1(x)
        out = self.bn1(out)
        out = self.relu(out)

        out = self.conv2(out)
        out = self.bn2(out)

        if self.downsample is not None:
            identity = self.downsample(x)

        out += identity
        out = self.relu(out)

        return out

另一種殘差結(jié)構(gòu)稱(chēng)為 Bottleneck,就是瓶頸的意思:

瓶頸

作者起名字真的很形象只嚣,網(wǎng)絡(luò)結(jié)構(gòu)也正如這瓶頸一樣沮稚,首先做一個(gè)降維,然后做卷積册舞,然后升維蕴掏,這樣做的好處是可以大大減少計(jì)算量,專(zhuān)門(mén)用于網(wǎng)絡(luò)層數(shù)較深的的網(wǎng)絡(luò)调鲸,ResNet-50 以上的網(wǎng)絡(luò)都有這種基礎(chǔ)結(jié)構(gòu)構(gòu)成(不同層級(jí)的輸入輸出維度可能會(huì)不一樣盛杰,但結(jié)構(gòu)類(lèi)似):
Bottleneck

Pytorch 中的代碼,注意到上圖中為了減少計(jì)算量藐石,作者將 256 維的輸入縮小了 4 倍變?yōu)?64 進(jìn)入卷積即供,在升維時(shí)需要升到 256 維,對(duì)應(yīng)代碼中的 expansion 參數(shù):

class Bottleneck(nn.Module):
    expansion = 4

    def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1,
                 base_width=64, dilation=1, norm_layer=None):
        super(Bottleneck, self).__init__()
        if norm_layer is None:
            norm_layer = nn.BatchNorm2d
        width = int(planes * (base_width / 64.)) * groups
        # Both self.conv2 and self.downsample layers downsample the input when stride != 1
        self.conv1 = conv1x1(inplanes, width)
        self.bn1 = norm_layer(width)
        self.conv2 = conv3x3(width, width, stride, groups, dilation)
        self.bn2 = norm_layer(width)
        self.conv3 = conv1x1(width, planes * self.expansion)
        self.bn3 = norm_layer(planes * self.expansion)
        self.relu = nn.ReLU(inplace=True)
        self.downsample = downsample
        self.stride = stride

    def forward(self, x):
        identity = x

        out = self.conv1(x)
        out = self.bn1(out)
        out = self.relu(out)

        out = self.conv2(out)
        out = self.bn2(out)
        out = self.relu(out)

        out = self.conv3(out)
        out = self.bn3(out)

        if self.downsample is not None:
            identity = self.downsample(x)

        out += identity
        out = self.relu(out)

        return out

由上面介紹的基本結(jié)構(gòu)再加上池化以及全連接層于微,就構(gòu)成了各種完整的網(wǎng)絡(luò):


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

圖中的網(wǎng)絡(luò)在 Pytorch 中都已經(jīng)集成進(jìn)去了逗嫡,而且都是預(yù)訓(xùn)練好的,我們可以在預(yù)訓(xùn)練好的模型上面訓(xùn)練自己的分類(lèi)器株依,大大減少我們的訓(xùn)練時(shí)間驱证。下面簡(jiǎn)單介紹一下如何使用 ResNet。

在 Pytorch 中使用 ResNet

Pytorch 是一個(gè)對(duì)初學(xué)者很友好的深度學(xué)習(xí)框架恋腕,入門(mén)的話非常推薦抹锄,官方提供了一小時(shí)入門(mén)教程:https://pytorch.org/tutorials/beginner/deep_learning_60min_blitz.html
在 Pytorch 中使用 ResNet 只需要 4 行代碼:

from torch import nn
# torchvision 專(zhuān)用于視覺(jué)方面
import torchvision 
  
# pretrained :使用在 ImageNet 數(shù)據(jù)集上預(yù)訓(xùn)練的模型
model = torchvision.models.resnet18(pretrained=True)
# 修改模型的全連接層使其輸出為你需要類(lèi)型數(shù),這里是10
# 由于使用了預(yù)訓(xùn)練的模型 而預(yù)訓(xùn)練的模型輸出為1000類(lèi),所以要修改全連接層
# 若不使用預(yù)訓(xùn)練的模型可以直接在創(chuàng)建模型時(shí)添加參數(shù) num_classes=10 而不需要修改全連接層
model.fc = nn.Linear(model.fc.in_features, 10)

下面你就可以使用這個(gè)模型來(lái)做分類(lèi)了伙单,當(dāng)然到這里還沒(méi)在自己的數(shù)據(jù)集上進(jìn)行訓(xùn)練呆万,關(guān)于如何訓(xùn)練可以參考官方教程:https://pytorch.org/tutorials/beginner/blitz/cifar10_tutorial.html
如果對(duì)代碼以及源碼有疑問(wèn)的話可以在下面留言我們一起討論。

最后车份,求贊求關(guān)注谋减,歡迎關(guān)注我的微信公眾號(hào)[MachineLearning學(xué)習(xí)之路] ,深度學(xué)習(xí) & CV 方向的童鞋不要錯(cuò)過(guò)Iㄕ印出爹!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市缎除,隨后出現(xiàn)的幾起案子严就,更是在濱河造成了極大的恐慌,老刑警劉巖器罐,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件梢为,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡轰坊,警方通過(guò)查閱死者的電腦和手機(jī)铸董,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)肴沫,“玉大人粟害,你說(shuō)我怎么就攤上這事〔遥” “怎么了悲幅?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)站蝠。 經(jīng)常有香客問(wèn)我汰具,道長(zhǎng),這世上最難降的妖魔是什么菱魔? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任留荔,我火速辦了婚禮,結(jié)果婚禮上豌习,老公的妹妹穿的比我還像新娘存谎。我一直安慰自己拔疚,他們只是感情好肥隆,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著稚失,像睡著了一般栋艳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上句各,一...
    開(kāi)封第一講書(shū)人閱讀 49,821評(píng)論 1 290
  • 那天吸占,我揣著相機(jī)與錄音晴叨,去河邊找鬼。 笑死矾屯,一個(gè)胖子當(dāng)著我的面吹牛兼蕊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播件蚕,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼孙技,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了排作?” 一聲冷哼從身側(cè)響起牵啦,我...
    開(kāi)封第一講書(shū)人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎妄痪,沒(méi)想到半個(gè)月后哈雏,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡衫生,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年裳瘪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片罪针。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡盹愚,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出站故,到底是詐尸還是另有隱情皆怕,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布西篓,位于F島的核電站愈腾,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏岂津。R本人自食惡果不足惜虱黄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望吮成。 院中可真熱鬧橱乱,春花似錦、人聲如沸粱甫。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)茶宵。三九已至危纫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背种蝶。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工契耿, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人螃征。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓搪桂,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親盯滚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子锅棕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349

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

  • 文章作者:Tyan博客:noahsnail.com | CSDN | 簡(jiǎn)書(shū) 聲明:作者翻譯論文僅為學(xué)習(xí),如有侵權(quán)請(qǐng)...
    SnailTyan閱讀 5,675評(píng)論 0 4
  • 原文地址: http://www.sohu.com/a/164171974_741733本文收集了大量基于 PyT...
    UlissesJr閱讀 4,806評(píng)論 0 12
  • 聲明:作者翻譯論文僅為學(xué)習(xí)淌山,如有侵權(quán)請(qǐng)聯(lián)系作者刪除博文裸燎,謝謝! 翻譯論文匯總:https://github.com...
    SnailTyan閱讀 12,253評(píng)論 3 13
  • 當(dāng)一個(gè)人到了一定的年齡的時(shí)候就會(huì)知道: 當(dāng)你累了泼疑,會(huì)有很多人對(duì)你說(shuō)德绿,累就別干了⊥松可給你錢(qián)花的有嗎移稳? 當(dāng)你生...
    奮力拼搏A閱讀 332評(píng)論 0 0
  • 喜歡一個(gè)人真的可以沒(méi)有什么理由,就像我們總是可以沒(méi)有任何理由的喜歡上一首無(wú)意間聽(tīng)到的歌会油。如果有人問(wèn)我們說(shuō)為什么喜歡...
    我想做個(gè)夢(mèng)閱讀 282評(píng)論 0 0