日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

理解ResNet结构与TensorFlow代码分析

發(fā)布時間:2025/3/15 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 理解ResNet结构与TensorFlow代码分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

該博客主要以TensorFlow提供的ResNet代碼為主,但是我并不想把它稱之為代碼解析,因為代碼和方法,實踐和理論總是缺一不可。?
github地址,其中:

resnet_model.py為殘差網(wǎng)絡(luò)模型的實現(xiàn),包括殘差模塊,正則化,批次歸一化,優(yōu)化策略等等;

resnet_main.py為主函數(shù),主要定義了測試、訓(xùn)練、總結(jié)、打印的代碼和一些參數(shù)。

cifar_input.py為數(shù)據(jù)準(zhǔn)備函數(shù),主要把cifar提供的bin數(shù)據(jù)解碼為圖片tensor,并組合batch

為了保證行號的一致性,下面的內(nèi)容如果涉及到行號的話,均以github上的為準(zhǔn),同時為了節(jié)省篇幅,下面如果出現(xiàn)代碼將去掉注釋,建議在閱讀本博客是同時打開github網(wǎng)址,因為下面的內(nèi)容并沒有多少代碼。

既然是在說殘差模型,那么當(dāng)然就要說resnet_model.py這個代碼,整個代碼就是在聲明一個類——ResNet:

第38行到55行:

class ResNet(object):def __init__(self, hps, images, labels, mode):self.hps = hpsself._images = imagesself.labels = labelsself.mode = modeself._extra_train_ops = []
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

上面是構(gòu)造函數(shù)在初始化對象時的四個參數(shù),實例化對象時也就完成初始化,參數(shù)賦值給類中的數(shù)據(jù)成員,其中self._images為私有成員。此外又定義了一個新的私有數(shù)組成員:self._extra_train_ops用來執(zhí)行滑動平均操作。

構(gòu)造函數(shù)的參數(shù)有hps,images,labels,mode。

hps在resnet_main.py在初始化的:

hps = resnet_model.HParams(batch_size=batch_size,num_classes=num_classes,min_lrn_rate=0.0001,lrn_rate=0.1,num_residual_units=5,use_bottleneck=False,weight_decay_rate=0.0002,relu_leakiness=0.1,optimizer='mom')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

其中的HParams字典在resnet_mode.py的32行定義,變量的意義分別是:

HParams = namedtuple('HParams','一個batch內(nèi)的圖片個數(shù)', '分類任務(wù)數(shù)目', '最小的學(xué)習(xí)率', '學(xué)習(xí)率', '一個殘差組內(nèi)殘差單元數(shù)量', '是否使用bottleneck', 'relu泄漏','優(yōu)化策略')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

images和labels是cifar_input返回回來的值(115行),注意這里的值已經(jīng)是batch了,畢竟image和label都加了復(fù)數(shù)。?
mode決定是訓(xùn)練還是測試,它在resnet_main.py中定義(29行)并初始化(206行)。

除了__init__的構(gòu)造函數(shù)外,類下還定義了12個函數(shù),把殘差模型構(gòu)建中用到功能模塊化了,12個函數(shù)貌似很多的樣子,但是都是一些很簡單的功能,甚至有一些只有一行代碼(比如可以看下65行),之所有單拉出來是因為功能是獨立的,或者反復(fù)出現(xiàn),TensorFlow提供的代碼還是非常規(guī)范和正規(guī)的!

按照自上而下的順序依次是:

build_graph(self):?
構(gòu)建TensorFlow的graph

_stride_arr(self, stride):?
定義卷積操作中的步長

_build_model(self):?
構(gòu)建殘差模型

_build_train_op(self):?
構(gòu)建訓(xùn)練優(yōu)化策略

_batch_norm(self, name, x):?
批次歸一化操作

_residual(self, x, in_filter, out_filter, stride,activate_before_residual=False):?
不帶bottleneck的殘差模塊,或者也可以叫做殘差單元,總之注意不是殘差組

_bottleneck_residual(self, x, in_filter, out_filter, stride,activate_before_residual=False):?
帶bottleneck的殘差模塊

decay(self):?
L2正則化

_conv(self, name, x, filter_size, in_filters, out_filters, strides):?
卷積操作

_relu(self, x, leakiness=0.0):?
激活操作

_fully_connected(self, x, out_dim):?
全鏈接

_global_avg_pool(self, x, out_dim):?
全局池化

注意:?
1.在代碼里這12個函數(shù)是并列的,但是講道理的話它們并不平級(有一些函數(shù)在調(diào)用另一些)。比如卷積,激活,步長設(shè)置之類肯定是被調(diào)用的。而有三個函數(shù)比較重要,分別是:build_graph(self):、_build_model(self):、_build_train_op(self):。第一個是由于TensorFlow就是在維護一張圖,所有的數(shù)據(jù)以tensor的形式在圖上流動;第二個決定了殘差模型;第三個決定了優(yōu)化策略。

