이글은 다음 문서를 참조합니다.

https://www.tensorflow.org/alpha/guide/keras/overview

이 카테고리의 목적은 overview는 한글번역이 되어 있으나, 그 외에 것은 영어로 되있어 공부할 겸 번역한것입니다. 

그렇다고 overview를 빼놓긴 좀 그러니 추가해서 저 사이트의 가이드에 따라 끝까지 진행해보겠습니다.


이 글에는 즉시실행, Estimator, pipeline이 포함됩니다.


고급 모델 만들기

함수형 API

tf.keras.Sequential 모델은 단순히 층을 쌓은 것으로 임의의 구조를 표현할 수 없습니다. 함수형 APi는 다음과 같은 복잡한 모델 구조를 만들 수 있습니다.

- 다중 입력 모델

- 다중 출력 모델

- 층 공유

- 데이터 흐름이 차례대로 진행되지 않는 모델 ( ex: resnet)


함수형 API로 모델을 만드는 방식은 다음과 같습니다.

1. 하나의 층 객체는 호출 가능하고 텐서를 반환합니다.

2. tf.keras.Model 객체를 정의하기 위해 입력 텐서와 출력 텐서를 사용합니다.

3. 이 모델은 Sequential 모델과 동일한 방식으로 훈련됩니다.


다음 코드는 함수형 API를 사용하여 간단한 완전 연결 네트워크 예시입니다.

inputs = tf.keras.Input(shape=(32,))  # 입력 플레이스홀더를 반환합니다.

# 층 객체는 텐서를 사용하여 호출되고 텐서를 반환합니다.
x = layers.Dense(64, activation='relu')(inputs)
x = layers.Dense(64, activation='relu')(x)
predictions = layers.Dense(10, activation='softmax')(x)
model = tf.keras.Model(inputs=inputs, outputs=predictions)

# 컴파일 단계는 훈련 과정을 설정합니다.
model.compile(optimizer=tf.keras.optimizers.RMSprop(0.001),
              loss='categorical_crossentropy',
              metrics=['accuracy'])

# 5번의 에포크 동안 훈련합니다.
model.fit(data, labels, batch_size=32, epochs=5)

tf.keras.Sequential 모델과 다르게 Input과 Model객체를 통해 입력과 출력을 객체로 만들어 사용하고 있습니다.


모델 클래스 상속

tf.keras.Model 클래스를 상속하고 자신만의 forward pass를 정의하여 완전히 커스터마이징 된 모델을 만들 수 있습니다. __init__ 메서드에서 층을 만들어 클래스 객체의 속성으로 지정합니다. 

정방향 패스는 call 메서드에 정의합니다.

이 API에서는 가능한 한 함수형 API를 사용하라고 권장합니다. 

다음은 tf.keras.Model의 클래스를 상속하여 명령형 프로그래밍 방식으로 실행할 필요가 없는 정방향 패스를 구현한 예입니다.

class MyModel(tf.keras.Model): def __init__(self, num_classes=10): super(MyModel, self).__init__(name='my_model') self.num_classes = num_classes # 층을 정의합니다. self.dense_1 = layers.Dense(32, activation='relu') self.dense_2 = layers.Dense(num_classes, activation='sigmoid') def call(self, inputs): # 정방향 패스를 정의합니다. # `__init__` 메서드에서 정의한 층을 사용합니다. x = self.dense_1(inputs) return self.dense_2(x)

__init__에 모델 객체를 상속받아 모델 구성할 준비를 끝내고, 층을 쌓은뒤 call에서 먹이를 주고 결과를 반환받는다고 생각하시면 됩니다.

model = MyModel(num_classes=10)

# 컴파일 단계는 훈련 과정을 설정합니다.
model.compile(optimizer=tf.keras.optimizers.RMSprop(0.001),
              loss='categorical_crossentropy',
              metrics=['accuracy'])

# 5번의 에포크 동안 훈련합니다.
model.fit(data, labels, batch_size=32, epochs=5)


맞춤형 층(Custom layer)

tf.keras.layers.Layer 클래스를 상속하고 다음 메서드를 구현합니다.

- __init__ : 이 층에서 사용되는 하위 층을 정의합니다

- build : 층의 가중치를 만듭니다. add_weight를  사용해 가중치를 추가합니다.

- call : 정방향 패스를 구현합니다.


다음은 입력과 커널 행렬의 matmul 계산을 구현한 Custom layer의 예시입니다.

class MyLayer(layers.Layer):

  def __init__(self, output_dim, **kwargs):
    self.output_dim = output_dim
    super(MyLayer, self).__init__(**kwargs)

  def build(self, input_shape):
    # 이 층에서 훈련할 가중치 변수를 만듭니다.
    self.kernel = self.add_weight(name='kernel',
                                  shape=(input_shape[1], self.output_dim),
                                  initializer='uniform',
                                  trainable=True)

  def call(self, inputs):
    return tf.matmul(inputs, self.kernel)

  def get_config(self):
    base_config = super(MyLayer, self).get_config()
    base_config['output_dim'] = self.output_dim
    return base_config

  @classmethod
  def from_config(cls, config):
    return cls(**config)
model = tf.keras.Sequential([
    MyLayer(10),
    layers.Activation('softmax')])

# 컴파일 단계는 훈련 과정을 설정합니다.
model.compile(optimizer=tf.keras.optimizers.RMSprop(0.001),
              loss='categorical_crossentropy',
              metrics=['accuracy'])

