본문 바로가기

Programming Project/Pytorch Tutorials

Pytorch 머신러닝 튜토리얼 강의 10 (Basic CNN)


투명한 기부를 하고싶다면 이 링크로 와보세요! 🥰 (클릭!)

바이낸스(₿) 수수료 평생 20% 할인받는 링크로 가입하기! 🔥 (클릭!)

2018/07/02 - [Programming Project/Pytorch Tutorials] - Pytorch 머신러닝 튜토리얼 강의 1 (Overview)

2018/07/02 - [Programming Project/Pytorch Tutorials] - Pytorch 머신러닝 튜토리얼 강의 2 (Linear Model)

2018/07/02 - [Programming Project/Pytorch Tutorials] - Pytorch 머신러닝 튜토리얼 강의 2 (Linear Model)

2018/07/03 - [Programming Project/Pytorch Tutorials] - Pytorch 머신러닝 튜토리얼 강의 3 (Gradient Descent)

2018/07/03 - [Programming Project/Pytorch Tutorials] - Pytorch 머신러닝 튜토리얼 강의 4 (Back-propagation and Autograd)

2018/07/07 - [Programming Project/Pytorch Tutorials] - Pytorch 머신러닝 튜토리얼 강의 5 (Linear Regression in the PyTorch way)

2018/07/09 - [Programming Project/Pytorch Tutorials] - Pytorch 머신러닝 튜토리얼 강의 6 (Logistic Regression)

2018/07/10 - [Programming Project/Pytorch Tutorials] - Pytorch 머신러닝 튜토리얼 강의 7 (Wide and Deep)

2018/07/11 - [Programming Project/Pytorch Tutorials] - Pytorch 머신러닝 튜토리얼 강의 8 (PyTorch DataLoader)

2018/07/11 - [Programming Project/Pytorch Tutorials] - Pytorch 머신러닝 튜토리얼 강의 9 (Softmax Classifier)



이번 글에선 뉴럴넷 구조에서 진짜진짜 중요한 CNN에 관하여 알아 보도록 하겠습니다.


CNN은 이미지 프로세싱이나 NLP등 다양한 분야에서 좋은 성능을 발휘합니다.


CNN은 기본적으로 n x n 필터 모양을 가지고 이미지의 부분을 잘라서 새로운 숫자를 뽑아낸다는 데에 아이디어가 있습니다.


어떤 이미지가 있을 때 , 그 이미지의 사이즈가 ( x * y * depth ) 이라면, 그 중 일부를 조각내서 (n x n x depth) 새로운 하나의 pixel을 만들어내는 것이죠.




고양이 모양의 사진이 있을 때 , 그 중 일부분만 가지고 하나의 output을 만들어내는 필터를 사용하는 것입니다.


그래서 한번에 그림 전체를 보는 것이 아닌, Patch라고 불리는 작은 단위를 보기로 합니다.



아, 그리고 당연히 필터는 모든 이미지의 부분을 쭉 훑으면서 값을 뽑아냅니다.


그렇기 때문에 그 결과값도 a * b 사이즈가 나오게 됩니다.



이걸 어떻게 훑느냐를 정해주는 다양한 속성이 있는데요, 


stride 라는 속성은 한번에 몇 칸씩 건너뛰면서 볼 것인지를 정해주고, padding은 원래 그림의 테두리에 여백을 얼마나 준 상태로 시작할 것인지를 정해줍니다. 주로 여백은 0으로 채워줍니다.


http://taewan.kim/post/cnn/


링크의 1-3 , 1-4 부분을 보시면 이해가 쉬울 것입니다.





그리고 필터를 통해서 새로운 숫자를 만들어낸다는 것은 위와 같이, 


우리의 필터는 사실상 (또) weight 를 가진 파라미터입니다.


그래서 저렇게 수들을 곱해주게 되면 하나의 새로운 수가 나오게 되는것이구요.


하나의 필터를 가지고 그림의 전부를 stride에 맞춰 쫙 훑어주게 되는 것입니다.


그럼 그 weight와의 곱한 결과가 맨 오른쪽처럼 나오게 되겠네욤 ^^


* 잘 이해가 가지 않으신다면 위의 링크를 참고해주세요! 이 부분은 동영상 강의를 스샷떠서 글로 옮기려니 잘 되지 않네요 ㅠ_ㅠ




Zero Padding을 한 이미지는 다음과 같이 될 것이구요





(주로 가운데 정렬해서 패딩을 하므로 패딩을 한 줄 더한다면 왼쪽과 윗줄에 0 이 추가 될 것 입니다)



그렇다면 한번 필터 자체의 크기는 어떻게 되는지 생각 해 봅시다



왼쪽의 32*32 크기의 이미지가 RGB의 3개 속성값을 가지고 있다고 한다면, 우리가 5*5크기의 필터를 만든다고 할 때 , 최종 필터 한개의 사이즈는 어떻게 될까요?


바로 5*5*3입니다.

RGB각각 5*5크기의 필터가 낸 결과가 합쳐져야 합니다.




그리고 또한, 하나의 필터가 결국 하나의 큰 네모난 결과를 만들 것인데, 이것을 activation map 이라고 합니다.



