핸즈온 머신러닝을 공부하면서 정리하고 있습니다. 11장 심층 신경망 #8

in #kr5 years ago (edited)

머신러닝에 대한 책을 5권에서 6권정도 읽고 있는데 잘 이해가 안되는 부분이 참 많습니다. 그래서 내용을 필사하면서 직접 코드를 입력하면서 반복해서 보고 있습니다. 작년에 보았던 내용들 보다 더 많이 이해가 되고 점점 쉽게 느껴지는 부분도 생기네요. ^^

아래와 같은 순서로 책을 보시면됩니다. 파이썬 언어를 공부해야 합니다. => 판다스를 사용할 수 있어야 합니다. => 머신러닝, 딥러닝을 공부할 수 있습니다. 제가 정리한 글에 있습니다. 이런 순서로 공부하고 선형대수나 미분에 대한 내용을 개발자를 위한 수학책으로 따로 정리하면 될 것 같습니다. 좌절과 희열을 반복하면서 보고 있는데 점점 좌절보다는 희망을 보고 있습니다. 기계학습과 강화 학습을 공부하시는 모든 분들 화이팅입니다. ~~~~

https://steemit.com/kr/@papasmf1/73cj22

핸즈온 머신러닝 책의 소스는 아래의 깃허브에 있습니다. 참고하실 수 있습니다.

https://github.com/rickiepark/handson-ml

제가 테스트하고 실습하는 환경은 맥에 아나콘다 최근 패키지를 설치해서 주피터랩으로 실행하고 있습니다. 아나콘다 패키지를 사용하는 경우에 텐서플로는 쉽게 설치할 수 있습니다. ^^

11장 심층 신경망 훈련을 정리해 보았습니다.

고해상도 이미지에서 수백 종의 물체를 감지해야 하는 것처럼 아주 복잡한 문제를 다뤄야 한다면 어떻게 해야 할까요? 아무도 수백 개의 뉴런을 가진 10개 층이 수십만 개의 연결로 이어져 있는 훨씬 더 깊은 심층 신경망을 훈련시켜야 할 것입니다. 이건 그릭 쉬운 일이 아닙니다.

 첫째, 까다로운 그래디언트 소실 vanishing gradient(또는 그래디언트 폭수 exploding gradient)문제에 직면할 것입니다.
 둘째, 이런 대규모 신경망에서는 훈련이 극단적으로 느려질 것입니다.
 셋째, 수백만 개의 파라미터를 가진 모델은 훈련 세트에 과대적합될 위험이 매우 큽니다.

이 장에서는 이 문제들을 차례대로 살펴보고 해결 방법을 제시하겠습니다.

11.1 그래디언트 소실과 폭주 문제
안타깝게도 알고리즘이 하위층으로 진행됨에 따라 그래디언트는 점점 작아지는 경우가 많습니다. 결국 경사 하강법이 하위층의 연결 가중치를 실제 변경되지 않은 채로 둔다면 훈련이 좋은 솔루션으로 수렴되지 않습니다. 이 문제를 그래디언트 소실이라고 합니다. 어떤 경우엔 반대 현상이 일어날 수 있습니다. 그래디언트가 점점 커져 여러 개의 층이 비정상적으로 큰 가중치로 갱신되면 알고리즘은 발산 diverse하게 됩니다. 이 문제를 그래디언트 폭주라고 하며 순환 신경망에서 주로 나타납니다.
로지스틱 활성화 함수를 보면 입력의 절댓값이 크면 0이나 1로 수렴해서 기울기가 0에 매우 가까워지는 것을 알 수 있습니다. 그래서 역전파가 될 때 사실상 신경망으로 전파시킬 그래디언트가 거의 없고 조금 있는 그래디언트는 최상위층에서부터 역전파가 진행됨에 따라 점차 약해져서 실제로 아래쪽 층에는 아무것도 도달하지 않게 됩니다.

#텐서플로우 1.12에서 실행

파이썬 2와 파이썬 3 지원