# 5번의 에포크 동안 훈련합니다.
model.fit(data, labels, batch_size=32, epochs=5)

get_config는 생략하셔도 무방합니다. 나중에 더 알아보시면 됩니다. 중요한 것은 build에서 가중치를 통제한다는 것입니다. 

나머지 모델 구성 및 사용방법은 똑같습니다.


콜백

Callback은 훈련하는 동안 모델의 동작을 변경하고 확장하기 위해 전달하는 객체입니다. 자신만의 콜백을 작성하거나 다음과 같은 내장 tf.keras.callbacks를 사용할 수 있습니다.

-    tf.keras.callbacks.ModelCheckpoint : 일정 간격으로 모델의 체크포인트를 저장합니다. (가장 좋은 모델의 가중치, loss, acc 등등)

-    tf.keras.callbacks.LearningRateScheduler : 학습률을 동적으로 변경합니다.

-    tf.keras.callbacks.EarlyStopping : 검증 성능이 향상되지 않으면 훈련을 중지합니다.

-    tf.keras.callbacks.TensorBoard : 텐서보드를 사용하여 모델을 모니터링 합니다.


fit 메서드에 매개변수로 전달하여 사용할 수 있습니다.

callbacks = [
  # `val_loss`가 2번의 에포크에 걸쳐 향상되지 않으면 훈련을 멈춥니다.
  tf.keras.callbacks.EarlyStopping(patience=2, monitor='val_loss'),
  # `./logs` 디렉토리에 텐서보드 로그를 기록니다.
  tf.keras.callbacks.TensorBoard(log_dir='./logs')
]
model.fit(data, labels, batch_size=32, epochs=5, callbacks=callbacks,
          validation_data=(val_data, val_labels))


저장과 복원

가중치

tf.keras.Model.save_weights를 사용하여 모델의 가중치를 저장하고 복원합니다.

# 가중치를 텐서플로의 체크포인트 파일로 저장합니다.
model.save_weights('./weights/my_model')

# 모델의 상태를 복원합니다.
# 모델의 구조가 동일해야 합니다.
model.load_weights('./weights/my_model')

기본적으로 모델의 가중치는 텐서플로 체크포인트 파일 포맷으로 저장됩니다. 이와 다르게 케라스는 기본적으로 .hdf5 형식을 사용합니다


설정

케라스는 JSON과 YAML 포맷을 지원합니다.

# 모델을 JSON 포맷으로 직렬화합니다.
json_string = model.to_json()
json_string

YAML 포맷으로 직렬화하려면 텐서플로를 임포트하기 전에 pyyaml을 설치해야 합니다.

# JSON 파일로부터 (완전히 새로 초기화된) 모델을 만듭니다. fresh_model = tf.keras.models.model_from_json(json_string) # YAML 포맷으로 직렳화 합니다. yaml_string = model.to_yaml() print(yaml_string) # YAML파일로부터 모델을 다시 만듭니다 fresh_model = tf.keras.models.model_from_yaml(yaml_string)


(나머지는 복붙 및 코드로 대체하겠습니다. 넘어가셔도 됩니다)

즉시 실행

즉시 실행은 연산을 즉각 평가하는 명령형 프로그래밍(imperative programming) 환경입니다. 케라스에서는 즉시 실행이 필수가 아니지만 tf.keras는 이를 지원합니다. 이 기능은 프로그램을 검사하고 디버깅하는데 유용합니다.

모든 tf.keras 모델링 API는 즉시 실행과 호환됩니다. Sequential이나 함수형 API와 사용할 수 있지만 즉시 실행은 특히 모델 상속과 맞춤형 층을 만들 때 장점이 나타납니다. 이런 API는 (기존의 층을 조합하여 모델을 만드는 대신) 직접 정방향 패스의 코드를 작성하기 때문입니다.

즉시 실행 가이드에서 맞춤형 훈련 반복과 tf.GradientTape를 케라스 모델에 같이 사용하는 예를 참고하세요. 또한 간단하지만 완전한 예제를 여기에서 볼 수 있습니다.


분산처리

다중GPU

tf.keras 모델은 tf.distribute.Strategy를 사용하여 다중 GPU에서 실행할 수 있습니다. 이 API는 기존 코드를 거의 수정하지 않고 다중 GPU에서 훈련을 분산시킬 수 있습니다.

현재는 tf.distribute.MirroredStrategy가 유일하게 지원되는 분산 전략입니다. MirroredStrategy는 한 대의 장치에서 계산 결과를 모두 수집하는 방식인 그래프 내 복제(in-graph replication)를 수행합니다. distribute.Strategy를 사용하려면 Strategy의 .scope() 안에 옵티마이저 객체 생성, 모델 구성, 컴파일 단계를 포함시킨 다음 모델을 훈련합니다.

다음 코드는 한 대의 컴퓨터에서 다중 GPU를 사용해 tf.keras.Model을 분산 처리하는 예입니다.

먼저, MirroredStrategy의 scope() 안에서 모델을 정의합니다

strategy = tf.distribute.MirroredStrategy()

with strategy.scope():
  model = tf.keras.Sequential()
  model.add(layers.Dense(16, activation='relu', input_shape=(10,)))
  model.add(layers.Dense(1, activation='sigmoid'))

  optimizer = tf.keras.optimizers.SGD(0.2)

  model.compile(loss='binary_crossentropy', optimizer=optimizer)

model.summary()