본문 바로가기

개발/딥러닝

[논문 리뷰] ImageNet Classification with Deep Convolutional Neural Networks

 

alexNet에 대한 논문을 리뷰해 보겠습니다. 깊이 들어가기보다는

 

  1. 무엇을 하는 녀석인가
  2. 데이터는 어떻게 모았는가
  3. 구조가 어떻게 되어 있는가

에 초점을 맞춰 보겠습니다. 어느 정도의 지식이 있으면 직접 구현할 수 있도록 하는 것이 목표입니다.

 

무엇을 하는 녀석인가

어떤 물체가 있는 이미지를 주면 이 물체가 무엇인지 맞추는 녀석입니다. 227 * 227 크기의 이미지를 입력으로 받고 1000개의 분류 중 어떤 것이 정답인지 맞춥니다. 테스트 데이터에서 top-1 error(모델이 내놓은 답 상위 1개 중 정답이 없을 확률)가 37.5%, top-5 error가 17%로 당시 SOTA(가장 좋은 모델)를 이겼습니다.

데이터는 어떻게 모았는가

ImageNet에는 1500만 개의 고해상도 이미지들이 있습니다. 다양한 크기의 이미지들이 있지만 모델에 넣을 때는 일정한 크기여야 합니다. 그래서 이미지의 크기를 짧은 변의 길이가 256이 되도록 크기를 바꾸고 화면 가운데를 256*256으로 잘라내었습니다. subtracting the mean activity 작업을 제외한 어떤 전처리도 하지 않았습니다.

구조가 어떻게 되어 있는가

우선 사용한 기법들에 대해 알아봅시다.

1. ReLU

$f(s)=\max(0,x)$를 사용합니다. 속도가 빨라집니다.

2. GPU 여러 개 사용

GPU 두 개를 사용해서 GPU를 병렬적으로 사용합니다. 각 GPU에 커널을 절반씩 넣고 GPU끼리 특정 레이어에서만 통신하도록 합니다. 레이어 3에서는 레이어 2의 모든 커널에서 입력을 받지만 레이어 4에서는 해당 GPU에 있는 커널만 입력으로 받습니다. 

3. Local Response Normalization

각각의 커널(필터)에 대해 정규화를 진행합니다. 이 기법의 목적은 측면 억제입니다. 어떤 값이 너무 높으면 그 주위 픽셀에 너무 큰 영향을 미치게 되는데 이를 막아주기 위한 것입니다. 구체적인 식은

$b_{x,y}^i=a_{x,y}^i/\left(k+\alpha\sum_{j=max(0,i-n/2)}^{min(N-1,i+n/2)}(a_{x,y}^j)^2\right)^{\beta}$

입니다. 조금 쉽게 쓰자면 특정 픽셀 기준으로 앞 뒤 $\frac{n}{2}$개의 커널을 이용해 해당 픽셀의 값을 억눌러 줍니다. 논문에서는 $k=2, n=5, \alpha=10^{-4}, \beta=0.75$입니다.

4. overlapping pooling

cnn의 pooling(풀링)에서 에서 풀링의 크기가 $z*z$이고 각 풀링을 $s$ 픽셀씩 떨어트리면서 이동하는 것을 생각할 수 있습니다. 만약 $s=z$면 모든 입력 픽셀이 정확히 하나의 출력 픽셀여 영향을 미치고 이것이 전통적인 풀링입니다. $s<z$면 어떤 입력 픽셀은 여러 개의 출력 픽셀에 영향을 미칩니다. 이 논문에서는 $s=2, z=3$입니다. 

5. 실제 구조

 

논문에 있는 모델을 그대로 가져왔습니다. 위 부분이 조금 잘리긴 했지만 아래쪽 구조와 동일합니다. 위 부분이 하나의 GPU에 들어가고 아래 부분이 또 다른 GPU에 들어갑니다. 총 8개의 레이어로 처음 5개는 convolutional, 나머지 3개는 fully-connected입니다. 마지막 레이어는 1000개를 출력하고 이것을 softmax 합니다. 저희는 multinomial logistic regression를 최대화하는 것이 목표입니다.

 

첫 번째

첫 번째 cnn은 227*227*3개(논문에는 224인데 논문에 적힌 게 틀렸다는 말이 있습니다.)의 입력을 받고 11*11*3 커널 96개를 사용해 55*55*48 2개를 출력합니다. 이때 stride는 4입니다. ((227 - 7) / 4 = 55)

이후 ReLU를 적용합니다. 

이후 MaxPooling을 해줍니다. 플링 크기는 3, 간격은 2입니다. 27 * 27 * 48 2개를 만듭니다.((55 - 1) / 2 =27)

이후 local response normalization를 해줍니다.

 

두 번째

5*5*48 커널 256개를 사용해 27 * 27 * 128 두 개를 출력합니다. 이때, zero-pad를 2로 주어 크기 변화가 없도록 합니다.

이후 ReLU를 적용합니다. 

이후 MaxPooling을 해줍니다. 플링 크기는 3, 간격은 2입니다. 13 * 13 * 128 2개를 만듭니다.((27 - 1) / 2 =13)

이후 local response normalization를 해줍니다.

 

세 번째

3*3*256 커널 384개를 사용해 13*13*192 두 개를 출력합니다. 이때, zero-pad를 1로 주어 크기 변화가 없도록 합니다.

이 전의 13 * 13 * 128 두 개를 합쳐서 사용하기 때문에 3*3*256이 됩니다.

이후 ReLU를 적용합니다. 

 

네 번째

3*3*192 커널 384개를 사용해 13*13*192 두 개를 출력합니다. 이때, zero-pad를 1로 주어 크기 변화가 없도록 합니다.

이후 ReLU를 적용합니다. 

 

다섯 번째

3*3*192 커널 256개를 사용해 13*13*128 두 개를 출력합니다. 이때, zero-pad를 1로 주어 크기 변화가 없도록 합니다.

이후 ReLU를 적용합니다. 

이후 MaxPooling을 해줍니다. 플링 크기는 3, 간격은 2입니다. 6 * 6 * 128 2개를 만듭니다.((13 - 1) / 2 =6)

 

여섯 번째

dense layer를 사용해 2048 2개를 만듭니다.

이후 ReLU를 적용합니다. 

 

일곱 번째

dense layer를 사용해 2048 2개를 만듭니다.

이후 ReLU를 적용합니다. 

 

열 번째

dense layer를 사용해 1000개를 만듭니다.

이후 softmax를 적용합니다. 

 

데이터 늘리기.

데이터 모으는 부분을 보면 256*256 크기로 크기를 바꿔줍니다. 하지만 모델에는 227 * 227 크기입니다. 이는 오버피팅을 줄이기 위한 기법들 때문입니다. 256*256 이미지에서 임의의 227*227 이미지를 추출하고 좌우를 뒤집습니다. 이것으로 데이터 개수를 약 2048배 늘립니다.((256-227) * (256-227) * 2. 2는 뒤집을지 말지입니다. 근데 개수가 많이 늘었다는 것이 중요하지 정확한 크기는 중요하지 않습니다.)

그리고 RGB 색에 평균 0, 표준 편차 0.1인 무작위 값을 곱해서 데이터를 더 늘릴 수 있습니다.

드롭아웃

일정 확률(0.5)로 해당 뉴런은 학습에 영향을 미치지 않습니다. 오버피팅을 줄이는 효과가 있습니다. 처음 두 fully connect에서 사용해 줍니다.