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

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로 이루어져있고, 마지막 레이어의 소프트맥스 함수를 사용하여 예측을 하게된다.

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
표 57.1 : AlexNet 구조

AlexNet의 특징

  1. 활성화 함수

    AlexNet에서는 기존에 사용하던 시그모이드 함수나 하이퍼탄젠트 함수 대신에 렐루 함수(ReLU)를 사용한다. 시그모이드, 하이퍼탄젠트 함수를 사용했을 때 보다, 학습속도가 6배 가량 빨랐고(논문 주장), 지수 연산 처럼 연산량이 꽤 드는 작업이 없어 컴퓨터 자원을 많이 절약했으며, 그레디언트가 더 잘 보존되었다. AlexNet에서는 마지막 층을 제외하고는 모두 렐루 함수를 사용했다.

  2. GPU를 활용한 병렬 처리

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

  3. LRN(Local Response Normalization)

    활성화 함수로 렐루 함수를 사용했을 때, 또 하나의 장점은 시그모이드나 하이퍼탄젠트 함수에서와 달리 결과값이 양수에 한해서는 막히지 않았기 때문에 입력하는 데이터에 대한 정규화 과정이 꼭 필요하지 않다. 그럼에도 양수 방향으로 무한히 커질 가능성이 있어서 너무 큰 값이 주변 값들을 무시하게 할 수도 있기 때문에 정규화과정을 수행하는게 일반적인 관점(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로 하고, 스트라이드(stride)를 2로 설정하여 이미지의 크기를 반으로 줄였다. AlexNet에서는 이 대신 3x3 크기의 커널을 사용하고 스트라이드를 2로 설정하여, 풀링이 겹치게 하였다. 이렇게 한 결과, top-1 error 는 0.3, top-5 erorr는 0.4 정도 성능 개선이 있었다.

  5. Data Augmentation

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

    1. 224x224로 잘라낸 이미지 그리고 원데이터를 좌우반전한 이미지
      • AlexNet에서는 Data Augmentation을 위해 원데이터와 원데이터를 좌우반전한 이미지에서 임의로 224x224 이미지를 추출하여 사용했다.(원 데이터의 크기는 다양했다.) 이렇게 해서 1개의 이미지로 2048개의 이미지를 만들어낼 수 있었다. 테스트 시에는 이미지에서 상하좌우 중앙 의 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}}$$

구현

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

In [1]:
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout, BatchNormalization, Lambda
from tensorflow.keras.regularizers import l2
from tensorflow.keras import backend as K
from tensorflow.keras import optimizers
from tensorflow.keras.layers import Layer
In [2]:
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 compute_output_shape(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()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 56, 56, 96)        34944     
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 56, 56, 256)       614656    
_________________________________________________________________
local_response_normalization (None, 56, 56, 256)       0         
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 27, 27, 256)       0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 27, 27, 384)       885120    
_________________________________________________________________
local_response_normalization (None, 27, 27, 384)       0         
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 13, 13, 384)       0         
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 13, 13, 384)       1327488   
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 13, 13, 256)       884992    
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 6, 6, 256)         0         
_________________________________________________________________
flatten (Flatten)            (None, 9216)              0         
_________________________________________________________________
dense (Dense)                (None, 4096)              37752832  
_________________________________________________________________
dropout (Dropout)            (None, 4096)              0         
_________________________________________________________________
dense_1 (Dense)              (None, 4096)              16781312  
_________________________________________________________________
dropout_1 (Dropout)          (None, 4096)              0         
_________________________________________________________________
dense_2 (Dense)              (None, 1000)              4097000   
=================================================================
Total params: 62,378,344
Trainable params: 62,378,344
Non-trainable params: 0
_________________________________________________________________

질문/덧글

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