본문 바로가기

AI: ML,DL

[인공지능] 심층 신경망

심층 신경망

심층 신경망은 입력층과 출력층 사이에 여러 개의 은닉층이 존재하는 인공 신경망이다. 심층 신경망은 복잡한 비선형 관계를 모델링할 수 있다.

은닉층에는 활성화 함수가 있다. 활성화함수는 비선형적인 모델을 적용시켜 단순 선형 결과를 얻는 것을 피한다. 많이 사용하는 함수는 시그모이드/렐루 함수 등이 존재한다.

 

층을 만드는 방법은 이전 포스팅과 같다.

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

dense1은 은닉층이며 'sigmoid' 활성화 함수를 적용한 100개의 뉴런이 존재하는 밀집층이다. 그리고, 784개의 입력값을 갖는다. 여기서 중요한 점은 출력층의 뉴런보다는 많게 만들어야 한다는 점이다. 예를들어, 10개 클래스의 확률을 예측하는데 10개 미만의 뉴런으로 정보를 전달한다면 매우 부족할 것이다. 그리고, 다음 dense2는 출력층이다. 'softmax' 활성화 함수를 적용했으며, 클래스의 수인 10개의 뉴런이 존재한다.

 

심층 신경망 만들기

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

model.summary()

 

위 코드처럼 해당 층을 통해 심층신경망을 만든다. 출력층을 배열 가장 마지막에 두어야 한다. 심층 신경망은 이렇게 층을 추가하여 입력 데이터에 대한 연속적인 학습을 통해 개선된다. summary() 메서드를 통해 모델의 정보를 출력할 수 있다.

간단하게 설명하면, Output Shape은 (샘플 수, 뉴런 수)이다. 샘플 수는 확률적 경사 하강법의 샘플 수를 의미하는데 보통 미니 배치 방법을 활용하여 크기를 유연하게 결정할 수 있다. 뉴런 수는 앞에서 정한 해당 층의 뉴런 수이다. 그리고 Param은 '입력층X현재 층의 뉴런 수+현재 층의 절편 수'의 결과이다. 층에서 뉴런마다 1개의 절편이 존재한다.

 

 

사실 층을 추가할 때는 add() 메서드를 활용하는게 용이하다. 다음처럼 작성하면 특정 조건마다 층을 추가할 지 말 지 결정하는 방식으로 프로그래밍이 가능하기 때문이다.

model = keras.Sequential()
model.add(keras.layer.Dense(100, activation='sigmoid',input_shape=(784,)))
model.add(keras.layer.Dense(10, activation='softmax'))

 

설정 및 훈련, 평가는 이전 포스팅의 방법과 같다.

# 설정
model.compile(loss='sparse_categorical_crossentropy', metrics='accuracy')

# 훈련
model.fit(train_scaled,train_target,epochs=5)

# 평가
model.evaluate(val_scaled,val_target)

 

렐루 함수(ReLu Function)

초창기 인공 신경망의 은닉층에서는 위처럼 활성화함수로 시그모이드 함수를 자주 사용했다. 시그모이드 함수는 0~1 사이의 값만 다룬다. 이는 결국 층이 많아져 곱하면 곱할 수록 결과가 0에 수렴하게 된다. 이에 대한 방안이 렐루 함수이다.

렐루 함수는 입력이 양수일 경우 입력을 그대로 통과시키고, 음수일 경우에는 값을 0으로 만든다. 간단하게 렐루 함수는 max(0,z)로 표현한다. z가 0보다 크면 z를 출력하고, z가 0보다 작으면 0을 출력한다.

 

케라스의 Flatten Layer

앞서 이미지 데이터를 1차원으로 만들기 위해 reshape 과정을 거쳤다. 케라스에서는 이런 과정을 보다 편리하게 하기 위한 Flatten 클래스를 제공한다. 이 클래스를 거치면 입력 차원을 모두 일렬로 펼친다. (인공 신경망의 성능 기여는 없음)

 

 

아래는 렐루 함수와 Flatten을 활용하여 심층 신경망을 만들어 훈련시키는 코드이다.

model = keras.Sequential()

model.add(keras.layers.Flatten(input_shape=(28,28)))
model.add(keras.layers.Dense(100,activation='relu'))
model.add(keras.layers.Dense(10,activation='softmax'))

(train_input,train_target),(test_input,test_target)=\
keras.datasets.fashion_mnist.load_data()
train_scaled = train_input/255.0
train_scaled,val_scaled,train_target,val_target=train_test_split(train_scaled,train_target,test_size=0.2,random_state=42)

model.compile(loss='sparse_categorical_crossentropy', metrics='accuracy')
model.fit(train_scaled,train_target,epochs=5)
model.evaluate(val_scaled,val_target)

시그모이드를 활용할 때보다 성능이 아주 조금 개선됐다.

 

옵티마이저

신경망에서는 사람이 지정해 주어야하는 하이퍼파라미터들이 많다. 그 중 신경망의 가중치와 절편을 학습하기 위한 다양한 알고리즘이 존재하는데 이들 중 적절한 알고리즘이 선택되어야 한다. 이런 알고리즘을 옵티마이저라고 한다. 앞서 사용한 compile 메서드에서 사용하는 경사 하강 알고리즘은 RMSprop이라는 알고리즘이다. 외에도 SGD, Adam 등이 존재한다.

 

추가로, 최적점(경사 최하단)에 도달할 수록 학습률을 낮추는 방법을 적응적 학습률이라고 한다. 이런 적응적 학습률을 활용하면 더 안정적으로 최적점에 수렴하게 되는데 이를 사용하는 대표적인 옵티마이저는 Adagrad와 RMSprop이다.

 

이는 아래처럼 compile 과정에서 optimizer 하이퍼파라미터를 통해 지정할 수 있다.

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

 

요약

  • 심층 신경망을 통해 복잡한 비선형 모델링이 가능하다. 더 좋은 평가 가능.
  • 시그모이드 함수는 심층 신경망에 적합하지 않아 렐루 함수를 활성화 함수로 자주 사용한다.
  • Flatten 층을 추가하여 reshape 과정을 피할 수 있다.
  • 적절한 옵티마이저(신경망 학습 알고리즘)을 선택하여 모델을 개선한다.

참고

  • 혼자 공부하는 머신러닝+딥러닝(박해선 저)