어떤 크기의 filter을 쓰느냐, 얼만큼 padding을 주느냐, 얼만큼 stride를 주느냐에 따라서 activation map 의 크기는 다르게 됩니다.




그리고 필터의 '종류'를 늘려서, 우리는 여러가지의 activation map 을 만들 수 있게 됩니다.


위의 그림과 같이 32*32*3 의 이미지를가지고 6개의 필터를 쓰면,


28*28*6의 새로운 activation maps를 얻을 수 있게 됩니다.





Pooling




CNN에서 또 많이 쓰이는게 Pooling 이라는 스킬입니다.


conv layer와 비슷하게 필터 크기와 stride 등을 정해서 진행하기는 하는데, 중요한건 pooling layer은 계산을 weight와 한다는 것이 아닌, 그냥 규칙대로 뽑아내는 연산을 합니다


위의 경우는 stride 가 2인 상태로 2*2필터로 Max pooling을 한 결과인데요.


max pooling layer 이란, 주어진 필터 범위 내에서 최대값을 뽑아내는 pooling layer입니다.



비슷하게, Average Pooling이나 (전체의 평균을 뽑아냄) Min Pool등도 있으나 주로 max pool이 쓰입니다.





그럼 이제 우리는 우리의 모델을 다음과 같이 구성할 수 있습니다.


앞쪽으로 conv layer들을 통해서 비교적 의미있는 정보들을 추출 한 후에,


그것을 fully connected layer을 통해서 다시 논리적으로 분석하는 과정을 거치는 것이죠.




만약 Fully connected layer을 처음부터 쓴다고 하면


Fully connected는 정말 끔찍하게 많은 파라미터가 필요 할 것입니다.


Locally Connected layer은 비교해서, 이미지는 부분 부분 떨어져있지 않으므로, 적은 파라미터로도 의미있는 결과를 주게 됩니다.






그럼 이제 MNIST 이미지를 가지고 간단하게 CNN 을 구성해보도록 합시다.


일단 첫 input layer은 convolutional layer을 만들어보도록 할 것이구요.


pytorch에서 제공하는 2차원 이미지에 대한 Conv layer을 사용하도록 하겠습니다.


넘겨줘야 할 파라미터는 Conv2d(in체널,out체널, 커널사이즈 ) 인데요,


in 체널은 mnist가 흑백 이미지이기 때문에 1이고, 

out 체널은 10 정도로 줘 보도록 합시다.


커널이란, convolution 필터를 말하는데 (다른이름 이지만 같은것) 그 필터의 사이즈가 5*5 짜리라는 것입니다.


정리하자면, input 1 체널짜리 (이경우엔 흑백) 이미지로부터 10개의 서로 다른 5*5 필터를 통해서 새로운 결과를 만드는 layer가 됩니다.




그리고 pooling layer의 경우에는 Max pool을 쓸건데요, 


단순하게 커널 사이즈만 입력 해 주면 됩니다.


그러니까, 2*2 필터를 의미합니다.


Max pool함수는 stride 옵션을 따로 주지 않았기 때문에 파이토치 MaxPool 에선 기본 옵션이 kernel_size에 맞춰서 stride가 되어서 stride = 2가 될 것입니다.




Code



그럼 한번 코드를 짜봅시다. conv1 레이어의 경우, 보시는 바와 같고 conv 2레이어도 이해하시기에 무리가 없다고 생각합니다. 10체널로 만든 것에서 20개의 필터를 가지고 새로운 output을 만드는 것이기 때문입니다.





중요한것은 Conv layer에서 Fully Connected Layer로 넘어갈 때 입니다.


우리는 마지막 conv layer의 cell을 한줄로 쭉 나열 한 후에, 그 개수에 맞춰서 Fully connected layer의 input으로 넘겨 줄 것입니다.



그러기 위해서 필요한 node의 수는 몇개일까요?


수학적으로 계산할 수도 있지만 그냥 아무 숫자나 넣어보고 에러나면 그 에러메시지에 몇 차원인지가 뜬다고 합니다 (ㅋㅋㅋㅋ진짜 강의에서 이렇게 말함)


100을 대충 넣고 돌리면 이렇게 에러가 뜬다고 해요



64는 batch_size이고, 320이 이제 input으로 받아야 하는 dimension이라는거죠.



하지만 뭔가 좀 그러니까 수학적으로 한번 계산 해 보자면


28 * 28에서 패딩 없이 stride 1로 5*5를 통과시키니까 4칸이 가로세로에서 날라가서


24*24가 되고, max pool을 2*2짜리로 하게 되는데, MaxPool2d의 옵션은 따로 지정해주지 않으면 커널사이즈와 스트라이드 사이즈가 같기 때문에 12*12가 됩니다.


12*12에 5*5conv를 통과시키면 8*8이 되구요, 8*8짜리에서 Max Pool (2)를 하면 4*4가 됩니다.


4*4짜리 결과값이 20개의 체널이기 때문에 4*4*20개의 cell이 결과로 나오게 됩니다.


그래서 320개가 되는 것입니다 !


그럼 한번 돌려 보게 되면, Accuracy가 98%가 나온다고 합니다.


조금..! 더 좋은 결과가 나오는 것이죠 :)


한번 직접 짜보도록 합시다 !


커널 사이즈도 다르게 해 보시구요!