Pytorch로 시작하는 딥러닝 입문(08-02. CNN으로 MNIST 분류하기)

2024. 3. 22. 22:35딥러닝 모델: 파이토치

♣ 모델 이해하기

1. 첫 번째 표기 방법

합성곱(nn.Conv2d) + 활성화 함수(nn.ReLU)를 하나의 합성곱 층으로 보고, 맥스풀링(nn.MaxPool2d)은 풀링층으로 별도로 명명한다. 

 

 

2. 두 번째 표기 방법

합성곱(nn.Conv2d) + 활성화 함수(nn.ReLU)+ 맥스풀링(nn.MaxPoold2d)을 하나의 합성곱 층으로 본다. 

 

첫 번째 표기 방법과 두 번째 표기 방법은 풀링도 하나의 층으로 보느냐 안 보느냐의 문제이다. 여기서는 편의를 위해 맥스풀링까지 포함해서 하나의 합성곱 층으로 판단하여 정리한다. 

 

모델의 아키텍처는 총 3개의 층으로 구성된다. 

 

#1번 레이어: 합성곱층(Convolutional layer)

 

합성곱(in_channel = 1, out_channel = 32, kernel_size = 3, stride = 1, padding=1) + 활성화 함수 ReLU + 맥스 풀링(kernel_size=2, stride=2)

 

#2번 레이어: 합성곱층(Convolutional layer)

 

합성곱(in_channel=32, out_channel=64, kernel_size=3, stride=1, padding=1) + 활성화 함수(ReLU) + 맥스풀링(kernel_size=2, stride=2)

 

#3번 레이어: 전결합층(Fully-Connected layer)

 

특성맵을 펼친다: batch_size × 7 × 7 × 64 -> batch_size × 3136

전결합층(뉴런 10개) + 활성화 함수 Softmax

 

이를 직접 구현해보자. 

 

♣ 모델 구현하기

1. 임의의 텐서 만들기 

임의의 텐서는 배치 크기 × 채널 × 높이(height) × 너비(width) 의 크기의 텐서를 선언했다. 

 

 

2. 합성곱층과 풀링 선언하기 

 

첫 번째 합성곱 층을 구현해보자

 

합성곱(in_channel = 1, out_channel = 32, kernel_size = 3, stride = 1, padding=1) + 활성화 함수 ReLU + 맥스 풀링(kernel_size=2, stride=2)

 

1채널 짜리를 입력 받아서 32채널을 뽑아내고, 커널 사이즈는 3, 패딩은 1이다. 

 

두 번째 합성곱 층을 구현해보자 

 

합성곱(in_channel=32, out_channel=64, kernel_size=3, stride=1, padding=1) + 활성화 함수(ReLU) + 맥스풀링(kernel_size=2, stride=2)

 

맥스 풀링을 구현해보자. 정수 하나를 인자로 넣으면 커널 사이즈와 스트라이드가 둘 다 해당값으로 지정된다. 

정수 2를 인자로 넣으니 커널 사이즈와 스트라이드가 모두 2로 설정되었다. dilation=1 은 커널 요소 사이의 간격을 나타낸다. 여기서는 1로 설정되어 있으므로 간격이 없다. 

 

 

3. 구현체를 연결하여 모델 만들기

지금까지는 층을 선언하기만 하고 연결시키지 않았다. 이들을 연결시켜서 모델을 완성한다. 입력을 첫 번째 합성곱층을 통과시킨 후의 결과를 살펴보자

첫 번째 합성곱층을 통과한 결과는 32채널의 너비 28, 높이 28의 텐서가 되었다. 32가 나온 이유는 conv1의 out_channel로 32를 지정해주었기 때문이다. 또한 패딩을 1로 하고 3×3 커널을 사용하면 크기가 보존된다. 이제 이를 맥스풀링을 통과시킨 후 텐서의 크기를 확인한다. 

32 채널의 너비 14, 높이 14의 텐서가 된다. 이를 다시 두 번째 합성곱층에 통과시킨다. 

 

64채널의 너비 14, 높이 14의 텐서가 된다. 64가 나온 이유는 conv2의 out_channel로 64를 지정했기 때문이다. 또한 너비 14, 높이 14가 된 이유는 패딩을 1폭으로 하고 3×3 커널을 사용하면 크기가 보존되기 때문이다. 이제 이 결과를 맥스풀링을 통과시킨 후 텐서를 살펴보자. 

 

이제 이 텐서를 펼치는 작업을 한다. 펼치기에 앞서 텐서의 n번째 차원에 접근하게 해주는 .size(n)에 대해서 배워보자.

현재 out의 크기는 1 × 64 × 7 × 7 이다. out의 첫 번째 차원이 몇인지 출력해보자 .

이 네 개 차원을 가지고 .view( )를 사용하여 텐서를 펼치는 작업을 해보자. 

배치 차원을 제외하고는 모두 하나의 차원으로 통합된 것을 볼 수 있다. 이제 이 결과를 전결합층(Fully-Connected layer)를 통과시켜보자. 출력층으로 10개의 뉴런을 배치하여 10개 차원의 텐서로 변환한다. 

 

 

♣ CNN으로 MNIST 분류하기

1. 도구 import 하고 시드 고정하기

 

2. 학습에 사용될 파라미터 설정하기

 

 

3. 데이터셋 정의하기

 

 

4. 데이터로더 사용하여 배치 크기 정하기 

 

 

5. 클래스로 모델 설계하기

 

 

6. 모델 정의하기

 

 

7. 비용함수와 옵티마이저 정의하기

 

 

8. 총 배치의 수 출력하기

 

총 배치의 수는 600이다. 그런데 배치 크기(batch_size)를 100으로 했으므로 훈련 데이터는 총 60,000개이다. 이제 모델을 훈련시켜보자

 

 

9. 모델 훈련시키기

 

 

10. 테스트하기