본 포스팅 한빛미디어의 <혼자공부하는 머신러닝+딥러닝(박해선 저)>를 요약 정리했습니다.


1. 2개의 층


케라스 API를 사용해 MNIST 데이터셋을 불러온다.
1절과 같이 학습시키고 인공 신경망 모델에 층을 2개 추가한다.

입력층과 출력층 사이에 밀집층이 추가된 것으로 이 사이에 있는 모든 층을 은닉층이라 부른다.
은닉층 옆에 활성화 함수가 붙는데 이는 신경망 층의 선형 방정식의 계산 값에 적용하는 함수이다.
활성화 함수는 출력층에 적용하는 활성화 함수보다 비교적 자유롭다.

은닉층에서 선형적인 산술 계산만 수행한다면 수행 역할이 없는 셈이 되어 선형 계산을 적당하게 비선형적으로 비틀어야 한다.
다음 층의 계산과 단순히 합쳐지는 것을 방지하고 나름의 역할을 하도록 하는 것이다.

많이 사용하는 활성화 함수 중 하나는 시그모이드 함수이다.

이 함수는 뉴런의 출력을 z값을 0과 1 사이로 압축하는데
시그모이드 활성화 함수를 사용한 은닉층과 소프트맥스 함수를 사용한 출력층을 케라스의 Dense 클래스로 만들어 보자.

dense1 = keras.layers.Dense(100, activation='sigmod', input_shape=(784,))
dense2 = keras.layers.Dense(10, activation='softmax')

dense1이 은닉층이고 100개의 뉴런을 가진 밀집층이다. 은닉층의 뉴런 개수를 정하는데는 특별한 기준이 없다.
하지만 적어도 출력층의 뉴런보다는 많게 만들어야 한다. 부족한 정보가 전달될 수 있기 때문이다.
dense2는 출력층으로 10개의 클래스를 분류하므로 10개의 뉴런을 둔 것이다.

2. 심층 신경망 만들기


앞서 만든 두 객체를 Sequential클래스에 추가해서 심층 신경망을 만들어 보자.

model = keras.Sequential([dense1, dense2])

Sequential 클래스에서 여러 개의 층을 추가하려면 두 객체를 리스트로 만들어 전달해야 한다. [dense1, dense2]
이 리스트는 가장 처음 등장하는 은닉층에서 마지막 출력층의 순서로 나열해야 한다.
출력층을 가장 마지막에 두어야 한다는 것이다.

케라스는 모델의 summary() 메서드를 호출하면 층에 대한 유용한 정보를 얻을 수 있는데

model.summary()

이런 식으로 확인 가능하다.

맨 첫 줄에 모델 이름이 나오면서 이 모델에 들어 있는 층이 순서대로 나열된다. 결정트리
위처럼 층마다 층 이름, 클래스, 출력 크기, 모델 파라미터 개수가 출력되는 것을 볼 수 있다.
위의 정보를 보고 모델의 층들을 파악하면 된다.

3. 층을 추가하는 다른 방법


Seqeuntial 클래스에 층을 추가하는 다른 방법으로 이 클래스 생성자 안에서 바로 Dense 클래스의 객체를 만드는 것이 있다.

model = keras.Sequential([
    keras.layers.Dense(100, activation='sigmoid', input_shape=(784,), name='hidden'),
    keras.layers.Dense(10, activation='softmax', name='output')
], name='패션 MNIST 모델')

위와 같이 작성하게 되면 층을 한눈에 쉽게 알아볼 수 있고 name 매개변수로 모델의 이름을 지정할 수 있다.

Dense 클래스를 사용해 sigmod와 softmax를 사용한 것과 같이 Seqeuntial 클래스의 객체를 만들고 이 객체의 add() 메서드를 호출해 층을 추가할 수 있다.
이와 같이 만들어진 모델을 compile() 설정을 하여 에포크를 지정해 훈련한다.

4. 렐루 함수


시그모이드 함수는 올바른 출력을 만드는데 신속하게 대응하지 못한다는 단점이 있다.
이를 보완하기 위해 제안된 활성화 함수가 렐수 함수이다.

렐루 함수는 양수일 경우 입력을 그냥 통과 시키고, 음수일 경우에는 0으로 만든다.
따라서 max(0, z)와 같은 형식으로 쓸 수 있고 이미지 처리에서 좋은 성능을 낸다.

렐루 함수를 사용하기 전 Flatten 층을 살펴보자.
Flatten은 배치 차원을 제외한 나머지 입력 차원을 모두 일렬로 펼치는 역할을 하는데, 층처럼 입력층과 은닉층 사이에 추가하기 때문에 이를 층이라 부른다.
따라서, 입력층 바로 뒤에 코드를 추가하면 된다.

Flatten 층을 신경망 모델에 추가하면 입력값의 차원을 짐작할 수 있는 것에 장점이 있다.
input_shape 매개변수를 Flatten 층으로 옮기고 첫 번째 Dense 층의 활성화 함수를 relu로 바꾸어 확인해 보면 알 수 있다.
시그모이드 함수를 사용했을 때보다 성능이 향상되고, 검증 세트에서도 몇 퍼센트 성능이 향상된다.

5. 옵티마이저


옵티마이저의 종류로 Adam, Momentum, RMSprop, SGD 등이 존재한다.
가장 기본적인 옵티마이저는 확률적 경사 하강법인 SGD이다.

model.compile(optimizer='sgd', loss='sparse_categorical_crossentropy', metrics='accuracy')

또는

sgd = keras.optimizers.SGD()
model.compile(optimizer=sgd, loss='sparse_categorical_crossentropy', metrics='accuracy')

이렇게 SGD 옵티마이저를 불러온다.
기본 경사 하강법 옵티마이저는 모두 SGD 클래스에서 제공하고, SGD 클래스의 momentum 매개변수의 기본값은 0이다.
모멘텀 최적화를 사용하여 보통 momentum 매개변수는 0.9 이상을 지정한다.

SGD 클래스의 nesterov 매개변수를 기본값 False에서 True로 바꾸면 네스테로프 모멘텀 최적화를 사용한다.
이는 모멘텀 최적화를 2번 반복하여 구현한다. 기본 확률적 경사 하강법보다는 더 나은 성능을 제공한다.

모델이 최적점에 가까이 갈수록 학습률을 낮출 수 있다. 이를 적응적 학습률이라고 한다.
학습률 매개변수를 튜닝하는 수고를 덜 수 있다는 것이 장점이며, 대표적으로 Adagrad, RMSprop가 있다.


모멘텀 최적화와 RMSprop의 장점을 접목한 것이 Adam이다.
이전에 학습한 것과 같이 optimizer을 ‘adam’으로 설정해 훈련하면 기본 RMSprop 보다 조금 나은 성능을 보여준다.