2.個人認為_stride_arr(self, stride):函數(shù)不應(yīng)該出現(xiàn)在該位置(65行),如果把它放后面,前三個函數(shù)就分別是構(gòu)件圖,構(gòu)建模型,構(gòu)建優(yōu)化策略。這樣邏輯上就很清晰。

3.這套代碼沒有常規(guī)的池化操作,一方面是因為RenNet本身就用步長為2的卷積取代池化,但是在進入殘差組之前還是應(yīng)該有一個常規(guī)池化的,只是這個代碼沒有。

4.這個代碼有一個很不講理的地方,第一層卷積用了3*3的核,不是7*7,也不是3個3*3(73行)

5.這套代碼使用的是bin封裝的cifar數(shù)據(jù),所以要想改成自己的數(shù)據(jù)集需要把input的部分換掉。

6.這套代碼沒有設(shè)終止條件,會一直訓(xùn)練/測試,直到手動停止。

到這里代碼的結(jié)構(gòu)起碼說清楚了,帶著上面的注意事項,我們就可以看代碼。?
圖構(gòu)建沒什么好說的,我們直接進入_build_model(self)好了(69行):?
71-73行定義殘差網(wǎng)絡(luò)的第一個卷積層?
。?
75-82行使用哪種殘差單元(帶bottleneck還是不帶bottleneck),并分別對兩種情況定義了殘差組中的特征通道數(shù)。

90-109行構(gòu)建了三個殘差組,每個組內(nèi)有4個單元,這個數(shù)量是由hps參數(shù)決定的。

111-124行是殘差組結(jié)束后模型剩余的部分(池化+全連接+softmax+loss function+L2),這已經(jīng)和殘差網(wǎng)絡(luò)的特性沒什么關(guān)系了,每個卷積神經(jīng)網(wǎng)絡(luò)差不多都是這樣子。

126行將損失函數(shù)計算出的cost加入summary。

所以殘差模型最關(guān)鍵的東西,最能表征殘差特性的東西,都在90-109行,當(dāng)然這十幾行里是調(diào)用了其他函數(shù)的。這個本文的最后后再說,下面為保證代碼部分的連貫性,先往下說_build_train_op(self)(128行):

130-131行獲取學(xué)習(xí)率并加入到summary。

133-134行根據(jù)cost與權(quán)系數(shù)計算梯度。

136-136行選擇使用隨機梯度下降還是帶動量梯度下降。

141-143行執(zhí)行梯度下降優(yōu)化。

145行將梯度下降優(yōu)化操作與bn操作合并(帶op的變量是一種操作)。

146行得到最后的結(jié)果,在這里定義了一個新的數(shù)組成員:self.train_op,而這個變量最終被用到了resnet_main.py中(113行):

while not mon_sess.should_stop():mon_sess.run(model.train_op)
  • 1
  • 2

如果沒有達到終止條件的話,代碼將一直執(zhí)行優(yōu)化操作,model是類實例化出來的一個對象,在resnet_main.py中的model和在resnet_model.py中的self是一個東西。

到這里重要的代碼就都說完了,最后說回殘差網(wǎng)絡(luò)最核心的東西:兩種殘差單元。?
殘差網(wǎng)絡(luò)的結(jié)構(gòu)非常簡單,就是不斷的通過一組一組的殘差組鏈接,這是一個Resnet50的結(jié)構(gòu)圖,不同的網(wǎng)絡(luò)結(jié)構(gòu)在不同的組之間會有不同數(shù)目的殘差模塊,如下圖:?
?
舉個例子,比如resnet50中,2-5組中分別有3,4,6,3個殘差模塊。

樸素殘差模塊(不帶bottleneck):?
?
左側(cè)為正常了兩個卷積層,而右側(cè)在兩個卷積層前后做了直連,這個直連解釋殘差,左側(cè)的輸出為H(x)=F(x),而加入直連后的H(x)=F(x)+x,一個很簡單的改進,但是取得了非常優(yōu)異的效果。?
至于為什么直連要跨越兩個卷積層,而不是一個?這個是實驗驗證的結(jié)果,在一個卷積層上加直連性能并沒有太大提升。

bottleneck殘差模塊:?
bottleneck殘差模塊讓殘差網(wǎng)絡(luò)可以向更深的方向上走,原因就是因為同一通道數(shù)的情況下,bottleneck殘差模塊要比樸素殘差模塊節(jié)省大量的參數(shù),一個單元內(nèi)的參數(shù)少了,對應(yīng)的就可以做出更深的結(jié)構(gòu)。?
?
上面這樣圖能夠說明二者的區(qū)別,左側(cè)的通道數(shù)是64(它常出現(xiàn)在50層內(nèi)的殘差結(jié)構(gòu)中),右側(cè)的通道數(shù)是256(常出現(xiàn)在50層以上的殘差結(jié)構(gòu)中),從右面的圖可以看到,bottleneck殘差模塊將兩個3*3換成了1*1,3*3,1*1的形式,第一個1*1用來降通道,3*3用來在降通道的特征上卷積,第二個1*1用于升通道。而參數(shù)的減少就是因為在第一個1*1將通道數(shù)降了下來。我們可以舉一個例子驗證一下:

假設(shè)樸素殘差模塊與bottleneck殘差模塊通道數(shù)都是256,那么:

樸素殘差模塊的參數(shù)個數(shù):?
3*3*256*256+3*3*256*256 = 10616832?
bottleneck殘差模塊的參數(shù)個數(shù):?
1*1*256*64+3*3*64*64+1*1*64*256 = 69632?
可以看到,參數(shù)的減少非常明顯。

再回到上面的圖:?

Resnet34余Resnet50層每一組中的模塊個數(shù)并沒有變化,層數(shù)的上升是因為以前兩個卷積層變成了3個,前者的參數(shù)為3.6億,后者參數(shù)為3.8億。這樣來看的話參數(shù)為什么反而多了?這是因為組內(nèi)的通道數(shù)發(fā)生了變化,前者各組通道數(shù)為[64,128,256,512],而后者的各組通道數(shù)為[256,512,1024,2048]。這也是殘差網(wǎng)絡(luò)在設(shè)計時的一個特點,使用bottleneck殘差模塊時,組內(nèi)的通道數(shù)要明顯高于使用樸素殘差模塊。

TensorFlow提供的代碼也是這樣,可以看下77行:

if self.hps.use_bottleneck:res_func = self._bottleneck_residualfilters = [16, 64, 128, 256]else:res_func = self._residualfilters = [16, 16, 32, 64]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

通過上面的理論說明,就可以再回頭看下代碼中的:_residual()函數(shù)和_bottleneck_residual()函數(shù)了。

原文地址:http://blog.csdn.net/chaipp0607/article/details/75577305

總結(jié)

以上是生活随笔為你收集整理的理解ResNet结构与TensorFlow代码分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 免费古装一级淫片潘金莲 | 国产精品熟妇人妻g奶一区 a少妇 | 国产乱码精品一区二区三区精东 | 亚洲视频免费 | 午夜国产在线观看 | 国产欧美日韩在线播放 | 欧美日韩不卡在线 | 久久亚洲在线 | 国产精品亚洲第一 | 亚洲综合日韩精品欧美综合区 | 午夜精品久久久久久久久久 | 国产精品久久久国产盗摄 | 欧美变态口味重另类在线视频 | 日韩欧美中文字幕一区二区三区 | 四虎影院永久地址 | 国产精品99久久久久久久女警 | 午夜亚洲aⅴ无码高潮片苍井空 | 99色亚洲 | 视频二区在线观看 | 亚洲人成色777777精品音频 | 国产精品久久久av | 俄罗斯黄色录像 | 国产精品福利片 | 激情视频在线免费观看 | 熟妇熟女乱妇乱女网站 | 狠狠插狠狠操 | 超碰caopeng| 91色视频在线 | 亚洲视频在线观看网站 | 日韩有码第一页 | 伊伊成人 | 国产拍拍拍拍拍拍拍拍拍拍拍拍拍 | 草草屁屁影院 | 亚洲第一综合网 | 国产最新地址 | 亚洲区小说区图片区qvod | 校园春色亚洲色图 | 人妻少妇被猛烈进入中文字幕 | 欧美精品h| 日韩综合另类 | 老司机午夜免费精品视频 | 爱啪啪影视 | 冈本视频在线观看 | 日韩欧美视频在线 | 国产精品二 | 91视频国产精品 | 天天操狠狠操夜夜操 | 草莓视频一区二区三区 | av中文天堂在线 | www.狠狠艹 | 国产美女无遮挡免费 | 中文字幕欧美在线观看 | 综合九九 | 欧美日韩在线观看成人 | 精品一区二区人妻 | 香蕉视频网站入口 | 亚洲欧美另类日韩 | 日韩综合一区二区三区 | 99一区二区 | 福利视频91| 久久精国产 | 国产精品jizz在线观看老狼 | 成人免费视频一区二区 | 手机在线看黄色 | 性大毛片视频 | 成人在线一区二区三区 | 久久泄欲网 | 久久久久成人精品免费播放动漫 | 超碰人人干人人 | 中国精品毛片 | 男人插入女人阴道视频 | 欧美粗又大 | 麻豆av在线播放 | 天天碰天天摸 | 日韩美一级片 | www.欧美.com| 亚洲国产视频一区二区 | 牛牛精品一区二区 | 黄色三级三级 | 亚洲视频导航 | 国产在线视频不卡 | 国产人妻大战黑人20p | 精品www久久久久久奶水 | 伊人av一区 | 99热日本 | 91在线播放国产 | 精品视频站长推荐 | 台湾黄色网址 | 亚洲二区av | 国产毛片在线 | 国产视频综合 | 非洲黑寡妇性猛交视频 | 377p粉嫩大胆色噜噜噜 | 亚洲色图网址 | 中文字幕在线播放视频 | 日韩精品第二页 | 日本爽爽爽爽爽爽在线观看免 | 色天天综合 | 伊人宗合 |