書いてる理由
- pytorchを基礎からもう一回
参考
https://arxiv.org/pdf/1612.01105.pdf
詳細
pytorch_work/network.py at master · ys201810/pytorch_work · GitHub
PSPNetでセマンティックセグメンテーションする。
昨日はFeature Mapを作る箇所だったので、今日はPyramid Poolingの箇所
PSPNetは、上の画像の通り、inputの画像(a)をFeature Map(b)で特徴抽出して、Pyramid Pooling Moudle(c)で4つの異なるサイズのFeature Mapを元のFeature MAPの大きさにUpsamplingした上でconcatしてから予測する。
この(c)の箇所
# Pyramid Pooling class PyramidPooling(nn.Module): def __init__(self, in_channels, pool_sizes, height, width): super(PyramidPooling, self).__init__() self.height = height self.width = width out_channels = int(in_channels / len(pool_sizes)) self.avpool1 = nn.AdaptiveAvgPool2d(output_size=pool_sizes[0]) self.cbr1 = Conv2DBatchNormRelu(in_channels, out_channels, kernel_size=1, stride=1, padding=0, dilation=1, bias=False) self.avpool2 = nn.AdaptiveAvgPool2d(output_size=pool_sizes[1]) self.cbr2 = Conv2DBatchNormRelu(in_channels, out_channels, kernel_size=1, stride=1, padding=0, dilation=1, bias=False) self.avpool3 = nn.AdaptiveAvgPool2d(output_size=pool_sizes[2]) self.cbr3 = Conv2DBatchNormRelu(in_channels, out_channels, kernel_size=1, stride=1, padding=0, dilation=1, bias=False) self.avpool4 = nn.AdaptiveAvgPool2d(output_size=pool_sizes[3]) self.cbr4 = Conv2DBatchNormRelu(in_channels, out_channels, kernel_size=1, stride=1, padding=0, dilation=1, bias=False) def forward(self, x): out1 = self.cbr1(self.avpool1(x)) out1 = F.interpolate(out1, size=(self.height, self.width), mode='bilinear', aligh_corners=True) out2 = self.cbr2(self.avpool2(x)) out2 = F.interpolate(out2, size=(self.height, self.width), mode='bilinear', aligh_corners=True) out3 = self.cbr3(self.avpool3(x)) out3 = F.interpolate(out3, size=(self.height, self.width), mode='bilinear', aligh_corners=True) out4 = self.cbr4(self.avpool4(x)) out4 = F.interpolate(out4, size=(self.height, self.width), mode='bilinear', aligh_corners=True) output = torch.cat([x, out1, out2, out3, out4], dim=1) return output
Pyramid Poolingは、前の層で得た60 * 60 * 2048のFeature Mapを4つの異なるサイズで特徴抽出して、Pyramid Poolingのinputと同じサイズにUpsamplingしてconcatする。
AdaptiveAvgPool2dにoutput_sizeを指定すると、その縦横サイズでinputの次元数をもつ出力が得られる。
今欲しい4つのサイズが、6 * 6, 3*3, 2 * 2, 1 * 1なので、
nn.AdaptiveAvgPool2d(output_size=6)、nn.AdaptiveAvgPool2d(output_size=3)、nn.AdaptiveAvgPool2d(output_size=2)、nn.AdaptiveAvgPool2d(output_size=1)でそれぞれ実施後、Conv -> BatchNorm -> Reluをかけて、Upsamplingで 60 * 60に戻す。
UpsamplingはF.interpolateで実施する。
最後に、torch.cat([x, out1, out2, out3, out4], dim=1)でConcat。dim=1はchannel方向に結合を意味する。(batch_size, channel_size, height, widhtなので)
今日はここまで。次は、予測結果の出力箇所。