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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

机器学习笔记:ResNet 及残差连接

發(fā)布時間:2025/4/5 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 机器学习笔记:ResNet 及残差连接 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1 為什么會有ResNet?

? ? ? ?自從深度神經(jīng)網(wǎng)絡(luò)在ImageNet大放異彩之后,后來問世的深度神經(jīng)網(wǎng)絡(luò)就朝著網(wǎng)絡(luò)層數(shù)越來越深的方向發(fā)展。直覺上我們不難得出結(jié)論:增加網(wǎng)絡(luò)深度后,網(wǎng)絡(luò)可以進(jìn)行更加復(fù)雜的特征提取,因此更深的模型可以取得更好的結(jié)果。

????????但事實(shí)并非如此,人們發(fā)現(xiàn)隨著網(wǎng)絡(luò)深度的增加,模型精度并不總是提升,并且這個問題顯然不是由過擬合(overfitting)造成的,因?yàn)榫W(wǎng)絡(luò)加深后不僅測試誤差變高了,它的訓(xùn)練誤差竟然也變高了。【注:過擬合應(yīng)該是訓(xùn)練誤差很小,但是測試誤差很大;這里訓(xùn)練誤差都很大,說明不是過擬合的問題】

????????這可能是因?yàn)?span style="color:#38d8f0;">更深的網(wǎng)絡(luò)會伴隨梯度消失/爆炸問題,從而阻礙網(wǎng)絡(luò)的收斂。這種加深網(wǎng)絡(luò)深度但網(wǎng)絡(luò)性能卻下降的現(xiàn)象被稱為退化問題(degradation problem)。

? ? ? ? 從上圖我們可以看出,當(dāng)傳統(tǒng)神經(jīng)網(wǎng)絡(luò)的層數(shù)從20增加為56時,網(wǎng)絡(luò)的訓(xùn)練誤差和測試誤差均出現(xiàn)了明顯的增長,也就是說,網(wǎng)絡(luò)的性能隨著深度的增加出現(xiàn)了明顯的退化。

????????ResNet就是為了解決這種退化問題而誕生的。

2 ResNet原理

????????隨著網(wǎng)絡(luò)層數(shù)的增加,梯度爆炸和梯度消失問題嚴(yán)重制約了神經(jīng)網(wǎng)絡(luò)的性能,研究人員通過提出包括Batch normalization在內(nèi)的方法,已經(jīng)在一定程度上緩解了這個問題,但依然不足以滿足需求。

2.1?恒等映射(Identity mapping)

? ? ? ? ResNet提出了使用恒等映射(Identity mapping)來解決這個問題。

????????問題解決的標(biāo)志是:增加網(wǎng)絡(luò)層數(shù),但訓(xùn)練誤差不增加。

????????那怎么構(gòu)建恒等映射呢?

????????簡單地說,原先的網(wǎng)絡(luò)輸入x,希望輸出H(x)。

????????現(xiàn)在我們改一改,我們令H(x)=F(x)+x,那么我們的網(wǎng)絡(luò)就只需要學(xué)習(xí)輸出一個殘差F(x)=H(x)-x。

? ? ? ? ResNet作者提出,學(xué)習(xí)殘差F(x)=H(x)-x會比直接學(xué)習(xí)原始特征H(x)簡單的多。

2.2 skip connection?

?

?3 ResNet(各變體)網(wǎng)絡(luò)結(jié)構(gòu)

????????ResNet有很多變體,比較著名的有五種主要形式:Res18,Res34,Res50,Res101,Res152。

????????

? ? ? ? 如上圖所示,ResNet及其變體主要包括三個主要部分:輸入部分(input)+中間卷積(stage1~stage4)+輸出部分(output)

3.1 網(wǎng)絡(luò)整體結(jié)構(gòu)

? ? ? ? 以ResNet18為例:?

class ResNet(nn.Module):def forward(self, x):x = self.conv1(x)x = self.bn1(x)x = self.relu(x)x = self.maxpool(x)#輸入部分x = self.layer1(x)x = self.layer2(x)x = self.layer3(x)x = self.layer4(x)#卷積部分#ResNet18和其他的ResNet網(wǎng)絡(luò)的區(qū)別主要就在這四層里面x = self.avgpool(x)x = x.view(x.size(0), -1)x = self.fc(x)#輸出部分return x# 生成一個res18網(wǎng)絡(luò)(看是否有預(yù)訓(xùn)練的參數(shù)) def resnet18(pretrained=False, **kwargs):model = ResNet(BasicBlock, [2, 2, 2, 2], **kwargs)if pretrained:model.load_state_dict(model_zoo.load_url(model_urls['resnet18']))return model

?3.2 網(wǎng)絡(luò)輸入部分

self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False) ''' size=7*7,stride=2的卷積核 '''self.bn1 = nn.BatchNorm2d(64)self.relu = nn.ReLU(inplace=True)self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1 ''' size=3x3, stride=2的最大池化 ''')

