3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

みんな大好きResNetのReceptive field(受容野)について調べます。

Receptive field(受容野)

畳み込み演算におけるReceptive field(受容野)とは畳み込み演算の結果の1点と結合する入力画像の幅のことを指します。ある1点の特徴量を計算したい場合、その点を基準にどれくらいマージンをとれば良いかが分かります。

ResNet

2015年にMicrosoft Researchが考案した畳み込みニューラルネットワークのアーキテクチャであり、様々な画像認識タスクで用いられています。

ResNetのアーキテクチャ

論文を参考にResNetのアーキテクチャを確認します。

image.png

conv3_x以降のダウンサンプリング(stride=2)するタイミングですが、論文中に

Downsampling is performed by conv3_1, conv4_1, and conv5_1 with a stride of 2.

と書かれおり、conv3_x以降のブロックの先頭で行われていることが分かります。

ResNet50のReceptive field

まずは畳み込みのKernel sizeとStrideがReceptive fieldにどのような影響を与えるかを考えます。

Kernel sizeとReceptive field

畳み込みのKernel sizeをksizeとするとReceptive fieldは(ksize-1)/2増加すると考えることが出来ます。

StrideとReceptive field

stride=2で畳み込んだ場合、次回以降の畳み込みのReceptive fieldの増加量が2倍になると考えることが出来ます。

Receptive field試算

以上を踏まえてResNet50のReceptive fieldを試算するための表を作成します(1x1の畳み込み等を除く)。

block名 ksize stride=2 RF増加分 RF累積
(input) 1
conv1 7 3
conv2_x max pool 3 2
conv2_1 3 4
conv2_2 3 4
conv2_3 3 4 18
conv3_x conv3_1 3 4
conv3_2 3 8
conv3_3 3 8
conv3_4 3 8 46
conv4_x conv4_1 3 8
conv4_2 3 16
conv4_3 3 16
conv4_4 3 16
conv4_5 3 16
conv4_6 3 16 134
conv5_x conv5_1 3 16
conv5_2 3 32
conv5_3 3 32 214

実験

500x500ピクセルの画像を上下に分割し、ResNet50に入力して中間層conv4_xでの特徴マップを結合させます。上下分割しない場合の特徴マップを一致させるにはどれくらいのマージンが必要かを考えます。

試算によるとマージンは134ピクセルで良さそうです。但し、畳み込み演算はシフト不変ですが、ダウンサンプリングの影響でconv4_xの場合は16刻みで平行移動させないと計算結果が変わってしまいます。ここは16の倍数で丸めてマージンを144ピクセルとしましょう。128ピクセルでは不一致となるはずです。

ソースコード

Torchvisionのresnet50を使用します。論文中のブロック名「conv4_x」は「layer3」に対応します。

import torch
from torchvision.models import resnet50
from torchvision.models.feature_extraction import create_feature_extractor

def test_margin(margin):
    # ResNet50をロード
    model = create_feature_extractor(
        resnet50(weights="DEFAULT"),
        return_nodes=["layer3"]) # conv4_xはlayer3に対応
    model.eval()

    # 入力画像(ランダム)
    input = torch.rand((1,3,500,500))

    # 分割しないで推論
    with torch.no_grad():
        feature = model(input)["layer3"]

    # 分割位置(16の倍数にする)
    half = input.size(2)//2
    half = half - half%16

    # マージンを付加して上下分割
    input_t = input[:, :, :half+margin]
    input_b = input[:, :, half-margin:]

    # 分割して推論
    with torch.no_grad():
        feature_t = model(input_t)["layer3"]
        feature_b = model(input_b)["layer3"]

    # マージンを付加した分を切り落とす
    feature_t = feature_t[: ,:, :-margin//16]
    feature_b = feature_b[:, :, margin//16:]

    # 上下結合
    feature_t_b = torch.cat((feature_t, feature_b), dim=2)

    # 誤差を計算
    err = (feature - feature_t_b).abs().max()
    print(f"margin:{margin} max_err:{err}")

if __name__ == "__main__":
    test_margin(112)
    test_margin(128)
    test_margin(144)
    test_margin(160)

実行結果

margin:112 max_err:0.04556167125701904
margin:128 max_err:3.552436828613281e-05
margin:144 max_err:0.0
margin:160 max_err:0.0

期待通りマージン144ピクセルで特徴マップが一致することを確認しました。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?