다운로드
작성자: admin 작성일시: 2019-01-22 11:18:38 조회수: 701 다운로드: 54
카테고리: 기타 태그목록:

AlexNet

이미지넷에서 주관하는 ILSVRC (Large Scale Visual Recognition Competition) 이라는 대회에서, 2012년 제프리 힌튼 교수팀의 AlexNet이 top 5 test error(5개의 예측값 중에 정답이 없는 경우) 기준 15.4%를 기록해 2위(26.2%)를 큰 폭으로 이기고 1위를 차지했다. 이 대회는 1000개의 클래스에 대해, 약 120만장의 이미지를 학습하고 15만장의 이미지를 테스트하여, 정답률을 겨루는 대회이다. AlexNet의 등장은 딥러닝, 특히 CNN이 본격적으로 주목 받게되는 계기가 되었고, 여기서 소개된 ReLU, Dropout 등은 지금도 업계의 표준으로 사용되고 있다.

AlexNet 구조

AlexNet의 구조는 5개의 convolution layer, 3개의 fully connected layer로 이루어져있고, 마지막 레이어의 softmax를 사용하여 예측을 하게된다.

AlexNet

유형 입력 크기 출력 크기 커널 크기 스트라이드 활성화함수
입력 (224,224,3)
Conv (224,224,3) (56,56,96) (11,11) 4 ReLU
Conv (56,56,96) (56,56,256) (5,5) 1 ReLU
LRN
maxpool (56,56,256) (27, 27, 256) (3,3) 2
Conv (27, 27, 256) (27, 27, 384) (3,3) 1 ReLU
LRN
maxpool (27, 27, 384) (13, 13, 384) (3,3) 2
Conv (13, 13, 384) (13, 13, 384) (3,3) 1 ReLcU
Conv (13, 13, 384) (13, 13, 256) (3,3) 1 ReLU
maxpool (13, 13, 256) (6,6,256) (3,3) 2
FCN (9216) (4096) ReLu
FCN (4096) (4096) ReLu
FCN (4096) (1000) softmax
표 18.4.1 : AlexNet 구조

AlexNet의 특징

  1. 활성화 함수

    AlexNet에서는 기존에 사용하던 Sigmoid나 tanh(saturated function; 포화함수) 대신에 ReLU(Rectified Linear Unit)(non-saturated function)을 사용한다. Sigmoid, tanh 함수를 사용했을 때 보다, 학습속도가 6배 가량 빨랐고(논문 주장), exponetial 연산 처럼 연산량이 꽤 드는 작업이 없어 컴퓨터 자원을 많이 절약했으며, Gredient가 더 잘 보존되었다. AlexNet에서는 마지막 Layer를 제외하고는 모두 ReLU를 사용했다.

  2. GPU를 활용한 병렬 처리

    AlexNet 저자들이 사용한 GPU모델은 GTX-580 3GB이다. 네트워크를 학습시키기엔 메모리에 한계가 있었기 때문에, 두 대의 GPU를 병렬 처리하여 사용하였다. 이 당시에는 학습을 90 epochs를 수행하는데, 5~6일이 소요되었다고 한다.

  3. Local Response Normalization

    활성화 함수로 ReLU를 사용했을 때, 또 하나의 장점은 sigmoid나 tanh 함수에서와 달리, 결과값이 양수에 한해서는 막히지 않았기 때문에, 입력하는 데이터에 대한 정규화 과정이 꼭 필요하지 않다. 하지만, 양수 방향으로 무한히 커질 수 있어, 너무 큰 값이 주변 값들을 무시하게 할 수도 있어, 정규화과정을 수행하는게 generalization 관점에서 좋다.

    • LRN $$ b_{x,y}^i = \dfrac{a_{x,y}^i}{ \left (k + \alpha \displaystyle\sum^{min(N-1, i+n/2)}_{j=max(0,i-n/2)}(a_{x,y}^j)^2 \right )^{\beta}} $$ 위 식에서 $a_{x,y}^i$ 는 이미지의 $x, y$ 좌표에서의 i 번째 필터를 의미한다. 그리고 $N$은 필터의 갯수를 의미한다. $k, n, \alpha, \beta$는 하이퍼 파라미터로 AlexNet에서는 각각 $k=2, n=5, \alpha=10^{-4}, \beta=0.75$로 설정했다. 예를 들어, 5번째 필터의 결과값은 3 ~ 7번째 결과값으로 정규화한다.
  4. Overlapping Pooling

    기존의 Pooling 방식은 2x2 kernel size에 strides는 2로 설정하여, 이미지의 크기를 반으로 줄였다. AlexNet에서는 이 대신 3x3 kernel 사이즈에 strides를 2로 설정하여, Pooling kernel이 겹치게 하였다. 이렇게 한 결과, 성능이 top-1 error 는 0.3, top-5 erorr는 0.4 정도 성능 개선이 있었다.

  5. Data Augmentation

    AlexNet에서는 과적합 문제를 방지하기 위해서, 아래에서 설명할 Dropout과 함께 Data Augmentation 을 사용했다.

    1. 224x224로 잘라낸 이미지 그리고 원데이터를 좌우반전한 이미지
      • 원래 제공되는 이미지는 256x256이었지만, AlexNet에서는 Data Augmentation을 위해 원데이터와 원데이터를 좌우반전한 이미지에서 임의로 224x224 이미지를 추출하여 사용했다. 이렇게 해서 1개의 이미지로 2048개의 이미지를 만들어낼 수 있었다. Test 시에는 이미지에서 상하좌우 중앙 의 5개이미지와 이를 반전한 5개 이미지 총 10장에 대한 예측치의 평균을 사용했다.
    2. 학습 이미지로 부터 RGB값을 변화
      • 모든 학습 이미지의 픽셀값에 대해 PCA를 수행하고 여기에 평균 0 표준편차 0.1의 정규분포에서 샘플링한 값($\alpha$)을 곱해주어 원래 픽셀에 더해줌으로써 다양한 이미지를 얻을 수 있었다. $$I_{xy} = [I_{xy}^R, I_{xy}^G, I_{xy}^B] + [v_1, v_2, v_3][\alpha_1\lambda_1, \alpha_2\lambda_2, \alpha_2\lambda_2]^T$$
  6. Dropout

    Dropout은 Fully Connected layers 의 앞 두 단계에서 사용되었다. Dropout이 없을 때 보다, 수렴하는 시간은 느리지만, 과적합 문제를 극복할 수 있었다고 한다.

  7. 최적화 과정

    • Stochastic Gradient Descent
      • batch size = 128
      • momentum = 0.9
      • weight decay = 0.0005
      • learning rate = 0.01 ($\epsilon$) $$v_{i+1} = 0.9v_i - 0.0005 \epsilon w_i - \epsilon \dfrac{\partial{L}}{\partial{w_i}}$$

