์๋ ํ์ธ์. ์ ๋ฒ Depthwise Separable Convolution ๊ธฐ๋ฒ์ ๋ํด ๊ธ์ ์ฌ๋ ธ์ต๋๋ค.
์ค๋์ ์ด ๊ธฐ๋ฒ์ ์ฌ์ฉํ Xception ๋ ผ๋ฌธ์ ๋ํด ๋ฆฌ๋ทฐํ๋๋ก ํ๊ฒ ์ต๋๋ค.
์ฐ์ , Xception์ ๋ฆฌ๋ทฐํ๊ธฐ ์ Inception์ ๋ํด ๊ฐ๋จํ ์ง๊ณ ๋์ด๊ฐ๊ฒ ์ต๋๋ค.
Inception ๋ชจ๋๋ก 2014๋ ๋์ ๊ฐ์ฅ ๋์ ์ฑ์ ์ ๊ฑฐ๋ GoogleLeNet ์ ๋ง๋ค์์ต๋๋ค.
1. Inception Module
์ธ์ ์ ๋ชจ๋์ ์ด์ ๋จ๊ณ์ ํ์ฑํ ์ง๋์ ๋ค์ํ ํํฐ ํฌ๊ธฐ(Kernel_Size)๋ก ํฉ์ฑ๊ณฑ ์ฐ์ฐ์ ์ ์ฉํ๋ ๋ฐฉ์์ ๋๋ค.
์ฝ๊ฒ ํํํ๋ฉด, ๊ฐ์์ง ์ฌ์ง์์ ๊ท, ์ฝ, ๋ ๋ฑ์ ํน์ง์ ๋ค๋ฅธ ๋ฐฉํฅ์ผ๋ก ๋ณด๋ ๊ฒ์ ๋๋ค.
๋ค๋ฅธ ๋ฐฉํฅ์์ ๋ณด๊ธฐ ๋๋ฌธ์, ๊ฐ์ ๊ฐ์์ง ์ฌ์ง์์ ๋ค๋ฅธ ํน์ฑ๋ค์ ์ถ์ถํ ์ ์์ต๋๋ค.
์ธ์ ์ ์ ์ ์ ํ๋ผ๋ฏธํฐ๋ก ๋ค์ํ ํน์ง๊ฐ์ ์ถ์ถํ๋๋ฐ ์๋ฏธ๊ฐ ์์ต๋๋ค.
class InceptionModule(nn.Module):
def __init__(self, n_channels=10):
super(InceptionModule, self).__init__()
# Sequential : ์ฐ์ฐ์ ์ฐจ๋ก๋ก ์ํ
self.conv2d_3k = nn.Conv2d(in_channels=n_channels,
out_channels=n_channels,
kernel_size=3,
padding=1)
self.conv2d_1k = nn.Conv2d(in_channels=n_channels,
out_channels=n_channels,
kernel_size=1)
self.avgpool2d = nn.AvgPool2d(kernel_size=1)
def forward(self, x):
y1 = self.conv2d_1k(x)
y2_1 = self.conv2d_1k(x)
y2_2 = self.conv2d_3k(y2_1)
y3_1 = self.avgpool2d(x)
y3_2 = self.conv2d_3k(y3_1)
y4_1 = self.conv2d_1k(x)
y4_2 = self.conv2d_3k(y4_1)
y4_3 = self.conv2d_3k(y4_2)
out = torch.cat([y1, y2_2, y3_2, y4_3], dim=1)
return out
2. ๋จ์ํ Inception Module
์ ๋ฒ ๊ธ์ ๋์จ Depthwise Separable Convolution์ ํต์ฌ ๊ฐ๋ ์ธ spartial correlation(3x3 convolution)๊ณผ cross channel correlation(1x1 convolution)์ด ๋ฑ์ฅํฉ๋๋ค.
์ฌ๊ธฐ Standard Convolution๊ณผ ์ฐจ๋ณ ์ ์ ์๋ก๊ฐ ๋งคํ(mapping)๋์ง ์๊ณ ๋ ๋ฆฝ์ ์ผ๋ก ์ํํ๋ ๊ฒ์ ๋๋ค.
Figure1์ ๋ณต์กํจ์ ์ต๋ํ Simpleํ๊ฒ ๊ฐ๋๋ฐ ์๋ฏธ๊ฐ ์์ต๋๋ค.
class SimplyInceptionModule(nn.Module):
def __init__(self, n_channels=10):
super(SimplyInceptionModule, self).__init__()
# Sequential : ์ฐ์ฐ์ ์ฐจ๋ก๋ก ์ํ
self.conv2d_3k = nn.Conv2d(in_channels=n_channels,
out_channels=n_channels,
kernel_size=3,
padding=1)
self.conv2d_1k = nn.Conv2d(in_channels=n_channels,
out_channels=n_channels,
kernel_size=1)
def forward(self, x):
y1_1 = self.conv2d_1k(x)
y1_2 = self.conv2d_3k(y1_1)
y2_1 = self.conv2d_1k(x)
y2_2 = self.conv2d_3k(y2_1)
y3_1 = self.conv2d_1k(x)
y3_2 = self.conv2d_3k(y3_1)
out = torch.cat([y1_2, y2_2, y3_2], dim=1)
return out
3. ๋ ๋จ์ํ Inception module
Figure2์์ 1x1 Convolution์ Input๋ง๋ค ๋ ๋ฆฝ์ ์ผ๋ก ์ํํ๋ค๋ฉด,
Figure3์์๋ 1x1 Convolution์ input ํ ๋ฒ๋ง์ ์ํํฉ๋๋ค.
1x1 Convolution ์ํํ output์ (๊ทธ๋ฃน์ผ๋ก) ๋ถ๋ฆฌํ์ฌ 3x3 Convolution์ ์ํํฉ๋๋ค.
Figure2๋ฅผ ๋ณํํ์ฌ ๋ Simpleํ๊ฒ!
SimplyInceptionModule3 = nn.Sequential(
nn.Conv2d(in_channels=9,
out_channels=9,
kernel_size=1,
bias=False),
nn.ReLU(),
nn.Conv2d(in_channels=9,
out_channels=9,
kernel_size=3,
groups=3,
bias=False),
nn.ReLU()
)
์ด ๋ ผ๋ฌธ์์ ์ค์ํ ๋ถ๋ถ์ด๋ผ๊ณ ์๊ฐ๋๋ ๋ถ๋ถ์ ๋๋ค.
This observation naturally raises the question:
์ด ๊ด์ฐฐ์ ๋น์ฐํ ๋ฌธ์ ๋ฅผ ์ ๊ธฐํฉ๋๋ค.
what is the effect of the number of segments in the partition (and their size)?
ํํฐ์
์ ์ธ๊ทธ๋จผํธ ์ (๋ฐ ํฌ๊ธฐ)๋ ์ด๋ค ์ํฅ์ ๋ฏธ์นฉ๋๊น?
4. Extreme version of Inception module
Figure3์์ Output Channels๋ฅผ ์ต๋๋ก ๊ทธ๋ฃน์ ์ง์ด ๋ถ๋ฆฌํ์ฌ ์ํํ๋ฉด ์ด๋จ๊น?
์ ๋ ผ๋ฌธ์ ์ง๋ฌธ์ ๊ฐ์ค๋ก, ํํฐ์ ์ ์ธ๊ทธ๋จผํธ๋ฅผ ์ต๋ ๋จ์๋ก ์ํํ๋ค๋ฉด ์ด๋ป๊ฒ ๋๋๊ฐ?
ExtremeInception = nn.Sequential(
nn.Conv2d(in_channels=9,
out_channels=9,
kernel_size=1,
bias=False),
nn.ReLU(),
nn.Conv2d(in_channels=9,
out_channels=9,
kernel_size=3,
groups=9,
bias=False),
nn.ReLU()
)
We remark that this extreme version of an Inception module is almost identical to a depthwise
separable convolution, an operation that has been used in neural network design as early as
2014 and has become more popular since its inclusion in the TensorFlow framework in 2016.
An extreme version of Inception module์ 2014 ๋
์ด ์ ๊ฒฝ๋ง ์ค๊ณ์ ์ฌ์ฉ๋์์ผ๋ฉฐ 2016 ๋
TensorFlow ํ๋ ์ ์ํฌ์
ํฌํจ ๋ ์ดํ ๋ ๋๋ฆฌ ์ฌ์ฉ๋๋ Depthwise Separable Convolution๊ณผ ๊ฑฐ์ ๋์ผํฉ๋๋ค.
depthwise separable convolution ์ ๋น์ทํ ํํ์ ๋ชจ๋์ด ์์ฑ๋ฉ๋๋ค.
depthwise separable convolution๊ฐ ๊ถ๊ธํ์๋ฉด
https://coding-yoon.tistory.com/77
Xception์ ํ ๋ฒ์ ์์ฑํ ๋ ค๊ณ ํ์ง๋ง ์๊ฐ๋ณด๋ค ์ธ ๊ฒ์ด ๋ง์ 2ํธ ์ ๋๋ก ์ฐ์ฅ๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ฒซ ๋ ผ๋ฌธ ๋ฆฌ๋ทฐ์ธ๋ฐ ๋ถ์กฑํ ๋ถ๋ถ์ด ๋ง์ต๋๋ค. ํผ๋๋ฐฑ ์ฃผ์๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค.