๐ PyTorch๋ก CNN ๋ชจ๋ธ ๋จ๊ณ๋ณ๋ก ์ ๋ณตํ๊ธฐ
์ค๋์ ๋ง์น ๋ ๊ณ ๋ธ๋ก์ ํ๋์ฉ ์์ ๋ฉ์ง ์ฑ์ ๋ง๋ค๋ฏ, ๊ฐ๋จํ ์ ๊ฒฝ๋ง์์ ์์ํด ์์ ํ CNN ๋ชจ๋ธ์ ๋จ๊ณ๋ณ๋ก ๊ตฌ์ถํ๋ ๊ณผ์ ์ ์งํํ๋ค. Fashion MNIST ๋ฐ์ดํฐ์ ์ ๊ฐ์ง๊ณ , ๊ฐ ๋ถํ(๋ ์ด์ด)์ด ๋ชจ๋ธ ์ฑ๋ฅ์ ์ด๋ค ์ํฅ์ ๋ฏธ์น๋์ง ์ง์ ํ์ธํด๋ณด๋ ์๊ฐ์ด์๋ค.
๐ง โCNN, ์ ์ด๋ฏธ์ง ์ฒ๋ฆฌ์ ๊ฐ๋ ฅํ ๊น?โ
์ด๋ฏธ์ง๋ ํฝ์ ์ ์์น์ ๊ด๊ณ, ์ฆ ๊ณต๊ฐ์ ํน์ง์ด ๋งค์ฐ ์ค์ํ๋ค. CNN์ ์ปจ๋ณผ๋ฃจ์ (Convolution) ๊ณผ ํ๋ง(Pooling) ์ด๋ผ๋ ํน๋ณํ ์ฐ์ฐ์ผ๋ก ์ด ๊ณต๊ฐ ์ ๋ณด๋ฅผ ๋๋ํ๊ฒ ์ ์งํ๋ฉฐ ํ์ตํ๊ธฐ ๋๋ฌธ์ ์ด๋ฏธ์ง ์ธ์์์ ๋ฐ์ด๋ ์ฑ๋ฅ์ ๋ฐํํ๋ค.
๐ ๏ธ CNN์ ํต์ฌ ์ฌ๋ฃ: ์ปจ๋ณผ๋ฃจ์ ๊ณผ ํ๋ง
- ์ปจ๋ณผ๋ฃจ์ (Convolution): ์ด๋ฏธ์ง ์๋ฅผ ์ฌ๋ผ์ด๋ฉํ๋ ํํฐ(์ปค๋) ๋ฅผ ํตํด ์ค๊ณฝ์ , ์ง๊ฐ ๊ฐ์ ๊ณ ์ ํ ํน์ง์ ์ถ์ถํ๋ค. ์ด ๊ฒฐ๊ณผ๋ฌผ์ ํน์ง ๋งต(Feature Map) ์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
- ํ๋ง(Pooling): ํน์ง ๋งต์ ํฌ๊ธฐ๋ฅผ ์ค์ฌ(Sub-sampling) ์ค์ํ ์ ๋ณด๋ง ๋จ๊ธด๋ค. ๋งฅ์ค ํ๋ง(Max Pooling) ์ ํน์ ์์ญ์์ ๊ฐ์ฅ ์ค์ํ ํน์ง(๊ฐ์ฅ ํฐ ๊ฐ)๋ง ๋ฝ์๋ด ๋ชจ๋ธ์ ๋ ๊ฐ์ธํ๊ฒ ๋ง๋ ๋ค.
โจ ๋ชจ๋ธ ๋น๋์ ๊ณผ์ : ๋ฐ๋ฅ๋ถํฐ ์ฒ์ฒํ
Fashion MNIST ๋ฐ์ดํฐ์ ์ผ๋ก ๋ชจ๋ธ์ ์ฑ๋ฅ์ด ์ด๋ป๊ฒ ์งํํ๋์ง ๋จ๊ณ๋ณ๋ก ๋ฐ๋ผ๊ฐ ๋ณด์๋ค.
1๏ธโฃ Step 1: ๊ธฐ๋ณธ DNN ๋ชจ๋ธ (Baseline)
- ๊ฐ์ฅ ๋จผ์ , ์ด๋ฏธ์ง๋ฅผ 1์ฐจ์์ผ๋ก ๊ธธ๊ฒ ํผ์ณ์ ์ผ๋ฐ์ ์ธ ์์ ์ฐ๊ฒฐ ์ ๊ฒฝ๋ง(DNN)์ผ๋ก ํ์ต์์ผฐ๋ค.
- ๊ฒฐ๊ณผ: Test Accuracy
88.66%
. ๋์์ง ์์ ์์์ด๋ค!
2๏ธโฃ Step 2: ์ปจ๋ณผ๋ฃจ์ (CNN) ๋ ์ด์ด ์ถ๊ฐ
- DNN ๋ชจ๋ธ ์์ ์ปจ๋ณผ๋ฃจ์ ๋ ์ด์ด๋ฅผ ์ถ๊ฐํ์ฌ ์ด๋ฏธ์ง์ ๊ณต๊ฐ ์ ๋ณด๋ฅผ ํ์ฉํ๋๋ก ํ๋ค.
- ๊ฒฐ๊ณผ: Test Accuracy
88.37%
. ์ ํ๋๋ ๋น์ทํ์ง๋ง, ํ์ต ๊ณผ์ ์ด ๋ ์์ ํ๋์๋ค.
3๏ธโฃ Step 3: ๋งฅ์คํ๋ง(Max Pooling)์ผ๋ก ์ฑ๋ฅ ์ ํ!
- ์ปจ๋ณผ๋ฃจ์ ๋ ์ด์ด ๋ค์ ๋งฅ์ค ํ๋ง์ ์ถ๊ฐํด ํน์ง์ ์์ถํ๊ณ ์ฐ์ฐ ํจ์จ์ ๋์๋ค.
- ๊ฒฐ๊ณผ: Test Accuracy
91.22%
. ์ฑ๋ฅ์ด ๋์ ๋๊ฒ ํฅ์๋์๋ค! ์ญ์ CNN์ ํต์ฌ์ ํ๋ง์ ์๋ ๊ฒ ๊ฐ๋ค.
4๏ธโฃ Step 4: ๊ณผ์ ํฉ ๋ฐฉ์ง & ์์ ํ (Dropout, Batch Norm)
- ๋ชจ๋ธ์ด ํ๋ จ ๋ฐ์ดํฐ์๋ง ๋๋ฌด ์ต์ํด์ง๋ ๊ณผ์ ํฉ์ ๋ง๊ธฐ ์ํด ๋๋กญ์์(Dropout) ๊ณผ ๋ฐฐ์น ์ ๊ทํ(Batch Normalization) ๋ฅผ ์ถ๊ฐํ๋ค. ์ด๋ค์ ๋ชจ๋ธ์ ๋ ์์ ์ ์ด๊ณ ์ผ๋ฐํ ์ฑ๋ฅ์ด ์ข๊ฒ ๋ง๋ค์ด์ค๋ค.
# ์ต์ข
๋ชจ๋ธ์ ์ผ๋ถ
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.layer1 = nn.Sequential(
nn.Conv2d(1, 32, kernel_size=3, padding=1),
nn.BatchNorm2d(32), # ๋ฐฐ์น ์ ๊ทํ
nn.ReLU(),
nn.MaxPool2d(2), # ๋งฅ์ค ํ๋ง
nn.Dropout(0.3) # ๋๋กญ์์
)
self.layer2 = nn.Sequential(
nn.Conv2d(32, 64, kernel_size=3, padding=1),
nn.BatchNorm2d(64),
nn.ReLU(),
nn.MaxPool2d(2),
nn.Dropout(0.3)
)
self.fc1 = nn.Linear(64 * 7 * 7, 10) # ์์ ์ฐ๊ฒฐ ๋ ์ด์ด
def forward(self, x):
x = self.layer1(x)
x = self.layer2(x)
x = x.view(x.size(0), -1) # flatten
x = self.fc1(x)
return x
- ์ต์ข
๊ฒฐ๊ณผ: Test Accuracy
~93%
. ๋ชจ๋ ๋ถํ์ ์กฐ๋ฆฝํ๋ ํจ์ฌ ๊ฒฌ๊ณ ํ๊ณ ๊ฐ๋ ฅํ ๋ชจ๋ธ์ด ์์ฑ๋์๋ค. ๐
โจ ์ค๋์ ํ๊ณ
๋จ์ํ DNN ๋ชจ๋ธ์์ ์์ํด ์ปจ๋ณผ๋ฃจ์ , ํ๋ง, ๋๋กญ์์, ๋ฐฐ์น ์ ๊ทํ ๊ฐ์ ๊ฐ๋ ๋ค์ ํ๋์ฉ ์ถ๊ฐํ๋ฉฐ ๋ชจ๋ธ์ ์ฑ๋ฅ์ด ๋์ ๋๊ฒ ์ข์์ง๋ ๊ฒ์ ์ง์ ํ์ธํ๋ ์ ๋ง ํฅ๋ฏธ๋ก์ ๋ค. ๊ฐ ๋ ์ด์ด๊ฐ ์ด๋ค ์ญํ ์ ํ๋์ง, ์ ํ์ํ์ง๋ฅผ ๋ชธ์ ์ฒด๊ฐํ ์ ์๋ ์ต๊ณ ์ ์ค์ต์ด์๋ค.
ํนํ ๋งฅ์ค ํ๋ง์ ์ถ๊ฐํ์ ๋ ์ฑ๋ฅ์ด ํฌ๊ฒ ์ค๋ฅด๋ ๊ฒ์ ๋ณด๊ณ , ํน์ง์ ์ ์์ถํ๊ณ ๊ฐ์กฐํ๋ ๊ฒ์ด ์ผ๋ง๋ ์ค์ํ์ง ๊นจ๋ฌ์๋ค. ๋ค์์๋ ์ค๋ ๋ง๋ ๋ชจ๋ธ์ ๊ธฐ๋ฐ์ผ๋ก ๋ ๋ณต์กํ ๋ฐ์ดํฐ์ ์ ๋์ ํ๊ฑฐ๋, VGG๋ ResNet ๊ฐ์ ์ ๋ช ํ CNN ์ํคํ ์ฒ๋ฅผ ๋ถ์ํด๋ด์ผ๊ฒ ๋ค. ๐