「ディープラーニングノート」CNNネットワーク設計における絶妙で普遍的な「小さな」プラグイン


序文

  • いわゆる「プラグイン」とは、ケーキの上のアイシングであり、移植と着陸が簡単である、つまり真のプラグアンドプレイである可能性があることを意味します。この記事でレビューする「プラグイン」は、多くのSOTAネットワークで見られる、CNN変換、回転、スケールおよびその他の縮退機能、またはマルチスケール特徴抽出、受容野およびその他の機能を改善できます。
  • いわゆる「プラグイン」とは、ネットワークの主要な構造を変更せずに、主流のネットワークに簡単に組み込むことができ、ネットワークの特徴抽出能力を向上させ、プラグアンドプレイできることを意味します。

1. STN(スペーストランスフォーマー)

ここに画像の説明を挿入

1.1コア分析

  • OCRなどのタスクでよく見られます。CNNネットワークの場合、オブジェクトの姿勢と位置に一定の不変性があることを期待しています。つまり、テストセットの特定の姿勢と位置の変化に適応できます。不変性または同変は、モデルの一般化能力を効果的に向上させることができます。CNNはスライディングウィンドウ畳み込み演算を使用しますが、ある程度の並進不変性があります。ただし、多くの研究では、ダウンサンプリングによってネットワークの並進不変性が破壊されることがわかっています。したがって、回転、スケール、照明の不変性は言うまでもなく、ネットワークの不変性能力は非常に弱いと考えることができます。一般に、ネットワークの「不変性」を実現するためにデータ拡張を使用します。
  • このホワイトペーパーでは、STNモジュールを提案します。このモジュールは、空間変換をネットワークに明示的に組み込み、それによってネットワークの回転、平行移動、およびスケールの不変性を改善します。「アライメント」操作として理解することができます。STNの構造を上図に示します。各STNモジュールは、ローカリゼーションネット(ローカルネットワーク)、グリッドジェネレーター、サンプラーの3つの部分で構成されています。
  1. Localisation net 空間変換を取得するための学習に使用されるパラメーターは、上記の式の6つのパラメーターです。
  2. Grid generator 座標マッピングに使用されます。
  3. Sampler ピクセルの収集は、双一次補間によって実行されます。

1.2コアコード

class SpatialTransformer(nn.Module):
    def __init__(self, spatial_dims):
        super(SpatialTransformer, self).__init__()
        self._h, self._w = spatial_dims 
        self.fc1 = nn.Linear(32*4*4, 1024) # 可根据自己的网络参数具体设置
        self.fc2 = nn.Linear(1024, 6)

    def forward(self, x): 
        batch_images = x #保存一份原始数据
        x = x.view(-1, 32*4*4)
        # 利用 FC 结构学习到 6 个参数
        x = self.fc1(x)
        x = self.fc2(x) 
        x = x.view(-1, 2,3) # 2x3
        # 利用 affine_grid 生成采样点
        affine_grid_points = F.affine_grid(x, torch.Size((x.size(0), self._in_ch, self._h, self._w)))
        # 将采样点作用到原始数据上
        rois = F.grid_sample(batch_images, affine_grid_points)
        return rois, affine_grid_points

2、ASPP

ここに画像の説明を挿入

2.1コア分析

  • このプラグインは、ホールコンボリューションを備えた空間ピラミッドプーリングモジュールであり、主にネットワークの受容野を改善し、マルチスケール情報を導入するために提案されています。セマンティックセグメンテーションネットワークの場合、通常、より大きな解像度の画像に直面することがわかっています。そのため、ネットワークには、ターゲットオブジェクトをカバーするのに十分な受容野が必要です。CNNネットワークの場合、受容野は基本的に畳み込み層を積み重ねてダウンサンプリングすることで得られます。この記事のモジュールは、特徴マップのサイズを変更せずに受容野を制御できます。これは、マルチスケール情報の抽出に役立ちます。その中で、レートは受容野のサイズを制御し、rが大きいほど受容野は大きくなります。
  • ASPPには、主に次の部分が含まれています。
  1. グローバル平均プーリングレイヤーは、画像レベルの特徴を取得し、1X1畳み込みを実行し、元のサイズに双線形補間します。
  2. 1つの1X1畳み込み層と3つの3X3中空畳み込み。
  3. 異なるスケールの5つの機能は、チャネル次元で連結され、フュージョン出力のために1X1コンボリューションに送信されます。

2.2コアコード

