[7]は、ゼロから学ぶYOLOv3。注意メカニズムYOLOv3モデルを追加するように教えます

はじめに:YOLOv3書き込みを学ぶ最初から[シリーズ]はので、このシリーズに追加し続ける、より多くの、コンテンツが比較的小さく予定されていたが、コードを読み取る過程でゆっくりといくつかの新しい明るいスポットを発見します。YOLOv3にコードを読む前に、私たちは、cfgファイル、モデルの構築とその上を学びました。本明細書で前に、モデルコードに基づいて、以前のシリーズ注意SEモジュールとYOLOv3にモジュールCBAM修正されます。

1.所定のフォーマット

同じように[convolutional][maxpool][net][route]あなたが規定CFG形式で見たいときCFGで定義されており、他の層には、我々は新しいモジュールを追加します。以下の規定を行います。

(詳細を参照に説明:SEモジュールを[注意機構におけるCV]最も単純で最も容易に実現SEモジュール)、パラメータが存在しreduction、このモジュールで詳細なパラメータは、我々は次のように従うように、パラメータのデフォルト値は、16であります設定:

[se]
reduction=16

CBAMモジュールにおいて(詳細を参照に説明する:【注意】機構2018畳み込みブロック注意モジュールECCVにおけるCV)、空間的注意機構とは、2つのパラメータの合計の存在下で注目メカニズム通路ratiokernel_sizeCFGファイルにそのような要件CBAMをそれほどフォーマット:

[cbam]
ratio=16
kernelsize=7

分析の部分を変更します。2.

我々は、我々は変更する必要がある前の話、あなたが機能を解析するのcfgファイルを変更する必要があるので、これらのパラメータは、カスタマイズされている追加以来parse_config.pyの一部を:

def parse_model_cfg(path):
    # path参数为: cfg/yolov3-tiny.cfg
    if not path.endswith('.cfg'):
        path += '.cfg'
    if not os.path.exists(path) and \
           os.path.exists('cfg' + os.sep + path):
        path = 'cfg' + os.sep + path

    with open(path, 'r') as f:
        lines = f.read().split('\n')

    # 去除以#开头的,属于注释部分的内容
    lines = [x for x in lines if x and not x.startswith('#')]
    lines = [x.rstrip().lstrip() for x in lines]
    mdefs = []  # 模块的定义
    for line in lines:
        if line.startswith('['):  # 标志着一个模块的开始
            '''
            eg:
            [shortcut]
            from=-3
            activation=linear
            '''
            mdefs.append({})
            mdefs[-1]['type'] = line[1:-1].rstrip()
            if mdefs[-1]['type'] == 'convolutional':
                mdefs[-1]['batch_normalize'] = 0 
        else:
            key, val = line.split("=")
            key = key.rstrip()

            if 'anchors' in key:
                mdefs[-1][key] = np.array([float(x) for x in val.split(',')]).reshape((-1, 2))
            else:
                mdefs[-1][key] = val.strip()

    # Check all fields are supported
    supported = ['type', 'batch_normalize', 'filters', 'size',\
                 'stride', 'pad', 'activation', 'layers', \
                 'groups','from', 'mask', 'anchors', \
                 'classes', 'num', 'jitter', 'ignore_thresh',\
                 'truth_thresh', 'random',\
                 'stride_x', 'stride_y']

    f = []  # fields
    for x in mdefs[1:]:
        [f.append(k) for k in x if k not in f]
    u = [x for x in f if x not in supported]  # unsupported fields
    assert not any(u), "Unsupported fields %s in %s. See https://github.com/ultralytics/yolov3/issues/631" % (u, path)

    return mdefs

上記、変更する必要があるが、フィールドでサポートされて、私たちの内容が追加されます。

supported = ['type', 'batch_normalize', 'filters', 'size',\
            'stride', 'pad', 'activation', 'layers', \
            'groups','from', 'mask', 'anchors', \
            'classes', 'num', 'jitter', 'ignore_thresh',\
            'truth_thresh', 'random',\
            'stride_x', 'stride_y',\
            'ratio', 'reduction', 'kernelsize']

3. SEとCBAMを達成するために

参照して具体的な原則[CV]注意の機構最も簡単で容易に実施SEモジュールECCV 2018畳み込みブロック注意モジュールに【注意】機構CV真上二条の下のコードを使用してこれら二つの記事、。

SE

