2 minute read

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()

HG8-4-1

이를 함수형 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()

HG8-4-2

두 모델이 동일하게 만들어진 것을 확인할 수 있습니다.

두 모델의 구성을 출력해보면 다음과 같습니다.

HG8-4-4 HG8-4-3

HG8-4-5 HG8-4-6

이렇게 Sequential class로 만든 모델을 함수형 API를 사용하여 동일하게 만들어보았습니다. 여기까지 생각했을 때 함수형 API의 용도에 의문이 생길 수 있습니다. 이런 단순한 모델의 경우에는 Sequential API만을 사용하여 무리없이 구현할 수 있기 때문입니다. 그러나 모델이 복잡해지고 입력층과 출력층이 여러개일 경우, Sequential API만을 사용하여 만들 수 없습니다.

함수형 API의 장점은 모든 레이어를 개별적이고 독립적으로 정의할 수 있기 때문에 다중 입력 및 출력이 가능하다는 것입니다. 다시 말해 모든 레이어에서 원하는 만큼의 다른 레이어를 추가할 수 있습니다.

HG8-4-7
다음과 같이 3개의 입력, 각 4개의 뉴런을 가진 hidden layer 2개와 하나의 output이 있는 신경망일 경우에는 Sequential API로도 모델을 생성할 수 있습니다.

HG8-4-8
그러나 다음과 같이 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