JS Star 블로그

기억보다는 기록을✏️ 머신러닝, 웹개발, 물리학을 공부했고 계속 배워가고 있습니다.
📌 기존에 포스팅하던 블로그에서 포스트를 옮기는 중입니다.

[Keras] Sequential vs Model 그리고 multiple output

02 Feb 2020 » machinelearning

Loss function 2개 이상을 이용해서 학습을 진행하고 싶다면 당연하게도 output이 2개 이상으로 나와야 한다. 기본적인 학습에서는 하나의 output을 내놓는 선형적인 모델을 만드는 경우가 대부분이기 때문에 Sequential을 사용하는 경우가 많다. 편의성으로 많이 사용하는 Sequential과 모델을 더 유연하게 만들 수 있는 Model의 차이점에 대해서 알아보자.

Sequential vs Model

Sequential

먼저 Sequential로 layer를 구성해보자.

from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.layers import Dense

testModel = Sequential()
testModel.add(Dense(5, input_shape=(1,)))	## input_shape을 지정하지 않으면 error를 내뱉는다.
testModel.add(Dense(10))

testModel.summary()

input_shape 대신에 input_dim을 사용할 수 있으며 차원이 있는 경우에는 input_dim + input_length을 함께 써야 하므로 애초에 input_shape을 사용하는게 더 편하다.

input_shape=(1, ) 은 input_dim=1과 같다. input_shape은 matrix 개념에서 행이 1개인 matrix를 만들겠다는 것이고, input_dim은 1차원에만 값을 넣겠다는 의미이다. (결국 같은 말이다.)

>
Model: "sequential_15"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_21 (Dense)             (None, 5)                 10        
_________________________________________________________________
dense_22 (Dense)             (None, 10)                60        
=================================================================
Total params: 70
Trainable params: 70
Non-trainable params: 0
_________________________________________________________________

SequentialInput layer를 추가해서 네트워크를 구성하지 않고, 맨 앞 layer의 parameter에서 결정한다. 결과에서 볼 수 있듯이 하나의 숫자가 들어가서 10개의 숫자를 내뱉는다.

Model

이번에는 Model을 이용해 layer를 구성해보자.

from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.layers import Input, Dense

inputLayer = Input(shape=(1,), name='input_layer')
hiddenLayer1 = Dense(5, name='hidden_layer1')(inputLayer)
hiddenLayer2 = Dense(10, name='hidden_layer2')(hiddenLayer1)
testModel = Model(inputLayer, hiddenLayer2, name='test_model')
testModel.summary()
>
Model: "test_model"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_layer (InputLayer)     [(None, 1)]               0         
_________________________________________________________________
hidden_layer1 (Dense)        (None, 5)                 10        
_________________________________________________________________
hidden_layer2 (Dense)        (None, 10)                60        
=================================================================
Total params: 70
Trainable params: 70
Non-trainable params: 0
_________________________________________________________________

Sequential과 같이 하나의 값이 들어가서 10개의 값이 나오지만 구성을 보면 Input Layer가 맨 처음에 구성되어 있음을 알 수 있다. Parameter 개수는 없기 때문에 필터느낌으로 생각하면 될 것 같다.

또 다른 점은 Sequential먼저 class를 선언하고 이후에 연속적으로 layer들을 add해 나가는 반면 Model은 하나씩 붙여나간 layer를 마지막에 최종적으로 input layer와 정리해 한번에 선언한다. (닭이 먼저냐 달걀이 먼저냐) 그래서 Sequential은 위에서부터 아래로 하나씩 추가해나가면 끝나기 때문에 직관적이다. 대신 layer들을 선형적으로만 만들어야 하기 때문에 다양하게 활용하기 힘들다.

예를들어 학습이 완료된 특정 layer를 빼와서 다른 곳에서 활용할 일이 생길 수도 있는데, 이럴 때는 Model이 더 적합하다.

Multiple Output

Output의 개수를 여러개로 사용하고 싶을 때도 Model이 더 적합하다. Output을 여러개 만들거나 Model에서 두개로 선언하면 되기 때문이다.

inputLayer = Input(shape=(1,), name='input_layer')
hiddenLayer1 = Dense(5, name='hidden_layer1')(inputLayer)
hiddenLayer2 = Dense(10, name='hidden_layer2')(hiddenLayer1)
testModel = Model(inputLayer, [hiddenLayer2, hiddenLayer2], name='test_model')
testModel.summary()
## 마지막에 output을 두개로 선언하면서 다른 두개의 loss function을 적용할 수 있다.

아래와 같이 아예 다른 갈래로 나뉘어져 두개의 output을 만들어낼 수도 있다.

inputLayer = Input(shape=(1,), name='input_layer')
hiddenLayer1 = Dense(5, name='hidden_layer1')(inputLayer)
hiddenLayer2 = Dense(10, name='hidden_layer2')(hiddenLayer1)

hiddenLayer1_1 = Dense(10, name='hidden_layer1_1')(hiddenLayer1)
hiddenLayer1_2 = Dense(20, name='hidden_layer1_2')(hiddenLayer1_1)

testModel = Model(inputLayer, [hiddenLayer2, hiddenLayer1_2], name='test_model')
testModel.summary()
## hiddenLayer1을 통과한 값들은 두개의 갈래로 나뉘어져 두개의 output을 만들어 낸다.