在pytorch 筆記:torch.nn.Conv2d_UQI-LIUWJ的博客-CSDN博客、pytorch筆記:torch.nn.MaxPool2d_UQI-LIUWJ的博客-CSDN博客中,我們說到,經(jīng)過Conv2d和MaxPool2d之后的channel數(shù)為:

????????在ResNet中,輸入部分是一個224x224的圖像,經(jīng)過輸入部分之后,變成了56x56大小的特征圖,極大減少了存儲所需大小。

?

3.3 中間卷積部分

????????中間卷積部分主要是下圖中的藍(lán)框部分,通過3*3卷積的堆疊來實(shí)現(xiàn)信息的提取。紅框中的[2, 2, 2, 2]和[3, 4, 6, 3]等則代表了bolck的重復(fù)堆疊次數(shù)。?

——>每一層卷積層:減一半feature map的長和寬,增加輸出channel一倍

——>第一個卷積層(conv1——,又被稱為”stem“)

? ? ? ? ?紅框前面的是卷積核的大小,以及輸出的channel數(shù)

????????剛剛我們調(diào)用的resnet18( )函數(shù)中有一句

model = ResNet(BasicBlock, [2, 2, 2, 2], **kwargs)

????????這里的[2, 2, 2, 2]與圖中紅框是一致的,如果你將這行代碼改為 ResNet(BasicBlock, [3, 4, 6, 3], **kwargs), 那你就會得到一個res34網(wǎng)絡(luò)。

3.4? 殘差塊

? ? ? ??下面我們來具體看一下一個殘差塊是怎么實(shí)現(xiàn)的。

????????如下圖所示的basic-block,輸入數(shù)據(jù)分成兩條路,一條路經(jīng)過兩個3*3卷積,另一條路直接短接,二者相加經(jīng)過relu輸出,十分簡單。

class BasicBlock(nn.Module):expansion = 1def __init__(self, inplanes, planes, stride=1, downsample=None):super(BasicBlock, self).__init__()self.conv1 = conv3x3(inplanes, planes, stride)self.bn1 = nn.BatchNorm2d(planes)self.relu = nn.ReLU(inplace=True)self.conv2 = conv3x3(planes, planes)self.bn2 = nn.BatchNorm2d(planes)self.downsample = downsampleself.stride = stridedef forward(self, x):identity = xout = 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 += identityout = self.relu(out)return out

?3.5 輸出部分

?????????網(wǎng)絡(luò)輸出部分很簡單,通過全局自適應(yīng)平滑池化,把所有的特征圖拉成1*1。

????????對于res18來說,就是1x512x7x7 的輸入數(shù)據(jù)拉成 1x512x1x1,然后接全連接層輸出,輸出節(jié)點(diǎn)個數(shù)與預(yù)測類別個數(shù)一致。

self.avgpool = nn.AdaptiveAvgPool2d((1, 1))self.fc = nn.Linear(512 * block.expansion, num_classes)

4 bottleneck 結(jié)構(gòu)?

????????ResNet50起,就采用Bottleneck結(jié)構(gòu),主要是引入1x1卷積。

????????我們來看一下這里的1x1卷積有什么作用:

  • 對通道數(shù)進(jìn)行升維和降維(跨通道信息整合),實(shí)現(xiàn)了多個特征圖的線性組合,同時保持了原有的特征圖大小;
  • 相比于其他尺寸的卷積核,可以極大地降低運(yùn)算復(fù)雜度;
  • 如果使用兩個3x3卷積堆疊,只有一個relu,但使用1x1卷積就會有兩個relu,引入了更多的非線性映射;

?

????????我們來計算一下1*1卷積的計算量優(yōu)勢:首先看上圖右邊的bottleneck結(jié)構(gòu),對于256維的輸入特征,參數(shù)數(shù)目:1x1x256x64+3x3x64x64+1x1x64x256=69632.

????????如果同樣的輸入輸出維度但不使用1x1卷積,而使用兩個3x3卷積的話,參數(shù)數(shù)目為(3x3x256x256)x2=1179648。

????????簡單計算下就知道了,使用了1x1卷積的bottleneck將計算量簡化為原有的5.9%,收益超高。

?參考文獻(xiàn):ResNet及其變種的結(jié)構(gòu)梳理、有效性分析與代碼解讀 - 知乎 (zhihu.com)

5 Batch-normalization和Relu,孰先孰后?

這個不確定,這里說一下ResNet中先BN再Relu的優(yōu)點(diǎn)吧

先BN的話,會有一半左右的輸出小于0,那么經(jīng)過Relu之后的結(jié)果就是0,網(wǎng)絡(luò)可以剪掉很多枝

總結(jié)

以上是生活随笔為你收集整理的机器学习笔记:ResNet 及残差连接的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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