基于PaddlePaddle實現(xiàn)ResNet在Cifar10上的訓(xùn)練全過程

當(dāng)網(wǎng)絡(luò)層數(shù)走向更深時丘逸,出現(xiàn)了網(wǎng)絡(luò)退化問題媒楼,即增加網(wǎng)絡(luò)層數(shù)之后,訓(xùn)練誤差往往不降反升雳刺,網(wǎng)絡(luò)性能快速下降劫灶。2015年何愷明推出的ResNet,通過增加一個identity mapping(恒等映射)掖桦,將原始所需要學(xué)的函數(shù)H(x)轉(zhuǎn)換成F(x)+x本昏,成功訓(xùn)練152層深的神經(jīng)網(wǎng)絡(luò),在ILSVRC2015比賽中獲得了冠軍枪汪,top-5錯誤率為3.57%涌穆,同時參數(shù)量卻比VGGNet低很多。

引用自:Deep Residual Learning for Image Recognition

引用地址:Deep Residual Learning for Image Recognition

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


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

代碼實現(xiàn):

import paddle 
import paddle.nn.functional as F # 組網(wǎng)相關(guān)的函數(shù)雀久,如conv2d, relu...
import numpy as np
from paddle.nn.layer.common import Dropout 
from paddle.vision.transforms import Compose, Resize, Transpose, Normalize, ToTensor
from paddle.vision.datasets import Cifar10

# 構(gòu)建ResNet網(wǎng)絡(luò)
# Sequential:順序容器蒲犬,子Layer將按構(gòu)造函數(shù)參數(shù)的順序添加到此容器中,傳遞給構(gòu)造函數(shù)的參數(shù)可以Layers或可迭代的name Layer元組
from paddle.nn import Sequential, Conv2D, ReLU, MaxPool2D, Linear, Dropout, Flatten, BatchNorm2D, AvgPool2D

#構(gòu)建模型
class Residual(paddle.nn.Layer):
    def __init__(self, in_channel, out_channel, use_conv1x1=False, stride=1):
        super().__init__()
        self.conv1 = Conv2D(in_channel, out_channel, kernel_size=3, padding=1, stride=stride)
        self.conv2 = Conv2D(out_channel, out_channel, kernel_size=3, padding=1)
        if use_conv1x1: #使用1x1卷積核
            self.conv3 = Conv2D(in_channel, out_channel, kernel_size=1, stride=stride)
        else:
            self.conv3 = None
        self.batchNorm1 = BatchNorm2D(out_channel)
        self.batchNorm2 = BatchNorm2D(out_channel)

    def forward(self, x):
        y = F.relu(self.batchNorm1(self.conv1(x)))
        y = self.batchNorm2(self.conv2(y))
        if self.conv3:
            x = self.conv3(x)
        out = F.relu(y+x) #核心代碼
        return out

殘差網(wǎng)絡(luò)ResNet50代碼實現(xiàn):

def ResNetBlock(in_channel, out_channel, num_layers, is_first=False):
    if is_first:
        assert in_channel == out_channel
    block_list = []
    for i in range(num_layers):
        if i == 0 and not is_first:
            block_list.append(Residual(in_channel, out_channel, use_conv1x1=True, stride=2))
        else:
            block_list.append(Residual(out_channel, out_channel))
    resNetBlock = Sequential(*block_list) #用*號可以把list列表展開為元素
    return resNetBlock

class ResNet50(paddle.nn.Layer):
    def __init__(self, num_classes=10):
        super().__init__()
        self.b1 = Sequential(
                    Conv2D(3, 64, kernel_size=7, stride=2, padding=3),
                    BatchNorm2D(64), 
                    ReLU(),
                    MaxPool2D(kernel_size=3, stride=2, padding=1))
        self.b2 = ResNetBlock(64, 64, 3, is_first=True)
        self.b3 = ResNetBlock(64, 128, 4)
        self.b4 = ResNetBlock(128, 256, 6)
        self.b5 = ResNetBlock(256, 512, 3)
        self.AvgPool = AvgPool2D(2)
        self.flatten = Flatten()
        self.Linear = Linear(512, num_classes)
        
    def forward(self, x):
        x = self.b1(x)
        x = self.b2(x)
        x = self.b3(x)
        x = self.b4(x)
        x = self.b5(x)
        x = self.AvgPool(x)
        x = self.flatten(x)
        x = self.Linear(x)
        return x
        
resnet = ResNet50(num_classes=10)
model = paddle.Model(resnet)
from paddle.static import InputSpec
input = InputSpec([None, 3, 96, 96], 'float32', 'image')
label = InputSpec([None, 1], 'int64', 'label')
model = paddle.Model(resnet, input, label)
model.summary()

訓(xùn)練代碼如下所示:

resnet = ResNet50(num_classes=10)
model = paddle.Model(resnet)
from paddle.static import InputSpec
input = InputSpec([None, 3, 96, 96], 'float32', 'image')
label = InputSpec([None, 1], 'int64', 'label')
model = paddle.Model(resnet, input, label)
model.summary()