class ASPP(nn.Module):
    def __init__(self, in_channel=512, depth=256):
        super(ASPP,self).__init__()
        self.mean = nn.AdaptiveAvgPool2d((1, 1))
        self.conv = nn.Conv2d(in_channel, depth, 1, 1)
        self.atrous_block1 = nn.Conv2d(in_channel, depth, 1, 1)
        # 不同空洞率的卷积
        self.atrous_block6 = nn.Conv2d(in_channel, depth, 3, 1, padding=6, dilation=6)
        self.atrous_block12 = nn.Conv2d(in_channel, depth, 3, 1, padding=12, dilation=12)
        self.atrous_block18 = nn.Conv2d(in_channel, depth, 3, 1, padding=18, dilation=18)
        self.conv_1x1_output = nn.Conv2d(depth * 5, depth, 1, 1)

    def forward(self, x):
        size = x.shape[2:]
     	# 池化分支
        image_features = self.mean(x)
        image_features = self.conv(image_features)
        image_features = F.upsample(image_features, size=size, mode='bilinear')
     	# 不同空洞率的卷积
        atrous_block1 = self.atrous_block1(x)
        atrous_block6 = self.atrous_block6(x)
        atrous_block12 = self.atrous_block12(x)
        atrous_block18 = self.atrous_block18(x)
        # 汇合所有尺度的特征
     	x = torch.cat([image_features, atrous_block1, atrous_block6,atrous_block12, atrous_block18], dim=1)
        # 利用1X1卷积融合特征输出
        x = self.conv_1x1_output(x)
        return net

三、非ローカル

ここに画像の説明を挿入

3.1コア分析

Non-Localは、注意メカニズムであり、移植と統合が容易なモジュールです。ローカルは主に受容野用です。CNNの畳み込み演算とプーリング演算を例にとると、その受容野サイズは畳み込みカーネルのサイズであり、スタッキングに3X3畳み込み層を使用することがよくあります。ローカル領域のみを考慮します。これはすべてローカル操作です。違いは、非ローカル操作の受容野が非常に大きくなる可能性があり、ローカルエリアではなくグローバルエリアになる可能性があることです。長距離の依存関係、つまり、画像上で特定の距離にある2つのピクセル間の接続を確立する方法をキャプチャすることは、一種の注意メカニズムです。いわゆる注意メカニズムはネットワークによって生成され、saliency map注意はネットワークが焦点を合わせる必要がある領域である顕著性領域に対応します。

特定の実装手順:

  • まず、入力フィーチャマップで1X1畳み込みを実行してチャネル数を圧縮し、θ、ϕ、g \ theta、\ phi、gを取得します。θ ϕ g機能。
  • 形状変更操作により、3つの特徴の次元が変換され、次に行列乗算操作が実行されて、同様の共分散行列が取得されます。このステップでは、特徴の自己相関を計算します。つまり、各フレームの各ピクセルを取得します。および他のすべてのフレームのすべてのピクセル関係。
  • 次に、自己相関機能でSoftmax操作を実行して、0〜1の重みを取得します。これが、必要な自己注意係数です。
  • 最後に、注意係数が対応して乗算されて特徴行列gに戻り、元の入力特徴マップXの残余が出力に追加されます。

3.2コアコード

class NonLocal(nn.Module):
    def __init__(self, channel):
        super(NonLocalBlock, self).__init__()
        self.inter_channel = channel // 2
        self.conv_phi = nn.Conv2d(channel, self.inter_channel, 1, 1,0, False)
        self.conv_theta = nn.Conv2d(channel, self.inter_channel, 1, 1,0, False)
        self.conv_g = nn.Conv2d(channel, self.inter_channel, 1, 1, 0, False)
        self.softmax = nn.Softmax(dim=1)
        self.conv_mask = nn.Conv2d(self.inter_channel, channel, 1, 1, 0, False)

    def forward(self, x):
        # [N, C, H , W]
        b, c, h, w = x.size()
        # 获取phi特征,维度为[N, C/2, H * W],注意是要保留batch和通道维度的,是在HW上进行的
        x_phi = self.conv_phi(x).view(b, c, -1)
        # 获取theta特征,维度为[N, H * W, C/2]
        x_theta = self.conv_theta(x).view(b, c, -1).permute(0, 2, 1).contiguous()
        # 获取g特征,维度为[N, H * W, C/2]
        x_g = self.conv_g(x).view(b, c, -1).permute(0, 2, 1).contiguous()
        # 对phi和theta进行矩阵乘,[N, H * W, H * W]
        mul_theta_phi = torch.matmul(x_theta, x_phi)
        # softmax拉到0~1之间
        mul_theta_phi = self.softmax(mul_theta_phi)
        # 与g特征进行矩阵乘运算,[N, H * W, C/2]
        mul_theta_phi_g = torch.matmul(mul_theta_phi, x_g)
        # [N, C/2, H, W]
        mul_theta_phi_g = mul_theta_phi_g.permute(0, 2, 1).contiguous().view(b, self.inter_channel, h, w)
        # 1X1卷积扩充通道数
        mask = self.conv_mask(mul_theta_phi_g)
        out = mask + x # 残差连接
        return out