from future import division, print_function, unicode_literals

공통

import numpy as np
import os

일관된 출력을 위해 유사난수 초기화

def reset_graph(seed=42):
tf.reset_default_graph()
tf.set_random_seed(seed)
np.random.seed(seed)

맷플롯립 설정

%matplotlib inline
import matplotlib
import matplotlib.pyplot as plt
plt.rcParams['axes.labelsize'] = 14
plt.rcParams['xtick.labelsize'] = 12
plt.rcParams['ytick.labelsize'] = 12

한글출력

plt.rcParams['font.family'] = 'AppleGothic'
plt.rcParams['axes.unicode_minus'] = False

그림을 저장할 폴더

PROJECT_ROOT_DIR = "."
CHAPTER_ID = "deep"

def save_fig(fig_id, tight_layout=True):
path = os.path.join(PROJECT_ROOT_DIR, "images", CHAPTER_ID, fig_id + ".png")
if tight_layout:
plt.tight_layout()
plt.savefig(path, format='png', dpi=300)

#그래디언트 폭주 소실 문제
def logit(z):
return 1 / (1 + np.exp(-z))

z = np.linspace(-5, 5, 200)

plt.plot([-5, 5], [0, 0], 'k-')
plt.plot([-5, 5], [1, 1], 'k--')
plt.plot([0, 0], [-0.2, 1.2], 'k-')
plt.plot([-5, 5], [-3/4, 7/4], 'g--')
plt.plot(z, logit(z), "b-", linewidth=2)
props = dict(facecolor='black', shrink=0.1)
plt.annotate('수렴', xytext=(3.5, 0.7), xy=(5, 1), arrowprops=props, fontsize=14, ha="center")
plt.annotate('수렴', xytext=(-3.5, 0.3), xy=(-5, 0), arrowprops=props, fontsize=14, ha="center")
plt.annotate('선형', xytext=(2, 0.2), xy=(0, 0.5), arrowprops=props, fontsize=14, ha="center")
plt.grid(True)
plt.title("로지스틱 활성화 함수", fontsize=14)
plt.axis([-5, 5, -0.2, 1.2])

save_fig("sigmoid_saturation_plot")
plt.show()

스크린샷 2019-03-05 오전 10.49.36.png

11.1.1 세이비어 초기화와 He 초기화
글로럿과 벤지오는 그들의 논문에서 이 문제를 크게 완화시키는 방법을 제언합니다. 예측을 할 때는 정방향으로, 그래디언트를 역전파할 때는 역방향으로 양방향 신호가 적절하게 흘러야 합니다. 신호가 죽거나 폭주 또는 소멸하지 않아야 합니다. 그들은 적절한 신호가 후르기 위해서는 각 층의 출력에 대한 분산이 입력에 대한 분산과 같아야 한다고 주장합니다.

11.1.2 수렴하지 않는 활성화 함수
글로럿과 벤지오의 2010년 논문에서 얻은 통찰 줄 아하는 활성화 함수를 잘못 선택하면 자칫 그래디언트의 소실이나 폭주로 이어질 수 있다는 것입니다. ReLU함수는 특정 양수값에 수렴하지 않는다는 커다른 장점이 있습니다. 그리고 계산도 빠릅니다.

11.1.3 배치 정규화
ELU(또는 다른 ReLU변종)과 함께 He초기화를 사용하면 훈련 초기 단계에서 그래디언트 소실이나 폭주 문제를 크게 감소시킬 수 있지만, 훈련하는 동안 다시 발생하지 않으리란 보장은 없습니다.
2015년 한 논문에서 세르게이 아이오페와 크리스티안 세게디가 그래디언트 소실과 폭주 문제를 해결하기 위한 배치 정규화 Batch Normalization(BN)기법을 제한했습니다. 더 일반적으로는, 훈련하는 동안 이전 층의 파라미터가 변함에 따라 각 층에 들어오는 입력의 분포가 변화되는 문제입니다(내부 공변량 변화 문제라고 부릅니다).