# Compose: 以列表的方式組合數(shù)據(jù)集預(yù)處理功能
# Resize: 調(diào)整圖像大小
# Transpose: 調(diào)整通道順序, eg, HWC(img) -> CHW(NN)
# Normalize: 對圖像數(shù)據(jù)歸一化
# ToTensor: 將 PIL.Image 或 numpy.ndarray 轉(zhuǎn)換成 paddle.Tensor
# cifar10 手動計算均值和標(biāo)準(zhǔn)差:mean = [125.31, 122.95, 113.86] 和 std = [62.99, 62.08, 66.7] link:http://www.reibang.com/p/a3f3ffc3cac1

t = Compose([Resize(size=96), 
             Normalize(mean=[125.31, 122.95, 113.86], std=[62.99, 62.08, 66.7], data_format='HWC'), 
             Transpose(order=(2,0,1)), 
             ToTensor(data_format='HWC')])

train_dataset = Cifar10(mode='train', transform=t, backend='cv2') 
test_dataset  = Cifar10(mode='test', transform=t, backend='cv2')
BATCH_SIZE = 256
train_loader = paddle.io.DataLoader(train_dataset, shuffle=True, batch_size=BATCH_SIZE)
test_loader = paddle.io.DataLoader(test_dataset, batch_size=BATCH_SIZE)
# 為模型訓(xùn)練做準(zhǔn)備岸啡,設(shè)置優(yōu)化器原叮,損失函數(shù)和精度計算方式
learning_rate = 0.001
loss_fn = paddle.nn.CrossEntropyLoss()
opt = paddle.optimizer.Adam(learning_rate=learning_rate, parameters=model.parameters())
model.prepare(optimizer=opt, loss=loss_fn, metrics=paddle.metric.Accuracy())

# 啟動模型訓(xùn)練,指定訓(xùn)練數(shù)據(jù)集巡蘸,設(shè)置訓(xùn)練輪次奋隶,設(shè)置每次數(shù)據(jù)集計算的批次大小,設(shè)置日志格式
model.fit(train_loader, test_loader, batch_size=256, epochs=20, eval_freq= 5, verbose=1)
model.evaluate(test_loader, verbose=1)

訓(xùn)練結(jié)果:測試數(shù)據(jù)集上的精度在:80%左右

Epoch 20/20
step 196/196 [==============================] - loss: 0.0529 - acc: 0.9840 - 318ms/step
Eval begin...
The loss value printed in the log is the current batch, and the metric is the average value of previous step.
step 40/40 [==============================] - loss: 0.1676 - acc: 0.7816 - 198ms/step

在PaddlePaddle中ResNet網(wǎng)絡(luò)還有一種實現(xiàn)方式悦荒,即直接用PaddlePaddle自帶的ResNet類唯欣,范例代碼如下所示:

from paddle.vision.models import ResNet   
from paddle.vision.models.resnet import BottleneckBlock     
# resnet = ResNet50(num_classes=10)
resnet = ResNet(BottleneckBlock, 50, num_classes=10)
model = paddle.Model(resnet)
from paddle.static import InputSpec
input = InputSpec([None, 3, 96, 96], 'float32', 'image')
label = InputSpec([None, 1], 'int64', 'label')
model = paddle.Model(resnet, input, label)
model.summary()

運行結(jié)果:

Epoch 20/20
step 196/196 [==============================] - loss: 0.0661 - acc: 0.9743 - 467ms/step
Eval begin...
The loss value printed in the log is the current batch, and the metric is the average value of previous step.
step 40/40 [==============================] - loss: 0.7514 - acc: 0.7846 - 235ms/step

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市搬味,隨后出現(xiàn)的幾起案子境氢,更是在濱河造成了極大的恐慌,老刑警劉巖碰纬,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件萍聊,死亡現(xiàn)場離奇詭異,居然都是意外死亡悦析,警方通過查閱死者的電腦和手機寿桨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來强戴,“玉大人亭螟,你說我怎么就攤上這事挡鞍。” “怎么了预烙?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵墨微,是天一觀的道長。 經(jīng)常有香客問我扁掸,道長翘县,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任也糊,我火速辦了婚禮炼蹦,結(jié)果婚禮上羡宙,老公的妹妹穿的比我還像新娘狸剃。我一直安慰自己,他們只是感情好狗热,可當(dāng)我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布钞馁。 她就那樣靜靜地躺著,像睡著了一般匿刮。 火紅的嫁衣襯著肌膚如雪僧凰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天熟丸,我揣著相機與錄音训措,去河邊找鬼。 笑死光羞,一個胖子當(dāng)著我的面吹牛绩鸣,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播纱兑,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼呀闻,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了潜慎?” 一聲冷哼從身側(cè)響起捡多,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎铐炫,沒想到半個月后垒手,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡倒信,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年淫奔,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片堤结。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡唆迁,死狀恐怖鸭丛,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情唐责,我是刑警寧澤鳞溉,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站鼠哥,受9級特大地震影響熟菲,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜朴恳,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一抄罕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧于颖,春花似錦呆贿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至同衣,卻和暖如春竟块,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背耐齐。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工浪秘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人埠况。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓耸携,卻偏偏與公主長得像,于是被迫代替她去往敵國和親询枚。 傳聞我的和親對象是個殘疾皇子违帆,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,047評論 2 355

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