- input이 결과적으로 2개, inputs=[input_A, input_B]
- fit() 학습시 x_train은 (x_train_A, x_train_B)와 같은 형태가 되어야 함
- x_valid도 같은 형태
- 위와 같은 모델 형상은 여러개의 출력이 필요한 경우에 사용
- 그림에 있는 주요 물체를 분류하고 위치를 알아야하는 작업 (회귀와 분류를 동시에 수행)
- 동일한 데이터에서 독립적인 여러 작업을 수행할 때, 사람의 표정을 통한 감정 분류
- 규제 기법으로 사용하는 경우, 신경망 구조안에 보조 출력을 추가할 수 있음
- 보조출력을 사용해 네트워크가 나머지 네트워크에 의존하지 않고 그 자체로 유용한 것을 학습하는지 확인할 수 있음
- 보조출력을 추가하는 것은 적절한 층에 연결하고 모델의 출력 리스트에 추가하는 방식으로 수행
- 보조출력 예제
```python
input_A = keras.layers.Input(shape=[5], name="wide_input")
input_B = keras.layers.Input(shape=[6], name="deep_input")
hidden1 = keras.layers.Dense(30, activation="relu")(input_B)
hidden2 = keras.layers.Dense(30, activation="relu")(hidden1)
concat = keras.layers.concatenate([input_A, hidden2])
output = keras.layers.Dense(1, name="main_output")(concat)
aux_output = keras.layers.Dense(1, name="aux_output")(hidden2)
model = keras.models.Model(inputs=[input_A, input_B],
outputs=[output, aux_output])
model.compile(loss=["mse", "mse"], loss_weights=[0.9, 0.1], optimizer=keras.optimizers.SGD(learning_rate=1e-3))
history = model.fit([X_train_A, X_train_B], [y_train, y_train], epochs=20,
validation_data=([X_valid_A, X_valid_B], [y_valid, y_valid]))
total_loss, main_loss, aux_loss = model.evaluate(
[X_test_A, X_test_B], [y_test, y_test])
y_pred_main, y_pred_aux = model.predict([X_new_A, X_new_B])
```
- 각 출력은 자신만의 손실함수가 필요
- 보조출력보다 주 출력에 더 큰 관심을 부여하려면 가중치를 부여해 조절
### 서브클래싱 API로 동적 모델 만들기
- 시퀀셜 API와 함수형 API는 모두 선언적인 특성을 가짐
- 사용할 층과 연결 방식을 먼저 정의할 필요성이 있음
- 그 후에 모델에 데이터를 입력하여 훈련이나 추론을 시작할수 있음
- 장점
- 모델의 저장 및 복사, 공유하기가 쉬움, 모델의 구조를 출력하거나 분석하기 좋음
- 프레임워크가 크기를 짐작하고 타입을 확인하여 에러를 일찍 발견 할 수 있음
- 전체 모델이 층으로 구성된 정적 그래프이므로 디버깅 용이
- 단점
- 여러 가지 동적인 구조를 수행하기 어려움
- 이런 경우 서브클래싱 API가 좋음
- model 클래스를 상속한 다음 생성자 안에서 필요한 층을 생성, 그 다음 call() 메서드 안에 수행하려는 연산을 기술
- WideAndDeepModel 예제
```python
class WideAndDeepModel(keras.models.Model):
def __init__(self, units=30, activation="relu", **kwargs):
super().__init__(**kwargs)
self.hidden1 = keras.layers.Dense(units, activation=activation)
self.hidden2 = keras.layers.Dense(units, activation=activation)
self.main_output = keras.layers.Dense(1)
self.aux_output = keras.layers.Dense(1)
def call(self, inputs):
input_A, input_B = inputs
hidden1 = self.hidden1(input_B)
hidden2 = self.hidden2(hidden1)
concat = keras.layers.concatenate([input_A, hidden2])
main_output = self.main_output(concat)
aux_output = self.aux_output(hidden2)
return main_output, aux_output
model = WideAndDeepModel(30, activation="relu")
model.compile(loss="mse", loss_weights=[0.9, 0.1], optimizer=keras.optimizers.SGD(learning_rate=1e-3))
history = model.fit((X_train_A, X_train_B), (y_train, y_train), epochs=10,
validation_data=((X_valid_A, X_valid_B), (y_valid, y_valid)))
total_loss, main_loss, aux_loss = model.evaluate((X_test_A, X_test_B), (y_test, y_test))
y_pred_main, y_pred_aux = model.predict((X_new_A, X_new_B))
```
- 해당 방법을 통하면 함수형 API와 다르게 input 클래스의 객체를 생성할 필요가 없음
- 대신 call() 메서드의 input 매개변수를 사용, 생성자에 있는 층 구성과 call() 메서드에 있는 정방향 계산을 분리
- call() 안에서 원하는 연산을 자체적으로 생성하여 수행가능
- 단점으로는 모델을 저장하거나 복사할 수 없음
- summary()를 통한 각 층간의 연결 정보를 얻을수 없음
- 높은 유연성이 필요하지 않는다면 API와 함수형 API를 사용하는 것이 좋음
### 모델 저장과 복원
- 시퀀셜 API와 함수형 API를 사용하면 훈련된 케라스 모델을 저장하는 것은 쉬워짐
- 저장 예제
```python
model = keras.models.Sequential([
keras.layers.Dense(30, activation="relu", input_shape=[8]),
keras.layers.Dense(30, activation="relu"),
keras.layers.Dense(1)
])
model.compile(loss="mse", optimizer=keras.optimizers.SGD(learning_rate=1e-3))
history = model.fit(X_train, y_train, epochs=10, validation_data=(X_valid, y_valid))
mse_test = model.evaluate(X_test, y_test)
model.save("my_keras_model.h5")
model = keras.models.load_model("my_keras_model.h5")
model.save_weights("my_keras_weights.ckpt")
model.load_weights("my_keras_weights.ckpt")
keras는 HDF5 포멧을 사용하여 모델구조와 층의 모든 모델 파라미터를 저장, 옵티마저도 저장
일반적으로 하나의 python script에서 모델을 훈련하고 저장한 다음 하나 이상의 script에서 모델을 로드하고 예측을 만드는 데 활용
시퀀셜, 함수형 API만 가능하고 서브클래싱에서는 불가능
콜백 사용하기
fit() 메서드의 callbacks 매개변수를 사용하여 케라스가 훈련의 시작이나 끝에 호출할 객체 리스트를 지정할 수 있음 또는 에포크의 시작이나 끝, 각 배치 처리 전후에 호출할 수도 있음
콜백 예제
model = keras.models.Sequential([
keras.layers.Dense(30, activation="relu", input_shape=[8]),
keras.layers.Dense(30, activation="relu"),
keras.layers.Dense(1)
])
model.compile(loss="mse", optimizer=keras.optimizers.SGD(learning_rate=1e-3))
checkpoint_cb = keras.callbacks.ModelCheckpoint("my_keras_model.h5", save_best_only=True)
history = model.fit(X_train, y_train, epochs=10,
validation_data=(X_valid, y_valid),
callbacks=[checkpoint_cb])
model = keras.models.load_model("my_keras_model.h5") # 최상의 모델로 롤백
mse_test = model.evaluate(X_test, y_test)
'save_best_only=True' 를 통해서 최상의 검증 세트 점수에서만 모델을 저장