텐서플로를 사용해 배치 정규화 구현하기
텐서플로는 손쉽게 입력값을 중앙에 정렬하고 정규화해주는 tf.nn.batch_normalization()함수를 제공하지만, (앞서 이야기한 대로 훈련할 때는 미니배치, 테스트 시에는 전체 데이터셋을 기반으로) 평균과 표준편차를 직접 계산해 이 함수의 매개변수로 전달해야 합니다. 하지만 이는 자주 편리한 방법은 아닙니다. 대신 다음 코드처럼 이 모든 일을 처리해주는 tf.layers.batch_normalization()함수를 사용하는 편이 좋습니다.

11.1.4 그래디언트 클리핑
그래디언트 폭주 문제를 줄이는 쉬운 방법은 역전파될 때 일정 임계값을 넘어서지 못하게 그래디언트를 그냥 단순히 잘라내는 것입니다. 이를 그래디언트 클리핑 Gradient Clipping이라고 합니다.

11.2 미리 훈련된 층 재사용하기
일반적으로 아주 큰 규모의 DNN을 처음부터 새로 훈련시키는 것은 좋은 생각이 아닙니다. 해결하려는 것과 비슷한 유형의 문제를 처리한 신경망이 이미 있는지 찾아보고 그런 다음 그 신경망의 하위칭을 재사용하는 것이 좋습니다. 이를 전이 학습 transfer learning이라고 합니다. 이 방법은 훈련 속도를 크게 높여줄 뿐만 아니라 필요한 훈련 데이터도 훨씬 적습니다.
예를 들어 동물, 식물, 자동차, 생활용품을 포함하여 100개의 카테고리로 구분된 이미지를 분류하도록 훈련시킨 DNN을 가지고 있다고 가정합니다. 그리고 이제 구체적인 자동차의 종류를 분류하는 DNN을 훈련시키려 합니다. 이런 작업들은 비슷한 점이 많으므로 첫 번째 신경망의 일부를 재사용해봐야 합니다.

11.2.1 텐서플로 모델 재사용하기
원본 모델이 텐서플로를 사용해 훈련되었다면 간단하게 바로 복원해서 새로운 작업에 훈련시킬 수 있습니다.

11.2.2 다른 프레임워크의 모델 재사용하기
만약 모델이 다른 프레임워크로 훈련되어 있다면 수동으로 (예를 들어 씨아노로 훈련된 모델이면 씨아노 API를 사용하여) 모델 파라미터를 읽어 들여 적절한 변수에 할당해야 합니다.

11.2.3 신경망의 하위층을 학습에서 제외하기
첫 번째 DNN의 하위층은 이미지에 있는 저수준 특성을 감지하도록 학습되어서 다른 이미지 분류 작업에 유용할 것 같습니다. 그러므로 이 층들은 그냥 있는 그대로 재사용할 수 있습니다. 일반적으로 새로운 DNN을 훈련시킬 때 재사용되는 층등의 가중치를 ‘동결’하는 것이 좋습니다.

11.24 동결된 층 캐싱하기
동결된 층은 변하지 않기 때문에 각 훈련 샘플에 대해 가장 위쪽의 동결된 층에서 나온 출력을 캐싱하는 것이 가능합니다. 전체 데이터셋에 대한 훈련이 여러 번 반복되기 때문에 훈련 샘플마다 동결된 층을 한 번만 거친다면(에포크마다 한 번씩이 아니라) 학습 속도를 크게 높을 수 있습니다.

11.2.5 상위층을 변경, 삭제, 대체하기
원본 모델의 출력층은 새로운 작업에는 거의 쓸모가 없고 심지어 새 작업을 위한 출력 뉴런 수도 같지 않을 수 있기 때문에 보통 교체됩니다.