구현

구현함에 앞서, 예제를 만드는 환경은 GPU 하나를 사용하고 있다. 따라서 GPU 병렬화 작업은 포함하지 않았다.

그리고, Keras의 Local response normalization(LRN) 명령이 없어졌다. 그래서 아래와 같이 직접 개발하여 사용한다.

In [1]:
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout, BatchNormalization, Lambda
from keras.regularizers import l2
from keras import backend as K
from keras import optimizers
Using TensorFlow backend.
In [2]:
from keras import backend as K
from keras.engine.topology import Layer


class LocalResponseNormalization(Layer):

    def __init__(self, n=5, alpha=1e-4, beta=0.75, k=2, **kwargs):
        self.n = n
        self.alpha = alpha
        self.beta = beta
        self.k = k
        super(LocalResponseNormalization, self).__init__(**kwargs)

    def build(self, input_shape):
        self.shape = input_shape
        super(LocalResponseNormalization, self).build(input_shape)

    def call(self, x):
        _, r, c, f = self.shape 
        squared = K.square(x)
        pooled = K.pool2d(squared, (self.n, self.n), strides=(1,1), padding="same", pool_mode='avg')
        summed = K.sum(pooled, axis=3, keepdims=True)
        averaged = self.alpha * K.repeat_elements(summed, f, axis=3)
            
        denom = K.pow(self.k + averaged, self.beta)
        
        return x / denom 
    
    def get_output_shape_for(self, input_shape):
        return input_shape 
In [3]:
input_shape = (224, 224, 3)

model = Sequential()
model.add(Conv2D(96, (11, 11), strides=4,
                 padding='same', input_shape=input_shape))
model.add(Conv2D(256, (5, 5), activation='relu', padding='same'))
model.add(LocalResponseNormalization(input_shape=model.output_shape[1:]))
model.add(MaxPooling2D(pool_size=(3, 3), strides=2))
model.add(Conv2D(384, (3, 3), activation='relu', padding='same'))
model.add(LocalResponseNormalization(input_shape=model.output_shape[1:]))
model.add(MaxPooling2D(pool_size=(3, 3), strides=2))
model.add(Conv2D(384, (3, 3), activation='relu', padding='same'))
model.add(Conv2D(256, (3, 3), activation='relu', padding='same'))
model.add(MaxPooling2D(pool_size=(3, 3), strides=2))
model.add(Flatten())
model.add(Dense(4096, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(4096, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(1000, activation='softmax'))

optimizer = optimizers.SGD(lr=0.01, decay=5e-5, momentum=0.9)
model.compile(loss='categorical_crossentropy',
              optimizer=optimizer, metrics=['accuracy'])
model.summary()
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1 (Conv2D)            (None, 56, 56, 96)        34944     
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 56, 56, 256)       614656    
_________________________________________________________________
local_response_normalization (None, 56, 56, 256)       0         
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 27, 27, 256)       0         
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 27, 27, 384)       885120    
_________________________________________________________________
local_response_normalization (None, 27, 27, 384)       0         
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 13, 13, 384)       0         
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 13, 13, 384)       1327488   
_________________________________________________________________
conv2d_5 (Conv2D)            (None, 13, 13, 256)       884992    
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 6, 6, 256)         0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 9216)              0         
_________________________________________________________________
dense_1 (Dense)              (None, 4096)              37752832  
_________________________________________________________________
dropout_1 (Dropout)          (None, 4096)              0         
_________________________________________________________________
dense_2 (Dense)              (None, 4096)              16781312  
_________________________________________________________________
dropout_2 (Dropout)          (None, 4096)              0         
_________________________________________________________________
dense_3 (Dense)              (None, 1000)              4097000   
=================================================================
Total params: 62,378,344
Trainable params: 62,378,344
Non-trainable params: 0
_________________________________________________________________

질문/덧글

아직 질문이나 덧글이 없습니다. 첫번째 글을 남겨주세요!