再送されたコードの詳細な説明

resnetで最も重要なことは、コードの残余ブロックです。

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
        out += identity
        out = self.relu(out)
        return out

残りのブロック構造:

左側のものはBasicBlockと呼ばれ、右側のものはボトルネックと呼ばれます

BasicBlock

class BasicBlock(nn.Module):
    expansion =1
    def __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 = 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
        out += identity
        out = self.relu(out)
        return out

 

ボトルネック

Res18とRes34はBasicBlockを使用し、残りはボトルネックを使用することに注意してください

resnet18:ResNet(BasicBlock、[2、2、2、2])

resnet34:ResNet(BasicBlock、[3、4、6、3])

resnet50:ResNet(ボトルネック、[3、4、6、3])

resnet101:ResNet(Bottleneck、[3、4、23、3])

resnet152:ResNet(Bottleneck、[3、8、36、3])

ボトルネックの各残差構造の出力次元は入力次元の4倍であるため、展開= 4

クラスBottleneck(nn.Module):
    拡張= 4

    def __init __(self、inplanes、planes、stride = 1、downsample = None):
        super(Bottleneck、self).__ init __()
        self.conv1 = conv1x1(inplanes、planes)
        self.bn1 = nn.BatchNorm2d(planes)
        self。 conv2 = conv3x3(planes、planes、stride)
        self.bn2 = nn.BatchNorm2d(planes)
        self.conv3 = conv1x1(planes、planes * self.expansion)
        self.bn3 = nn.BatchNorm2d(planes * self.expansion)
        self。 relu = nn.ReLU(inplace = True)
        self.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)

        self.downsampleがNoneでない場合:
            identity = self.downsample(x)

        out + =アイデンティティ
        out = self.relu(out)

        戻る

 

ResNetクラス

いくつかの重要なポイント:

1.残差構造の前に、最初に元の224 x 224画像を処理し、7 x 7の大きな畳み込みカーネル、BN、ReLU、および最大プーリングの後に56 x 56 x64の特徴マップを取得します
。 layer2、layer3、layer4は、最初のステージが特徴マップを縮小せず、残りはステージの最初のレイヤーでステップ2の3 x 3畳み込みを使用して、特徴マップの長さと幅を縮小することがわかります。半分に
、ダウンサンプリングアップグレード残留構造、直接に1×1の畳み込みプラスBN、次いでBasicBlockクラスとボトルネック・クラスの入力._make_layer機能3.得るために使用される
前記最後のプーリング層は、適応平均値を使用し論文のグローバル平均プーリングの代わりにプール

クラスResNet(nn.Module):

    def __init __(self、block、layers、num_classes = 1000、zero_init_residual = False):
        super(ResNet、self).__ init __()
        self.inplanes = 64
        self.conv1 = nn.Conv2d(3、64、kernel_size = 7、stride = 2、パディング= 3、
                               バイアス= False)
        self.bn1 = nn.BatchNorm2d(64)
        self.relu = nn.ReLU(inplace = True)
        self.maxpool = nn.MaxPool2d(kernel_size = 3、stride = 2、パディング= 1)
        self.layer1 = self._make_layer(block、64、layers [0])
        self.layer2 = self._make_layer(block、128、layers [1]、stride = 2)
        self.layer3 = self._make_layer(block 、256、layers [2]、stride = 2)
        self.layer4 = self._make_layer(block、512、layers [3]、stride = 2)
        self.avgpool = nn.AdaptiveAvgPool2d((1、1))
        self.fc = nn.Linear(512 * block.expansion、num_classes)

    デフ_make_layer(自己、ブロック、プレーン、ブロック、ストライド= 1):
        ダウンサンプリング=なし
        の場合ストライド= 1またはself.inplanes =プレーン* block.expansion!:
            ダウンサンプリング= nn.Sequential(
                conv1x1(self.inplanes、プレーン* block.expansion、stride)、
                nn.BatchNorm2d(planes * block.expansion)、
            )

        layers = []
        layers.append(block(self.inplanes、planes、stride、
        downsample ))self.inplanes = planes * block.expansion
        for _ in range(1、blocks):
            layers.append(block(self.inplanes、飛行機))

        nn.Sequential(* layers)を返します

    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)

        x = self.avgpool(x)
        x = x.view(x.size(0)、-1)
        x = self.fc(x)

        xを返す

おすすめ

転載: blog.csdn.net/qq_16792139/article/details/114314100