CNN | AlexNet, VGG
AlexNet은 8개의 레이어를 가진 CNN 모델로, 컨볼루션 레이어 풀링 레이어 노멀러제이션 레이어 등으로 이루어져 있다.
CNN?
이미지를 기계가 한번에 보고 인식할 수 없다. 그래서 처음에는 컨볼루션 필터를 사용해서 피쳐맵의 크기를 줄인다. 이렇게 줄어든 피쳐맵은 이미지의 세세한 부분을 볼 수 있고(엣지나 텍스쳐나 그런 거..) 필터를 여러 번 거치면서 뉴런 하나가 보는 영역은 점점 커지게 된다(점점 큰 부분을 보게 됨) 컨볼루션 필터는 특징을 추출하는 레이어라고 볼 수 있고, 풀링은 피쳐맵의 크기를 조절하거나 주요 특징을 선택하는 역할. 그리고 이런 레이어를 쌓아서 최종 결과물로 나온 피쳐맵은 1d 벡터로 변환한다. 추출된 특징을 바탕으로 fully connected layer(MLP)를 써서 최종 분류.
처음 인풋으로 들어오는 이미지는 224(픽셀) x 224(픽셀) x 3(RGB 3개 채널)이고, 아웃풋은 크기가 1000(클래스의 개수). 즉 1000개의 서로 다른 범주(강아지, 고양이, 비행기 등등)에 대해서 각 클래스에 대한 확률 점수를 나타낸다. Softmax 활성화 함수를 통과하여 모든 클래스에 대한 확률의 합이 1이 되도록 정규화되며, 가장 높은 확률의 클래스가 최종 예측 결과가 된다.
강아지는 0.9
고양이 0.03
...
컨볼루션 레이어는 5개, FCs(fully-conneted layer)는 3개로 총 8개의 레이어로 구성되어 있다. (풀링 레이어는 학습 가능한 파라미터가 없으므로 레이어 개수 셀때 제외)
컨볼루션 레이어
첫 번째 컨볼루션 레이어를 거치는 과정을 자세히 살펴보자.
인풋 이미지는 224*224*3이고, 필터 크기는 11*11*3이다. 논문에서 스트라이드는 4, 패딩은 2를 넣어줬기 때문에 아웃풋 공식에 따르면 55.25가 나와서 이미지의 크기는 224*224 -> 55*55로 줄어든다. 그리고 출력되는 채널 수는 연구자가 정하는 하이퍼파라미터인데, 11*11*3짜리 필터를 몇개를 쓸 것인지에 따라 결정된다. 알렉스넷에서는 96개를 사용했고, 이 필터들은 각기 다른 가중치값을 가진다. 1개의 필터가 연산을 거치면 55*55 짜리 하나가 나오고, 이걸 96번 반복해서 55*55*96 사이즈의 아웃풋이 나오게 된다. 예를 들면 필터1은 수직선을 감지하는 필터, 필터2는 수평선을 감지하는 필터.. 이런 식으로 각기 다른 필터들을 넣어주는 셈.
결과적으로 컨볼루션 레이어 딱 하나를 거쳤는데, 인풋이미지는 224*224 -> 55*55로 스페이셜한 디멘션은 줄었다. 하지만 채널의 개수는 3 -> 96으로 크게 늘었다. (논문에는 96개의 커널을 사용했다고 써있다. 채널 = 커널...? 음 헷갈리는 개념..)
The first convolutional layer filters the 224 × 224 × 3 input image with 96 kernels of size 11 × 11 × 3 with a stride of 4 pixels (this is the distance between the receptive field centers of neighboring neurons in a kernel map).
파이토치에서 컨볼루션 필터 사용하는 예제
torch.Size(3,32,32) 짜리 이미지가 있다고 하고,
아래처럼 써주면 3 -> 16으로 최종 채널 수가 16으로 변한다. (입력채널 수, 출력 채널 수, 커널 사이즈, 스트라이드, 패딩)
conv = nn.Conv2d(3, 16, kernel_size=3, stride=1, padding=0)
torch.Size(16,30,30)
파라미터는?
컨볼루션 레이어의 총 파라미터 수는 1개 필터당 11*11*3개만큼의 파라미터가 있다. 추가로 여기에 바이어스 1을 더해준다. 그리고 이 연산을 96번 반복한다. 총 ((11*11*3)+1) * 96 만큼의 파라미터가 있다. 첫 레이어만 거쳤는데 파라미터가 3.5만개로 엄청나게 커졌다.
Pooling Layer
첫 번째 풀링 레이어에서 55*55*96이 들어와서 27*27*96으로 아웃풋이 나온다. 연산은 3*3 필터에 s = 2, p = 0 사용. 입력으로 받은 채널 숫자 96과 아웃풋의 채널 수가 96으로 같다. (요 3*3 크기 필터에 s=2를 한 것이 딱 픽셀 한 줄씩을 겹쳐서 이동하는 것과 같은데, 이게 성능이 좋았다고)
컨볼루션 레이어에서는 원하는 만큼 필터의 개수를 써서 출력 채널의 숫자를 늘릴 수 있다. 하지만 풀링은 입력의 각 채널별로 연산을 진행하기 때문에 아웃풋의 채널도 같아야 한다. 그리고 풀링 레이어는 학습 가능한 파라미터가 0이다.
두 번째 컨볼루션 레이어
인풋으로 27*27*96 의 피쳐맵을 받아서 5*5*96 크기의 필터를 사용, s = 1, p=2 이다. 아웃풋의 스페이셜 크기는 27*27로 같으나, 필터의 개수는 256개를 써서 최종 결과의 크기는 총 27*27*256이다.
나머지 컨볼루션 레이어도 이렇게 해석하면 된다.
https://towardsdatascience.com/the-w3h-of-alexnet-vggnet-resnet-and-inception-7baaaecccc96
Activation Function
AlexNet은 렐루 함수를 사용하고 있다. 5개의 컨볼루션 레이어가 있을 때마다 ReLU 함수가 들어간다.(실험적으로 이게 젤 좋아서)
Local Response Normalization(LRN)
노멀라제이션은 차이나는 값들을 일정한 범위 안으로 조정하는 것을 말한다. 특정 값이 너무 쎄서, 주변 자잘한 값들을 모두 무시하게 만드는 경우가 있기 때문에, 이런 쎈 값의 영향력(?)을 줄여주는 것이라고 이해했는데. 강하게 활성화된 뉴런의 값을 감소시켜서 특정 뉴런만 활성화하는 것을 막았다고 한다. -> 나중에 등장한 Batch Normalization이 훨씬 더 많이 사용됨.
AlexNet는 어떻게 잘 학습되었는지 평가할 수 있을까?
학습 데이터에 대한 성능과 학습 데이터가 아닌 데이터(테스트 데이터)에 대한 성능을 측정하여 오버피팅의 정도를 비교한다. 학습 데이터의 에러가 꾸준히 줄어들고, 테스트 에러가 증가하는 시점을 기준으로 언더피팅과 오버피팅의 상태를 나눌 수 있는데, 학습 에러도 줄이면서 테스트 에러도 줄이는 방법을 찾아야 한다.
오버피팅 방지를 위한 방법
1) Data Augmentation
학습 데이터를 다양하게 변형(Augmentation)시켜서 최대한 많은 데이터로 학습할 수 있게 만들어줌. 다양성 늘리기! 원본 이미지를 뒤집거나, 자르거나, 반전시키거나 등...
2) 드롭아웃
학습시에만 적용되는 기법인데, 레이어 중간에 있는 뉴런들을 랜덤하게 몇 개를 꺼버리면서 학습 시키는 방법. 특정 뉴런의 값에 치중해 학습되는 것을 방지한다.
VGG
알렉스넷이 나오고 2년 뒤에 19개의 레이어를 써서 다시 한번 큰 성능 향상을 이끌었던 모델! 더 많은 레이어, 더 깊은 네트워크. VGG의 의미는, 단순한 구조인데 깊은 네트워크로 성능을 끌어올린 미학(!) 깊은 네트워크가 중요하구나!
VGG-F(fast), VGG-M(meduiu), VGG-S(slow)
VGG-16: 13개의 컨볼루션 레이어+3개 fcn, VGG-19: 16개의 컨볼루션 레이어+3개 fcn
알렉스넷과 비교하면 VGG는 모든 컨볼루션 레이어의 필터의 크기가 3*3으로 작아졌다. 알렉스넷은 11*11같은 필터를 초반에 써줬는데 VGG는 처음부터 3*3 필터를 여러개 쌓는 방식을 택함.
작은 필터를 쓴다는 것의 의미는 뭘까?
3*3 컨볼루션 3개는 7*7 컨볼루션 하나와 비슷한 효과를 갖는다. 하지만 더 적은 파라미터를 가짐! 액티베이션 펑션을 중간중간 써주면서 비선형성을 더 높여줄 수 있다. 동일 파라미터 대비 레이어를 더 깊게 쌓을 수 있는 효과.