11.2.6 모델 저장소
모델 저장소 model zoo에서 찾는 것입니다. 많은 사람이 다양한 문제에 대해 머신러닝 모델을 훈련시키고 있고, 친절하게도 미리 훈련된 모델을 공개하고 있습니다.
텐서플로는 https://github.com/tensorflow/models에 자체 모델 저장소를 가지고 있습니다. 특히 여기에는 VGG, Inception, ResNet과 같은 가장 성능이 뛰어난 이미지 분류 모델들이 대부분 포함되어 있습니다.

11.2.7 비지도 사전 훈련
레이블된 훈련 데이터가 많지 않은 복잡한 문제가 있는데, 아쉽게도 비슷한 작업에 대해 훈련된 모델을 찾을 수 없다고 가정합시다. 이럴 때도 방법이 전혀 없는 것은 아닙니다. 당연하지만 먼저 더 많은 레이블된 훈련 데이터를 모아보세요. 이것이 너무 힘들고 비용이 많이 든다면 비지도 사전 훈련 unsupervised pertraining을 해볼 수도 있습니다. 즉, 레이블이 없는 훈련 데이터가 많다면 제한된 볼츠만 머신이나 오토인코더 같은 비지도 특성 추출 알고리즘을 사용해 맨 하위층부터 위로 올라가면서 차례로 한 층씩 학습시킬 수 있습니다.

11.2.8 보조 작업으로 사전훈련
마지막 선택사항은 레이블된 훈련 데이터를 쉽게 얻거나 생성할 수 있는 보조 작업에 첫 번째 신경망을 훈련시키는 것입니다. 그리고 이 신경망의 하위층을 실제 작업을 위해 재사용합니다. 첫번째 신경망의 하위층은 두번째 신경망에 재사용될 수 있는 특성 추출기를 학습하게 됩니다.
예를 들어 수백만 개의 문장을 내려받아 ‘좋은 샘플’이라고 레이블하고, 문장의 단어를 무작위로 바꿔 ‘나쁜 샘플’이라고 레이블합니다. 신경망이 ‘강아지가 잔다 The dog sleeps’는 좋은 문장, ‘강아지 그들 The dog they’는 나쁜 문장이라고 구분할 수 있다면 언어에 대해 꽤 많이 알고 있는 것입니다. 이 하위층을 재사용하면 여러 가지 언어 처리 작업에 도움이 될 것입니다.

11.3 고속 옵티마이저
아주 큰 심층 신경망은 훈련이 심각하게 느릴 수 있습니다. 지금까지 훈련 속도를 높이는 네 가지 방법을 보았습니다.
훈련 속도를 크게 높일 수 있는 또 다른 방법으로 표준적인 경사 하강법 옵티마이저 대신 더 빠른 옵티마이저를 사용할 수 있습니다. 이 절에서는 가장 인기 있는 옵티마이저인 모멘텀 최적화, 네스테로프 가속 경사, AdaGrad, RMSProp, Adam옵티마이저를 소개하겠습니다.

11.3.1 모멘텀 최적화
볼링공이 매끈한 표면의 완만한 경사를 따라 굴러간다고 합시다. 처음에는 느리게 출발하지만 종단속도에 도달할 때까지는 빠르게 가속될 것입니다. 이것이 보리스 폴락이 1964년에 제안한 모멘텀 최적화의 간단한 원리입니다.

11.3.2 네스테로프 가속 경사
네스테로프 모멘텀 최적화 또는 네스테로프 가속 경사는 1983년 유리 네스테로프가 제안한 모멘텀 최적화의 한 변종으로 기본 모멘텀 최적화보다 거의 항상 더 빠릅니다. 기본 아이디어는 현재 위치가 아니라 모멘텀의 방향으로 족므 앞서서 비용 함수의 그래디언트를 계산하는 것입니다.

