[혼공머신러닝] Ch 8. 이미지를 위한 인공 신경망
2절에서는 패션 MNIST 데이터를 사용하여 합성곱 신경망을 만들고 그래프를 그려보았습니다. 그리고 3절에서는 함수형 API를 사용하여 합성곱 신경망의 시각화에 대해 알아봤습니다. 이 글은 함수형 API에 대해 다뤄보고자 작성하였습니다.
Sequential API로 만든 모델
2절에서는 신경망 모델을 만들 때에 다음과 같이 Sequential 클래스를 사용했습니다.
model = keras.Sequential()
model.add(keras.layers.Conv2D(32, kernel_size=3, activation='relu',
padding='same', input_shape=(28,28,1)))
model.add(keras.layers.MaxPooling2D(2))
model.add(keras.layers.Conv2D(64, kernel_size=(3,3), activation='relu',
padding='same'))
model.add(keras.layers.MaxPooling2D(2))
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(100, activation='relu'))
model.add(keras.layers.Dropout(0.4))
model.add(keras.layers.Dense(10, activation='softmax'))
Sequential 객체를 만들고 두 개의 합성곱-풀링 층을 만든 후 Flatten 클래스와 hidden layer, dropout층 그리고 출력층을 차례로 구성한 모델입니다.
model.summary()로 모델의 형태를 출력해보면 다음과 같습니다.
model.summary()
이를 함수형 API를 사용하여 만들어보겠습니다.
함수형 API로 만든 모델
앞서 만든 모델과 모든 조건을 동일하게 설정하여 모델을 구성합니다.
inputs = Input(shape=(28, 28, 1))
x = layers.Conv2D(32, 3, padding = 'same', activation = 'relu')(inputs)
x = layers.MaxPooling2D(2)(x)
x = layers.Conv2D(64, 3, padding = 'same', activation = 'relu')(x)
x = layers.MaxPooling2D(2)(x)
x = layers.Flatten()(x)
x = layers.Dense(100, activation = 'relu')(x)
x = layers.Dropout(0.4)(x)
outputs = layers.Dense(10, activation = 'softmax')(x)
model = keras.Model(inputs, outputs)
model.summary()
두 모델이 동일하게 만들어진 것을 확인할 수 있습니다.
두 모델의 구성을 출력해보면 다음과 같습니다.
이렇게 Sequential class로 만든 모델을 함수형 API를 사용하여 동일하게 만들어보았습니다. 여기까지 생각했을 때 함수형 API의 용도에 의문이 생길 수 있습니다. 이런 단순한 모델의 경우에는 Sequential API만을 사용하여 무리없이 구현할 수 있기 때문입니다. 그러나 모델이 복잡해지고 입력층과 출력층이 여러개일 경우, Sequential API만을 사용하여 만들 수 없습니다.
함수형 API의 장점은 모든 레이어를 개별적이고 독립적으로 정의할 수 있기 때문에 다중 입력 및 출력이 가능하다는 것입니다. 다시 말해 모든 레이어에서 원하는 만큼의 다른 레이어를 추가할 수 있습니다.
다음과 같이 3개의 입력, 각 4개의 뉴런을 가진 hidden layer 2개와 하나의 output이 있는 신경망일 경우에는 Sequential API로도 모델을 생성할 수 있습니다.
그러나 다음과 같이 2번째 hidden layer 다음에 하나의 레이어가 더 추가해서 원래의 출력값인 y1과 추가된 레이어를 통과한 출력값인 y2를 동시에 얻고싶을 때 함수형 API를 사용할 수 있습니다.
위 그림을 토대로 모델을 만들어보면 다음과 같이 표현할 수 있습니다.
##입력 레이어
input_layer = Input(shape=(3,),name='input_layer')
##2개의 히든 레이어
Layer_1 = Dense(10, activation="relu",name='Layer_1')(input_layer)
Layer_2 = Dense(10, activation="relu",name='Layer_2')(Layer_1)
##출력 레이어 y1
y1_output= Dense(1, activation="linear",name='y1_output')(Layer_2)
##정의 Branched layer
Branched_layer=Dense(10, activation="relu",name='Branched_layer')(Layer_2)
##두 번째 출력 레이어 y2
y2_output= Dense(1, activation="linear",name='y2_output')(Branched_layer)
##입력 및 출력 레이어 지정
model = Model(inputs=input_layer,outputs=[y1_output,y2_output])
그림과 동일한 구조의 모델을 만들었습니다. 두 번째 hidden layer 다음에 하나의 레이어가 더 추가되었고, 두번째 hidden layer의 출력은 y1을 예측하는데에 사용되며 동시에 Branched layer에 전달됩니다. 또한 두 번째 출력을 예측하기 위해 더 많은 레이어를 추가할 수 있습니다. 이러한 방법을 사용하여 동시에 여러 출력층을 만들 수 있습니다.
결론적으로 Sequential API를 사용하면 출력층 y1 및 y2를 예측하기 위해 2개의 다른 신경망을 구축해야 하지만, 함수형 API를 사용하면 단일 네트워크에서 두 개의 출력을 만들 수 있습니다.
또한 이보다 모델이 복잡해졌을 때에도, 함수형 API를 사용하면 훨씬 더 효율적으로 모델을 구성할 수 있습니다.
Comments