05. 고급 합성곱 신경망 구조
목차
5.1 CNN의 디자인 패턴
첫 번째 패턴 - 특징 추출과 분류
- 특징 추출을 맡는 부분은 일련의 합성곱 층, 분류를 맡는 부분은 일련의 전결합층으로 구성
두 번째 패턴 - 이미지 깊이는 증가, 크기는 감소
- 합성곱 연산을 거치며 이미지의 깊이는 증가하고 크기는 감소(높이x폭x깊이)
- 입력 때의 깊이는 색상 채널(3:컬러, 1:회색조)를 의미하지만 이후 계층에서는 추출된 특징을 나타내는 특징맵이 된다.
세 번째 패턴 - 전결합층
- 대부분의 경우 모든 전결합층은 유닛 수가 같거나, 이어지는 층에서 점차 유닛 수가 감소하는 패턴을 보임
- 이어지는 층에서 유닛 수가 증가하는 경우는 매우 드물다.
- 모든 전결합층의 유닛 수를 같게해도 학습 능력이 저해되는 현상은 아직 발견하지 못함
5.2 LeNet-5
논문 제목 : Gradient-Based Learning Applied to Document Recognition
논문 요약 참고 : https://arclab.tistory.com/150
5.2.1 LeNet 구조
Input Image -> C1(합성곱층) -> TANH(활성화 함수) -> S2(서브샘플링층) -> C3 -> TANH -> S4 -> C5 -> TANH
->FC6(전결합층) -> SOFTMAX7
5.2.2 Keras로 LeNet-5 구현하기
논문 page 6~8에 실린 구조에 따라 구현하기
- 각 합성곱층의 필터 수 / C1 : 6, C3 : 16, C5 : 120
- 각 합성곱층의 커널 크기 / kernel_size : 5 x 5
- 풀링층(서브샘플링층) / average pooling(pool_size : 2x2)
- 활성화 함수 / tanh(당시에는 대칭 함수가 sigmoid 함수에 비해 가중치가 더 빨리 수렴한다고 생각함)
from keras.models import Sequential
from keras.layers import Conv2D, AveragePooling2D, Flatten, Dense
model = Sequential()
model.add(Conv2D(filters=6, kernel_size=5, strides=1, activation='tanh', input_shape=(28,28,1), padding='same'))
model.add(AveragePooling2D(pool_size=2, strides=2, padding='valid'))
model.add(Conv2D(filters=16, kernel_size=5, strides=1, activation='tanh', padding='valid'))
model.add(AveragePooling2D(pool_size=2, strides=2, padding='valid'))
model.add(Conv2D(filters=120, kernel_size=5, strides=1, activation='tanh', padding='valid'))
model.add(Flatten())
model.add(Dense(units=84, activation='tanh'))
model.add(Dense(units=10, activation='softmax'))
model.summary()
5.2.3 하이퍼파라미터 설정하기
LeNet-5
epoch | learning-rate |
2 | 0.0005 |
3(3~5) | 0.0002 |
4(6~9) | 0.00005 |
....(9 이후) | 0.00001 |
def lr_schedule(epoch):
if epoch <= 2:
lr = 5e-4
elif epoch > 2 and epoch <= 5:
le = 2e-4
elif epoch >5 and epoch <= 9:
lr = 5e-5
else:
lr = 1e-5
return lr
- lr_schedule 함수 컴파일
from keras.callbacks import ModelCheckpoint, LearningRateScheduler
lr_scheduler = LearningRateScheduler(lr_schedule)
checkpoint = ModelCheckpoint(filepath='path_to_save_file/file.hdf5',
monitor= 'val_ac',
verbose=1,
save_best_only=True)
callbacks = [checkpoint, lr_scheduler]
model.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy'])
hist = model.fit(X_train, y_train, batch_size=32, epochs=20, validation_data=(X_test, y_test), callbacks=callbacks, verbose=2, shuffle=True)
5.3 AlexNet
논문 제목 : ImageNet Classification with Deep Convolutional Neural Networks
논문 요약 참고 : https://jjuon.tistory.com/22
5.3.1 AlexNet 구조
Input Image -> CONV1 -> POOL2 -> CONV3 -> POOL4 -> CONV5 -> CONV6 -> CONV7 -> POOL8
-> FC9 -> -> FC10 -> SOFTMAX7
- 합성곱층의 필터 크기 : 11x11, 5x5, 3x3
- 최대 풀링 사용
- 과적합 방지를 위한 드롭아웃 적용
- 은닉층의 활성화 함수는 ReLU, 출력층의 활성화 함수는 소프트맥스 함수 사용
5.3.2 AlexNet에서 발전된 부분
ReLU를 활성화함수로 사용
- 학습 시간을 크게 단축시킴
- 기울기 소실 문제 해결 : 입력에 큰 차이가 있어도 sigmoid 함수의 함숫값에는 큰 차이가 나지 않음을 해결
드롭아웃층
- 신경망 모델의 과적합 방지
데이터 강화
- 레이블 값을 변화시키지 않고 원 데이터만 변형하는 방법
- 데이터 양을 늘리는 기법도 과적합 방지에 효율적임
국소 응답 정규화(Local Response Nomalization)
- 가중치가 빨리 수렴되도록하는 목적
- 최근에는 배치 정규화가 많이 사용된다.
가중치 규제화(AlexNet은 0.0005 적용)
- L2 규제화와 같은 개념
- 과적합 억제를 통한 일반화 성능 개선
model.add(Conv2D(32, (3,3) kernel_regularizer=-l2(lambda)))
다중 GPU 사용
- 분산 학습 기법 적용
5.3.3 Keras로 AlexNet 구현하기
논문 page 4에 실린 구조에 따라 구현하기
model = Sequential()
# 첫 번째 층
model.add(Conv2D(filters=96, kernel_size=(11,11), strides=(4,4), padding='valid', input_shape=(227,227,3)))
model.add(Activation('relu'))
model.add(MaxPool2D(pool_size=(3,3), strides=(2,2)))
model.add(BatchNormalization())
# 두 번째 층
model.add(Conv2D(filters=256, kernel_size=(5,5), strides=(1,1), padding='same', kernel_regularizer=l2(0.0005)))
model.add(Activation('relu'))
model.add(MaxPool2D(pool_size=(3,3), strides=(2,2), padding='valid'))
model.add(BatchNormalization())
# 세 번째 층
model.add(Conv2D(filters=384, kernel_size=(3,3), strides=(1,1), padding='same', kernel_regularizer=l2(0.0005)))
model.add(Activation('relu'))
model.add(BatchNormalization())
# 네 번째 층
model.add(Conv2D(filters=384, kernel_size=(3,3), strides=(1,1), padding='same', kernel_regularizer=l2(0.0005)))
model.add(Activation('relu'))
model.add(BatchNormalization())
# 다섯 번째 층
model.add(Conv2D(filters=256, kernel_size=(3,3), strides=(1,1), padding='same', kernel_regularizer=l2(0.0005)))
model.add(Activation('relu'))
model.add(BatchNormalization())
model.add(MaxPool2D(pool_size=(3,3), strides=(2,2), padding='valid'))
model.add(Flatten()) # CNN의 출력을 1차원으로 변환해 전결합층에 입력
# 여섯 번째 층
model.add(Dense(units=4096, activation='relu'))
model.add(Dropout(0.5))
# 일곱 번째 층
model.add(Dense(units=4096, activation='relu'))
model.add(Dropout(0.5))
# 여덟 번째 층
model.add(Dense(units=1000, activation='softmax'))
model.summary()
...........Layer 정보는 생략
5.3.4 하이퍼파라미터 설정하기
reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=np.sqrt(0.1))
optimizer = keras.optimizers.sgd(lr=0.01, momentum=0.9)
model.compile(loss='categoriacal_crossentropy', optimizer=optimizer, metrics=['accuracy'])
model.fit(X_train, y_train, batch_size=128, epochs=90, validation_data=(X_test, y_test), verbose=2, callbacks=[reduce_lr])
top-1 오차율과 top-5 오차율
: 알고리즘의 분류 성능을 나타내기 위한 개념으로 예측 결과가 틀렸더라도 정답과 얼마나 근접한지 나타내는 지표
top-1 오차율 : 분류기가 정답 클래스에 가장 높은 확률을 부여하지 않은 비율
top-5 오차율 : 정답이 예측 확률 상위 5개 안에 들어 있지 않은 비율
5.4 VGGNet
논문 제목 : Very Deep Convolutional Networks for Large-Scale Image Recognition
5.4.1 VGGNet에서 발전된 부분
- 동일하게 설정된 층(Conv, FC)을 사용해서 신경망 구조를 단순화 시킴
- 전체적인 신경망 구조는 Conv층 뒤에 Pooling층이 배치
- 모든 Conv층은 3x3 크기의 필터와 스트라이드 1, 패딩 1을 적용
- 필터 크기를 줄인 이유는 더 세밀한 특징을 추출하기 위함
- 논문에 따르면 커널 크기가 3x3 두층 쌀은 구조는 5x5과 동등하고 세개 쌓은 구조는 7x7과 동등) 하지만 파라미터
억제 효과도 존재함
- 모든 Pooling층은 2x2 크기의 풀링영역과 스트라이드 2 적용
5.4.2 VGGNet의 다양한 버전
- D와 E가 가장 일반적으로 사용된다.
- 가중치를 포함하는 층수를 붙여 각각 VGG16, VGG19라고 부른다.
신경망 유형 | A, A-LRN | B | C | D | E |
파라미터 수 | 133 | 133 | 134 | 138 | 144 |
※ Keras 코드 구현은 생략,,(너무 길어요..)
5.5 인셉션과 GoogLeNet
GoogleNet : 신경망 내부적으로 계산 자원의 효율을 높여 신경망의 층수를 늘린 인셉션 신경망 구조를 구현
논문 제목 : Going deeper with convolutions
논문 요약 참고:
5.5.1 인셉션 구조에서 발전된 부분
인셉션 모듈 : 합성곱층의 커널 크기, 풀링층의 배치를 직접 결정하는 대신 블록 전체에 똑같은 설정을 적용
- 기존 방식에서는 Conv층과 Pooling층을 번갈아 쌓아올리는 방식으로 특징 추출기를 구성하고, 뒤에 전결합층으로 구성된 분류기를 배치
- 인셉션 구조는 Conv층과 Pooling층으로 인셉션 모듈을 구성한 다음 이 인셉션 모듈과 풀링층을 쌓아 측징 추출디를 구성하고, 뒤에 전결합층으로 구성
5.5.2 단순 인셉션 모듈
- 입력을 4개의 층에 동시 입력하고 출력
5.5.3 차원 축소가 적용된 인셉션 모듈
: 단순 인셉션 모듈은 5x5 Conv층과 같은 크기의 큰 필터를 포함하기 때문에 계산 비용이 큼
그러므로 차원 축소층을 도임하여 계산 부하를 낮춤.(Conv 1x1 층 사용)
차원 축소가 적용된 단순한 인셉션 구조
5.5.4 인셉션 구조
GoogleNet 구조
- A 블록 : Conv층과 Pooling층이 번갈아 배치된 Alexnet이나 LeNet과 같은 구조
- B 블록 : 9개의 인셉션 모듈이 인셉션 모듈 2개 + Pooling층 + 인셉션 모듈 5개 + Pooling층 + 인셉션 모듈 2개 순으로 서로 쌓인 구조
- C 블록 : 전결합측와 소프트맥스층으로 구성된 신경망의 분류기 부분
※ Keras 코드 구현은 생략,,(너무 길어요..)
5.6 ResNet
논문 제목 : deep residual learning for image recognition
논문 요약 참고 : https://jxnjxn.tistory.com/22
5.6.1 ResNet에서 발전된 부분
: 층수를 대폭 늘려보자라는 컨셉(50층, 100층, 150층..)
-> 과적합을 dropout, L2 규제화, 배치 정규화를 통해 해결
스킵 연결 : 기울기 소실 문제를 해결하기 위해 뒤쪽 층의 기울기를 앞쪽 층에 직접 전달하는 별도의 경로를 추가
직관적인 코드 구현
X_shortcut = X
X = Conv2D(filters=F1, kernel_size=(3,3), strides=(1,1))(X)
X = Activation('relu')(X)
X = Conv2D(filters=F1, kernel_size=(3,3), strides=(1,1))(X)
X = ADD()(X, X_shortcut])
X = Activation('relu)(X)
5.6.2 잔차 블록
: Conv층에 스킵 연결을 추가한 구조
- 지름길 경로 : 입력을 주 경로의 ReLU 입력 전으로 전달
- 주 경로 : [CONV -> BN -> ReLU] x 3
- 잔차 블록에는 Pooling층이 없다. 대신 인셉션 구조와 비슷하게 1x1 Conv층을 사용한 다운샘플링을 적용
- 잔차 블록 처음에 1x1 Conv층을 배치하고, 출력에는 3x3 Conv층과 1x1 Conv층을 하나씩 배치해서 두 번에 걸쳐 차원 축소
- 이렇게 차원 축소가 적용된 블록을 병목 잔차 블록(bottleneck residual block)이라 한다.
- 잔차 블록을 배치하면 블록마다 입출력의 차원이 달라지는데, 이 문제를 해결하기 위해 지름길 경로 역시 주 경로의 값과 더하기 전에 다운 샘플링을 적용한다. -> 병목층(1x1 Conv층 + BN) 추가를 통해
- 이러한 구조를 축소 지름길 경로(reduce shortcut)이라고 한다.
※ Keras 코드 구현은 생략,,(너무 길어요..)
참고 : 비전 시스템을 위한 딥러닝(모하메드 엘겐디)
전체 코드 : https://github.com/moelgendy/deep_learning_for_vision_systems