์๋ ํ์ธ์. ์ค๋์ Deep Learning ๋ถ์ผ์์ CNN์ BottleNeck๊ตฌ์กฐ์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค.
๋ํ์ ์ผ๋ก ResNet์์ BottleNeck์ ์ฌ์ฉํ์ต๋๋ค.
ResNet์์ ์ผ์ชฝ์ BottleNeck ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ์ง ์์๊ณ , ์ค๋ฅธ์ชฝ์ BottleNeck ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ์ต๋๋ค.
BottleNeck์ ์ค๋ช ํ๊ธฐ ์ , Convolution์ Parameters์ ๊ณ์ฐํ ์ค ์์์ผ ํฉ๋๋ค. ์ด ๋ถ๋ถ์ ๋ค๋ฅธ ๊ธ์์ ์์ธํ ์ค๋ช ํ๊ฒ ์ต๋๋ค.
Convolution Parameters = Kernel Size x Kernel Size x Input Channel x Output Channel
BottleNeck์ ํต์ฌ์ 1x1 Convolution์ ๋๋ค. ( Pointwise Convolution ์ด๋ผ๊ณ ๋ ํฉ๋๋ค. ์ด๋ Depthwise Separable Convolution์์๋ ๋๊ฐ์ ์๋ฆฌ๋ก ์ด์ฉ๋๊ธฐ ๋๋ฌธ์ ์ ์์๋๋ฉด ์ข์ต๋๋ค.)
1x1 Convolution์ Parameters๋ 1 x 1 x Input Channel x Output Channel์ ๋๋ค.
๋๊ฒ 1x1 Convolution์ ์ฐ์ฐ๋์ด ์๊ธฐ ๋๋ฌธ์ Feature Map(Output Channel)์ ์ค์ด๊ฑฐ๋ ํค์ธ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
BottleNeck ๊ตฌ์กฐ
1. Input Channel = 256์ธ 320x320 Input Image๊ฐ ์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค.
2. Channel Compression ( ์ฑ๋ ์์ถ )
Input Channel 256 -> Output Channel 64
256์ 64๋ก ์ฑ๋์ ๊ฐ์ ๋ก ์ถ์ํ ์ด์ ๋ ์ค๋ก์ง ์ฐ์ฐ๋์ ์ค์ด๊ธฐ ์ํจ์ ๋๋ค.
1x1 Convolution์๋ Spatial(๊ณต๊ฐ์ ์ธ) ํน์ง์ ๊ฐ์ง๊ณ ์์ง ์์ต๋๋ค. Convolution ์ฐ์ฐ์ด ๊ณต๊ฐ์ ์ธ ํน์ง์ ์ถ์ถํ๊ธฐ ์ํด์ Kernel์ด ์ต์ 2 ์ด์ ๋์ด์ผ ํฉ๋๋ค.
3. ํน์ง ์ถ์ถ
Input Channel 64 -> Output Channel 64
3x3 Convolution์ ํน์ฑ์ ์ถ์ถํ๋ ์ญํ ์ ํฉ๋๋ค.
3x3 Convolution ์ฐ์ฐ์ = 3 x 3 x Input Channel x Output Channel ์ ๋๋ค. ( 3 x 3 x 64 x 64 )
3x3 Convolution์ 1x1 Convolution ๋ณด๋ค 9๋ฐฐ ์ฐ์ฐ๋์ด ๋ง๊ธฐ ๋๋ฌธ์, 1x1 Convolution์์ ์ฑ๋์ ์ค์ธ ํ์
3x3 Convolution์์ ํน์ฑ์ ์ถ์ถํฉ๋๋ค.
4. Channel Increase( ์ฑ๋ ์ฆ๊ฐ )
Input Channel 64 -> Output Channel 256
CNN์ Feature Map์ ํน์ฑ์ด ๋ง์ผ๋ฉด ๋ง์์๋ก ํ์ต์ด ์ ๋๊ธฐ ๋๋ฌธ์, 1x1 Convolution์ผ๋ก ๊ฐ์ ์ ์ผ๋ก ์ฑ๋์ ์ฆ๊ฐ์์ผ์ค๋๋ค.
BottleNeck์ ๊ตฌ์กฐ๋ 1x1 Convolution์ผ๋ก ์ฅ๋์ ์น๋ฉด์ ์ฐ์ฐ๋์ ์ต์ํํ๋ ๊ฒ์ ๋๋ค.
ํ์ง๋ง ๊ฐ์ ๋ก ์ฑ๋์ ์ค์ด๊ณ ๋๋ฆฌ๋ ๊ฒ์ ์ ๋ณด ์์ค์ ์ผ์ผํต๋๋ค.
์ ๋ณด ์์ค์ ๋ชจ๋ธ์ ์ ํ์ฑ์ ๋จ์ด๋จ๋ฆฝ๋๋ค.
์ฐ์ฐ๋๊ณผ ์ ๋ณด์์ค์ ์๋ก tradeoff ๊ด๊ณ์ด๊ธฐ ๋๋ฌธ์ ์๋ก์ ํฉ์์ ์ ์ฐพ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
ResNet์ด ์ ์ํ ๋ ๊ตฌ์กฐ๋ฅผ Pytorch๋ก ๊ตฌํํด Parameter๋ฅผ ํ์ธํ๊ฒ ์ต๋๋ค.
Standard๋ Channel ์๊ฐ ์ ์์ง๋ผ๋, 3x3 Convolution์ ๋ ๋ฒ ํต๊ณผํ๊ณ ,
BottleNeck์ 1x1, 3x3, 1x1 ์์ผ๋ก Convolution์ ํต๊ณผํ๊ณ , Channel ์๋ 4๋ฐฐ ์ ๋ ๋ง์ง๋ง, Parameter๊ฐ ์ธ ๋ฐฐ ์ ๋ ์ ์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ํ์ฑ๋ ๊ฒ์ด ๋๋ก์ ๋ณ๋ชฉ ํ์๊ณผ ๋น์ทํ๋ค ํ์ฌ BottleNeck ๊ตฌ์กฐ๋ผ๊ณ ๋ถ๋ฆฝ๋๋ค.
cf) Pytorch Code
# standard
class Standard(nn.Module):
def __init__(self, in_dim=256, mid_dim=64, out_dim=64):
super(BuildingBlock, self).__init__()
self.building_block = nn.Sequential(
nn.Conv2d(in_channels=in_dim, out_channels=mid_dim, kernel_size=3, padding=1, bias=False),
nn.ReLU(),
nn.Conv2d(in_channels=mid_dim, out_channels=out_dim, kernel_size=3, padding=1, bias=False),
)
self.relu = nn.ReLU()
def forward(self, x):
fx = self.building_block(x) # F(x)
out = fx + x # F(x) + x
out = self.relu(out)
return out
# BottleNeck
class BottleNeck(nn.Module):
def __init__(self, in_dim=256, mid_dim=64, out_dim=256):
super(BottleNeck, self).__init__()
self.bottleneck = nn.Sequential(
nn.Conv2d(in_channels=in_dim, out_channels=mid_dim, kernel_size=1, bias=False),
nn.ReLU(),
nn.Conv2d(in_channels=mid_dim, out_channels=mid_dim, kernel_size=3, padding=1, bias=False),
nn.ReLU(),
nn.Conv2d(in_channels=mid_dim, out_channels=in_dim, kernel_size=1, bias=False),
)
self.relu = nn.ReLU()
def forward(self, x):
fx = self.bottleneck(x) # F(x)
out = fx + x # F(x) + x
out = self.relu(out)
return out