class SELayer(nn.Module):
    def __init__(self, channel, reduction=16):
        super(SELayer, self).__init__()
        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        self.fc = nn.Sequential(
            nn.Linear(channel, channel // reduction, bias=False),
            nn.ReLU(inplace=True),
            nn.Linear(channel // reduction, channel, bias=False),
            nn.Sigmoid()
        )

    def forward(self, x):
        b, c, _, _ = x.size()
        y = self.avg_pool(x).view(b, c)
        y = self.fc(y).view(b, c, 1, 1)
        return x * y.expand_as(x)

CBAM

class SpatialAttention(nn.Module):
    def __init__(self, kernel_size=7):
        super(SpatialAttention, self).__init__()
        assert kernel_size in (3,7), "kernel size must be 3 or 7"
        padding = 3if kernel_size == 7else1

        self.conv = nn.Conv2d(2,1,kernel_size, padding=padding, bias=False)
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        avgout = torch.mean(x, dim=1, keepdim=True)
        maxout, _ = torch.max(x, dim=1, keepdim=True)
        x = torch.cat([avgout, maxout], dim=1)
        x = self.conv(x)
        return self.sigmoid(x)
    
class ChannelAttention(nn.Module):
    def __init__(self, in_planes, rotio=16):
        super(ChannelAttention, self).__init__()
        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        self.max_pool = nn.AdaptiveMaxPool2d(1)

        self.sharedMLP = nn.Sequential(
            nn.Conv2d(in_planes, in_planes // ratio, 1, bias=False), nn.ReLU(),
            nn.Conv2d(in_planes // rotio, in_planes, 1, bias=False))
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        avgout = self.sharedMLP(self.avg_pool(x))
        maxout = self.sharedMLP(self.max_pool(x))
        return self.sigmoid(avgout + maxout)

コードの二つ以上のモジュールが追加されmodels.pyたファイル。

4.デザインcfgファイル

ここでのyolov3-tiny.cfgベースラインとして、次に注意機構モジュールを追加します。

同様CBAMとSE、SEは、例えば、バックボーン、情報の再構成(改良)した後、一部に添加します。

[net]
# Testing
batch=1
subdivisions=1
# Training
# batch=64
# subdivisions=2
width=416
height=416
channels=3
momentum=0.9
decay=0.0005
angle=0
saturation = 1.5
exposure = 1.5
hue=.1

learning_rate=0.001
burn_in=1000
max_batches = 500200
policy=steps
steps=400000,450000
scales=.1,.1

[convolutional]
batch_normalize=1
filters=16
size=3
stride=1
pad=1
activation=leaky

[maxpool]
size=2
stride=2

[convolutional]
batch_normalize=1
filters=32
size=3
stride=1
pad=1
activation=leaky

[maxpool]
size=2
stride=2

[convolutional]
batch_normalize=1
filters=64
size=3
stride=1
pad=1
activation=leaky

[maxpool]
size=2
stride=2

[convolutional]
batch_normalize=1
filters=128
size=3
stride=1
pad=1
activation=leaky

[maxpool]
size=2
stride=2

[convolutional]
batch_normalize=1
filters=256
size=3
stride=1
pad=1
activation=leaky

[maxpool]
size=2
stride=2

[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky

[maxpool]
size=2
stride=1

[convolutional]
batch_normalize=1
filters=1024
size=3
stride=1
pad=1
activation=leaky

[se]
reduction=16

# 在backbone结束的地方添加se模块
#####backbone######

[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky

[convolutional]
size=1
stride=1
pad=1
filters=18
activation=linear



[yolo]
mask = 3,4,5
anchors = 10,14,  23,27,  37,58,  81,82,  135,169,  344,319
classes=1
num=6
jitter=.3
ignore_thresh = .7
truth_thresh = 1
random=1

[route]
layers = -4

[convolutional]
batch_normalize=1
filters=128
size=1
stride=1
pad=1
activation=leaky

[upsample]
stride=2

[route]
layers = -1, 8

[convolutional]
batch_normalize=1
filters=256
size=3
stride=1
pad=1
activation=leaky

[convolutional]
size=1
stride=1
pad=1
filters=18
activation=linear

[yolo]
mask = 0,1,2
anchors = 10,14,  23,27,  37,58,  81,82,  135,169,  344,319
classes=1
num=6
jitter=.3
ignore_thresh = .7
truth_thresh = 1
random=1

5.モデル構築

これらは、SEに準備されている、例えば、我々は修正model.pyモデルファイルのロード部分を、および機能のコード前方部分を修正し、それが正常に機能してみましょう:

機能追加:model.pycreate_modules

        elif mdef['type'] == 'se':
            modules.add_module(
                'se_module',
                SELayer(output_filters[-1], reduction=int(mdef['reduction'])))

そして、前方部分ダークネットに機能を変更します。

def forward(self, x, var=None):
    img_size = x.shape[-2:]
    layer_outputs = []
    output = []

    for i, (mdef,
            module) in enumerate(zip(self.module_defs, self.module_list)):
        mtype = mdef['type']
        if mtype in ['convolutional', 'upsample', 'maxpool']:
            x = module(x)
        elif mtype == 'route':
            layers = [int(x) for x in mdef['layers'].split(',')]
            if len(layers) == 1:
                x = layer_outputs[layers[0]]
            else:
                try:
                    x = torch.cat([layer_outputs[i] for i in layers], 1)
                except:  # apply stride 2 for darknet reorg layer
                    layer_outputs[layers[1]] = F.interpolate(
                        layer_outputs[layers[1]], scale_factor=[0.5, 0.5])
                    x = torch.cat([layer_outputs[i] for i in layers], 1)

        elif mtype == 'shortcut':
            x = x + layer_outputs[int(mdef['from'])]
        elif mtype == 'yolo':
            output.append(module(x, img_size))
        layer_outputs.append(x if i in self.routs else [])

SEモジュールが前方に追加され、それは実際には非常に簡単です。SE畳み込みモジュール層は、試料は、最大細胞層は、上記のコード部分を修正する必要がある、同じ位置、それ以上の操作です。

    for i, (mdef,
            module) in enumerate(zip(self.module_defs, self.module_list)):
        mtype = mdef['type']
        if mtype in ['convolutional', 'upsample', 'maxpool', 'se']:
            x = module(x)

CBAM全体のプロセスは似ている、あなたは、それをYOLOv3の全体的なプロセスを理解するための方法を自分で試すことができます。

追記:この記事の内容は非常に簡単です、ただモジュールの注意を追加し、実現するのは簡単です。しかし、注目の具体的なメカニズムの位置は、その検証するための実験を行うために必要なモジュールの数を置きます。注意メカニズムは、すべて満足のいく結果を取得しようとする上院を持参する必要がワンサイズフィットではありません。グループチャット、それぞれのデータセットへのフィードバック効果を結合するために私に連絡する歓迎。

PS:身体への最近の注目は、マスクを着用して外出します。

おすすめ

転載: www.cnblogs.com/pprp/p/12241054.html