11.3.3 AdaGrad
한쪽이 길쭉한 그릇 문제를 다시 생각해 봅시다. 경사 하강법은 가장 가파른 경사를 따라 빠르게 내려가기 시작해서 골짜기 아래로 느리게 이동합니다. 알고리즘이 이를 일찍 감지하고 전역 최적점 쪽으로 좀 더 정확한 방향을 잡았으면 좋았을 것입니다.
AdaGrad알고리즘은 가장 가파른 차원을 따라 빠르게 내려가기 시작해서 골짜기 아래로 느리게 이동합니다. 알고리즘이 이를 일찍 감지하고 전역 최적점 쪽으로 좀 더 정확한 방향을 잡았으면 좋았을 것 입니다.

11.3.6 학습률 스케쥴링
좋은 학습률을 찾는 것은 쉬운 일이 아닙니다. 학습률을 너무 크게 잡으면 훈련이 실제로 발산할 수 있습니다. 만약 조금 높게 잡으면 처음에는 매우 빠르게 진행하겠지만 최적점 근처에서는 요동이 심해져 수렴하지 못할 것입니다. 컴퓨팅 자원이 한정적이라면 차선의 솔루션을 만들기 위해 완전히 수렴하기 전에 훈련을 멈추어야 합니다.

11.4 과대적합을 피하기 위한 규제 방법
심층 신경망은 전형적으로 수맨 개, 때로는 수백만 개의 파라미터를 가지고 있습니다. 파라미터가 많기 때문에 네트워크의 자유도가 매우 높으며 크고 복잡한 데이터셋을 학습할 수 있습니다. 하지만 이런 높은 자유도는 훈련 세트에 과대적합되기 쉽다는 것을 의미하기도 합니다.

11.4.2 조기 종료
훈련 세트에 과대적합되는 것을 피하기 위한 좋은 방법 하나는 조기 종료입니다. 검증 세트의 성능이 떨어지기 시작할 때 훈련을 중지시키기만 하면 됩니다.

11.4.3 드롭아웃
심층 신경망에서 가장 인기 있는 규제 방법은 드롭아웃dropout (제외)입니다. 이 방식은 2012년에 제프리 힌튼이 제안했고, 나중에 다른 논문에서 더 자세히 설명되었으며 아주 잘 작동된다고 입증되었습니다.
이 알고리즘은 매우 간단합니다. 매 훈련 스텝에서 각 뉴런은 임시적으로 드롭아웃될 확률P를 가집니다. 즉, 이번 훈련 스넵에는 와넌히 무시되지만 다음 스넵에는 활성화될 수 있습니다. 하이퍼파라미터 p를 드롭아웃 비율이라고 하며 보통 50%로 지정합니다.

11.4.4 맥스-노름 규제
신경망에서 아주 널리 사용되는 또 다른 규제 기법은 맥스-노름 규제입니다.

11.4.5 데이터 증식
마지막 규제 기법인 데이터 증식은 기존의 데이터에서 새로운 데이터를 생성해 인공적으로 훈련 세트의 크기를 늘립ㅈ니다. 이 방식은 과대적합을 줄이므로 규제의 방도로 사용됩니다. 이 기법은 실제와 같은 훈련 샘플을 생성하는 것입니다.
예를 들어 버섯 이미지를 구분하는 모델이 있다면 훈련 센트에 있는 모든 이미지를 다양하게 조금씩 이동, 회전하거나 크기를 바꿔서 만든 이미지를 훈련 세트에 추가합니다. 이렇게 하면 모델이 사진에 있는 버섯의 위치, 각도, 크기에 덜 민감해집니다.

11.5 실용적 가이드라인
이 장에서 많은 종류의 기법을 다루어서 어떤 것을 써야 할지 궁금할 수 있습니다.
아래의 설정이 대부분의 경우에 잘 맞을 것입니다.

기본 DNN설정
초기화 He초기화
활성화 함수 ELU
정규화 배치 정규화
규제 드롭아웃
옵티마이저 네스테로프 가속 경사
학습률 스케쥴링 없음

Coin Marketplace

STEEM 0.27
TRX 0.11
JST 0.031
BTC 67879.12
ETH 3787.66
USDT 1.00
SBD 3.46