四、SE

ここに画像の説明を挿入

4.1コア分析

この記事は、ImageNetの最後のコンテストのチャンピオン作品です。たとえば、多くの古典的なネットワーク構造で見られますMobilenet v3これは実際にはチャネル注意メカニズムです。機能の圧縮とFCにより、キャプチャされたチャネルアテンション機能にはグローバル情報が含まれます。この論文では、“Squeeze-and Excitation(SE)”各チャネルの特性応答値を適応的に調整し、チャネル間の内部依存性をモデル化できる新しい構造ユニットモジュールを提案します。

いくつかのステップがあります:

  • スクイーズ:空間次元に沿ってフィーチャ圧縮を実行し、各2次元フィーチャチャネルをグローバルな受容野を持つ数値に変換します。
  • 興奮:各機能チャネルは、機能チャネルの重要性を表す重みを生成します。
  • 再重み付け:励起出力の重みを各機能チャネルの重要性と見なし、乗算によって各チャネルに作用します。

4.2コアコード

class SE_Block(nn.Module):
    def __init__(self, ch_in, reduction=16):
        super(SE_Block, self).__init__()
        self.avg_pool = nn.AdaptiveAvgPool2d(1)  # 全局自适应池化
        self.fc = nn.Sequential(
            nn.Linear(ch_in, ch_in // reduction, bias=False),
            nn.ReLU(inplace=True),
            nn.Linear(ch_in // reduction, ch_in, bias=False),
            nn.Sigmoid()
        )

    def forward(self, x):
        b, c, _, _ = x.size()
        y = self.avg_pool(x).view(b, c) # squeeze操作
        y = self.fc(y).view(b, c, 1, 1) # FC获取通道注意力权重,是具有全局信息的
        return x * y.expand_as(x) # 注意力作用每一个通道上

ファイブ、CBAM

5.1コア分析

  • SENetは、特徴マップのチャネルで注意の重みを取得し、それを元の特徴マップと乗算します。この記事では、この注意方法は、チャネルレベルのどのレイヤーがより強力なフィードバック機能を持つかにのみ焦点を当てており、空間次元での注意を反映していないことを指摘しています。
  • この記事のハイライトとして、CBAMはチャネル次元と空間次元の両方に注意を払います。SEモジュールと同様に、CBAMはほとんどの主流ネットワークに組み込むことができ、計算やパラメーターの量を大幅に増やすことなくモデルを改善できます。特徴抽出機能。

チャネルの注意:上記のとおり

  1. まず、入力はH×W×C特徴Fです。2つの1×1×Cを取得するための2つの空間チャネルの各プールとグローバル平均最大プールに入れて説明します。
  2. 次に、それらを2層ニューラルネットワークに送信します。第1層のニューロンの数はC / r、活性化関数はRelu、第2層のニューロンの数はCです。この2層ニューラルネットワークは共有されていることに注意してください。
  3. 次に、得られた2つの特徴が加算され、シグモイド活性化関数に渡されて、重み係数Mcが取得されます。
  4. 最後に、重み係数と元の特徴Fを乗算して、スケーリング後に新しい特徴を取得します。

偽のコード:

def forward(self, x):
    # 利用FC获取全局信息,和Non-local的矩阵相乘本质上式一样的
    avg_out = self.fc2(self.relu1(self.fc1(self.avg_pool(x))))
    max_out = self.fc2(self.relu1(self.fc1(self.max_pool(x))))
    out = avg_out + max_out
    return self.sigmoid(out)

空間的注意:

  • チャネルアテンションと同様に、H×W×Cの機能F 'が与えられた場合、最初にチャネル次元の平均プーリングと最大プーリングを実行して2つのH×W×1チャネル記述を取得し、これら2つを組み合わせます。記述はスプライスされます。チャネルに従って一緒に。次に、7×7畳み込み層の後、活性化関数はシグモイドであり、重み係数Msが取得されます。最後に、重み係数と特徴F 'を乗算して、スケーリング後に新しい特徴を取得します。

偽のコード:

def forward(self, x):
    # 这里利用池化获取全局信息
    avg_out = torch.mean(x, dim=1, keepdim=True)
    max_out, _ = torch.max(x, dim=1, keepdim=True)
    x = torch.cat([avg_out, max_out], dim=1)
    x = self.conv1(x)
    return self.sigmoid(x)

待补全调整...

参照リンク

  1. https://mp.weixin.qq.com/s/glQSmbuvRI6CV8EyfYLezw

おすすめ

転載: blog.csdn.net/libo1004/article/details/112793383