このページは Cloud Translation API によって翻訳されました。
Switch to English

組み込みメソッドによるトレーニングと評価

TensorFlow.orgで表示 GoogleColabで実行 GitHubでソースを表示ノートブックをダウンロード

セットアップ

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

前書き

このガイドでは、トレーニングと検証に組み込みAPI( model.fit()model.evaluate()model.predict() )を使用する場合のトレーニング、評価、および予測(推論)モデルについて説明します。

独自のトレーニングステップ関数を指定しながらfit()を活用することに興味がある場合は、ガイドfit()で何が起こるかをカスタマイズする」を参照してください。

独自のトレーニングおよび評価ループを最初から作成することに興味がある場合は、ガイド「トレーニングループを最初から作成する」を参照してください。

一般に、組み込みループを使用している場合でも、独自のループを作成している場合でも、モデルのトレーニングと評価は、すべての種類のKerasモデル(シーケンシャルモデル、Functional APIで構築されたモデル、およびモデルのサブクラス化。

このガイドでは、分散トレーニングについては説明していません。分散トレーニングについては、マルチGPUおよび分散トレーニングのガイドを参照してください

APIの概要:最初のエンドツーエンドの例

モデルの組み込みトレーニングループにデータを渡すときは、 NumPy配列(データが小さく、メモリに収まる場合)またはtf.data Datasetオブジェクトを使用する必要があります。次の数段落では、オプティマイザー、損失、およびメトリックの使用方法を示すために、MNISTデータセットをNumPy配列として使用します。

次のモデルについて考えてみましょう(ここでは、Functional APIを組み込んでいますが、シーケンシャルモデルまたはサブクラス化されたモデルの場合もあります)。

inputs = keras.Input(shape=(784,), name="digits")
x = layers.Dense(64, activation="relu", name="dense_1")(inputs)
x = layers.Dense(64, activation="relu", name="dense_2")(x)
outputs = layers.Dense(10, activation="softmax", name="predictions")(x)

model = keras.Model(inputs=inputs, outputs=outputs)

典型的なエンドツーエンドのワークフローは次のようになります。

  • トレーニング
  • 元のトレーニングデータから生成されたホールドアウトセットの検証
  • テストデータの評価

この例では、MNISTデータを使用します。

(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()

# Preprocess the data (these are NumPy arrays)
x_train = x_train.reshape(60000, 784).astype("float32") / 255
x_test = x_test.reshape(10000, 784).astype("float32") / 255

y_train = y_train.astype("float32")
y_test = y_test.astype("float32")

# Reserve 10,000 samples for validation
x_val = x_train[-10000:]
y_val = y_train[-10000:]
x_train = x_train[:-10000]
y_train = y_train[:-10000]

トレーニング構成(オプティマイザー、損失、メトリック)を指定します。

model.compile(
    optimizer=keras.optimizers.RMSprop(),  # Optimizer
    # Loss function to minimize
    loss=keras.losses.SparseCategoricalCrossentropy(),
    # List of metrics to monitor
    metrics=[keras.metrics.SparseCategoricalAccuracy()],
)

fit()を呼び出します。これは、データをサイズ「batch_size」の「バッチ」にスライスし、指定された数の「エポック」についてデータセット全体を繰り返し反復することによってモデルをトレーニングします。

print("Fit model on training data")
history = model.fit(
    x_train,
    y_train,
    batch_size=64,
    epochs=2,
    # We pass some validation for
    # monitoring validation loss and metrics
    # at the end of each epoch
    validation_data=(x_val, y_val),
)
Fit model on training data
Epoch 1/2
782/782 [==============================] - 2s 2ms/step - loss: 0.3425 - sparse_categorical_accuracy: 0.9034 - val_loss: 0.1827 - val_sparse_categorical_accuracy: 0.9478
Epoch 2/2
782/782 [==============================] - 2s 2ms/step - loss: 0.1618 - sparse_categorical_accuracy: 0.9513 - val_loss: 0.1282 - val_sparse_categorical_accuracy: 0.9651

返された「履歴」オブジェクトは、トレーニング中の損失値とメトリック値の記録を保持します。

history.history
{'loss': [0.3424801528453827, 0.16180744767189026],
 'sparse_categorical_accuracy': [0.903439998626709, 0.9512799978256226],
 'val_loss': [0.18268445134162903, 0.12816601991653442],
 'val_sparse_categorical_accuracy': [0.9477999806404114, 0.9650999903678894]}

私たちはevaluate()介してテストデータでモデルを評価します:

# Evaluate the model on the test data using `evaluate`
print("Evaluate on test data")
results = model.evaluate(x_test, y_test, batch_size=128)
print("test loss, test acc:", results)

# Generate predictions (probabilities -- the output of the last layer)
# on new data using `predict`
print("Generate predictions for 3 samples")
predictions = model.predict(x_test[:3])
print("predictions shape:", predictions.shape)
Evaluate on test data
79/79 [==============================] - 0s 1ms/step - loss: 0.1310 - sparse_categorical_accuracy: 0.9637
test loss, test acc: [0.1309928148984909, 0.963699996471405]
Generate predictions for 3 samples
predictions shape: (3, 10)

それでは、このワークフローの各部分を詳しく見ていきましょう。

compile()メソッド:損失、メトリック、およびオプティマイザーの指定

fit()を使用してモデルをトレーニングするには、損失関数、オプティマイザー、およびオプションで監視するいくつかのメトリックを指定する必要があります。

これらをcompile()メソッドの引数としてモデルに渡します。

model.compile(
    optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(),
    metrics=[keras.metrics.SparseCategoricalAccuracy()],
)

metrics引数はリストである必要があります。モデルには任意の数のメトリックを含めることができます。

モデルに複数の出力がある場合は、出力ごとに異なる損失とメトリックを指定でき、モデルの総損失に対する各出力の寄与を調整できます。これについての詳細は、 「マルチ入力、マルチ出力モデルへのデータの受け渡し」のセクションにあります。

デフォルト設定に満足している場合、多くの場合、オプティマイザー、損失、およびメトリックは、ショートカットとして文字列識別子を介して指定できることに注意してください。

model.compile(
    optimizer="rmsprop",
    loss="sparse_categorical_crossentropy",
    metrics=["sparse_categorical_accuracy"],
)

後で再利用するために、モデル定義とコンパイルステップを関数に入れましょう。このガイドでは、さまざまな例でそれらを数回呼び出します。

def get_uncompiled_model():
    inputs = keras.Input(shape=(784,), name="digits")
    x = layers.Dense(64, activation="relu", name="dense_1")(inputs)
    x = layers.Dense(64, activation="relu", name="dense_2")(x)
    outputs = layers.Dense(10, activation="softmax", name="predictions")(x)
    model = keras.Model(inputs=inputs, outputs=outputs)
    return model


def get_compiled_model():
    model = get_uncompiled_model()
    model.compile(
        optimizer="rmsprop",
        loss="sparse_categorical_crossentropy",
        metrics=["sparse_categorical_accuracy"],
    )
    return model

多くの組み込みオプティマイザ、損失、およびメトリックが利用可能です

一般に、必要なものはすでにKeras APIの一部である可能性が高いため、独自の損失、メトリック、またはオプティマイザーを最初から作成する必要はありません。

オプティマイザー:

  • SGD() (勢いの有無にかかわらず)
  • RMSprop()
  • Adam()

損失:

  • MeanSquaredError()
  • KLDivergence()
  • CosineSimilarity()

指標:

  • AUC()
  • Precision()
  • Recall()

カスタム損失

Kerasでカスタム損失を提供する方法は2つあります。最初の例では、入力y_trueおよびy_predを受け入れる関数を作成します。次の例は、実際のデータと予測の間の平均二乗誤差を計算する損失関数を示しています。

def custom_mean_squared_error(y_true, y_pred):
    return tf.math.reduce_mean(tf.square(y_true - y_pred))


model = get_uncompiled_model()
model.compile(optimizer=keras.optimizers.Adam(), loss=custom_mean_squared_error)

# We need to one-hot encode the labels to use MSE
y_train_one_hot = tf.one_hot(y_train, depth=10)
model.fit(x_train, y_train_one_hot, batch_size=64, epochs=1)
782/782 [==============================] - 1s 1ms/step - loss: 0.0168

<tensorflow.python.keras.callbacks.History at 0x7f75581d56a0>

y_truey_pred横にあるパラメーターをy_true損失関数が必要な場合は、 tf.keras.losses.Lossクラスをサブクラス化して、次の2つのメソッドを実装できます。

  • __init__(self) :損失関数の呼び出し中に渡すパラメーターを受け入れます
  • call(self, y_true, y_pred) :ターゲット(y_true)とモデル予測(y_pred)を使用して、モデルの損失を計算します

平均二乗誤差を使用したいとしますが、0.5から遠く離れた予測値のインセンティブを下げる用語が追加されています(カテゴリターゲットはワンホットエンコードされ、0から1の間の値を取ると想定しています)。これにより、モデルが自信を持ちすぎないようにするインセンティブが生まれ、過剰適合を減らすのに役立つ可能性があります(試してみるまで機能するかどうかはわかりません!)。

これがあなたがそれをする方法です:

class CustomMSE(keras.losses.Loss):
    def __init__(self, regularization_factor=0.1, name="custom_mse"):
        super().__init__(name=name)
        self.regularization_factor = regularization_factor

    def call(self, y_true, y_pred):
        mse = tf.math.reduce_mean(tf.square(y_true - y_pred))
        reg = tf.math.reduce_mean(tf.square(0.5 - y_pred))
        return mse + reg * self.regularization_factor


model = get_uncompiled_model()
model.compile(optimizer=keras.optimizers.Adam(), loss=CustomMSE())

y_train_one_hot = tf.one_hot(y_train, depth=10)
model.fit(x_train, y_train_one_hot, batch_size=64, epochs=1)
782/782 [==============================] - 1s 2ms/step - loss: 0.0390

<tensorflow.python.keras.callbacks.History at 0x7f7558184c88>

カスタムメトリック

APIの一部ではないメトリックが必要な場合は、 tf.keras.metrics.Metricクラスをサブクラス化することで、カスタムメトリックを簡単に作成できます。 4つのメソッドを実装する必要があります。

  • __init__(self) 。ここで、メトリックの状態変数を作成します。
  • update_state(self, y_true, y_pred, sample_weight=None) 。これは、ターゲットy_trueとモデル予測y_predを使用して状態変数を更新します。
  • result(self) 。状態変数を使用して最終結果を計算します。
  • reset_states(self) 。これは、メトリックの状態を再初期化します。

場合によっては、結果の計算に非常にコストがかかり、定期的にしか実行されないため、状態の更新と結果の計算は別々に(それぞれupdate_state()result()update_state()保持されます。

これは、特定のクラスに属するものとして正しく分類されたサンプルの数をカウントするCategoricalTruePositivesメトリックを実装する方法を示す簡単な例です。

class CategoricalTruePositives(keras.metrics.Metric):
    def __init__(self, name="categorical_true_positives", **kwargs):
        super(CategoricalTruePositives, self).__init__(name=name, **kwargs)
        self.true_positives = self.add_weight(name="ctp", initializer="zeros")

    def update_state(self, y_true, y_pred, sample_weight=None):
        y_pred = tf.reshape(tf.argmax(y_pred, axis=1), shape=(-1, 1))
        values = tf.cast(y_true, "int32") == tf.cast(y_pred, "int32")
        values = tf.cast(values, "float32")
        if sample_weight is not None:
            sample_weight = tf.cast(sample_weight, "float32")
            values = tf.multiply(values, sample_weight)
        self.true_positives.assign_add(tf.reduce_sum(values))

    def result(self):
        return self.true_positives

    def reset_states(self):
        # The state of the metric will be reset at the start of each epoch.
        self.true_positives.assign(0.0)


model = get_uncompiled_model()
model.compile(
    optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(),
    metrics=[CategoricalTruePositives()],
)
model.fit(x_train, y_train, batch_size=64, epochs=3)
Epoch 1/3
782/782 [==============================] - 1s 2ms/step - loss: 0.3429 - categorical_true_positives: 45146.0000
Epoch 2/3
782/782 [==============================] - 1s 2ms/step - loss: 0.1560 - categorical_true_positives: 47637.0000
Epoch 3/3
782/782 [==============================] - 1s 2ms/step - loss: 0.1155 - categorical_true_positives: 48237.0000

<tensorflow.python.keras.callbacks.History at 0x7f755801bfd0>

標準の署名に適合しない損失とメトリックの処理

損失とメトリックの圧倒的多数は、 y_truey_predから計算できます。ここで、 y_predはモデルの出力です。しかし、それらのすべてではありません。たとえば、正則化の損失は、レイヤーのアクティブ化のみを必要とする場合があり(この場合、ターゲットはありません)、このアクティブ化はモデル出力ではない場合があります。

このような場合、カスタムレイヤーのcallメソッド内からself.add_loss(loss_value)呼び出すことができます。この方法で追加された損失は、トレーニング中の「メイン」損失( compile()渡された損失)に追加されます。アクティビティの正則化を追加する簡単な例を次に示します(アクティビティの正則化はすべてのKerasレイヤーに組み込まれていることに注意してください。このレイヤーは具体的な例を提供するためだけのものです)。

class ActivityRegularizationLayer(layers.Layer):
    def call(self, inputs):
        self.add_loss(tf.reduce_sum(inputs) * 0.1)
        return inputs  # Pass-through layer.


inputs = keras.Input(shape=(784,), name="digits")
x = layers.Dense(64, activation="relu", name="dense_1")(inputs)

# Insert activity regularization as a layer
x = ActivityRegularizationLayer()(x)

x = layers.Dense(64, activation="relu", name="dense_2")(x)
outputs = layers.Dense(10, name="predictions")(x)

model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(
    optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
)

# The displayed loss will be much higher than before
# due to the regularization component.
model.fit(x_train, y_train, batch_size=64, epochs=1)
782/782 [==============================] - 1s 2ms/step - loss: 2.4756

<tensorflow.python.keras.callbacks.History at 0x7f75501e1f98>

add_metric()を使用して、メトリック値のログに同じことを行うことができます。

class MetricLoggingLayer(layers.Layer):
    def call(self, inputs):
        # The `aggregation` argument defines
        # how to aggregate the per-batch values
        # over each epoch:
        # in this case we simply average them.
        self.add_metric(
            keras.backend.std(inputs), name="std_of_activation", aggregation="mean"
        )
        return inputs  # Pass-through layer.


inputs = keras.Input(shape=(784,), name="digits")
x = layers.Dense(64, activation="relu", name="dense_1")(inputs)

# Insert std logging as a layer.
x = MetricLoggingLayer()(x)

x = layers.Dense(64, activation="relu", name="dense_2")(x)
outputs = layers.Dense(10, name="predictions")(x)

model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(
    optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
)
model.fit(x_train, y_train, batch_size=64, epochs=1)
782/782 [==============================] - 1s 2ms/step - loss: 0.3493 - std_of_activation: 0.9813

<tensorflow.python.keras.callbacks.History at 0x7f75500321d0>

Functional APIでは、 model.add_loss(loss_tensor)またはmodel.add_metric(metric_tensor, name, aggregation)呼び出すこともできます。

簡単な例を次に示します。

inputs = keras.Input(shape=(784,), name="digits")
x1 = layers.Dense(64, activation="relu", name="dense_1")(inputs)
x2 = layers.Dense(64, activation="relu", name="dense_2")(x1)
outputs = layers.Dense(10, name="predictions")(x2)
model = keras.Model(inputs=inputs, outputs=outputs)

model.add_loss(tf.reduce_sum(x1) * 0.1)

model.add_metric(keras.backend.std(x1), name="std_of_activation", aggregation="mean")

model.compile(
    optimizer=keras.optimizers.RMSprop(1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
)
model.fit(x_train, y_train, batch_size=64, epochs=1)
782/782 [==============================] - 1s 2ms/step - loss: 2.5230 - std_of_activation: 0.0020

<tensorflow.python.keras.callbacks.History at 0x7f74ec71d828>

add_loss()を介して損失をadd_loss()と、モデルには最小化する損失がすでにあるため、損失関数なしでcompile()を呼び出すことが可能になることに注意してください。

次のLogisticEndpointレイヤーについて考えてみます。これは、入力ターゲットとロジットを受け取り、 add_loss()介してadd_loss()エントロピー損失をadd_loss()ます。また、 add_metric()を介して分類の精度をadd_metric()ます。

class LogisticEndpoint(keras.layers.Layer):
    def __init__(self, name=None):
        super(LogisticEndpoint, self).__init__(name=name)
        self.loss_fn = keras.losses.BinaryCrossentropy(from_logits=True)
        self.accuracy_fn = keras.metrics.BinaryAccuracy()

    def call(self, targets, logits, sample_weights=None):
        # Compute the training-time loss value and add it
        # to the layer using `self.add_loss()`.
        loss = self.loss_fn(targets, logits, sample_weights)
        self.add_loss(loss)

        # Log accuracy as a metric and add it
        # to the layer using `self.add_metric()`.
        acc = self.accuracy_fn(targets, logits, sample_weights)
        self.add_metric(acc, name="accuracy")

        # Return the inference-time prediction tensor (for `.predict()`).
        return tf.nn.softmax(logits)

次のように、 loss引数なしでコンパイルされた2つの入力(入力データとターゲット)を持つモデルで使用できます。

import numpy as np

inputs = keras.Input(shape=(3,), name="inputs")
targets = keras.Input(shape=(10,), name="targets")
logits = keras.layers.Dense(10)(inputs)
predictions = LogisticEndpoint(name="predictions")(logits, targets)

model = keras.Model(inputs=[inputs, targets], outputs=predictions)
model.compile(optimizer="adam")  # No loss argument!

data = {
    "inputs": np.random.random((3, 3)),
    "targets": np.random.random((3, 10)),
}
model.fit(data)
1/1 [==============================] - 0s 1ms/step - loss: 0.9344 - binary_accuracy: 0.0000e+00

<tensorflow.python.keras.callbacks.History at 0x7f7558339f28>

多入力モデルのトレーニングの詳細については、「多入力、多出力モデルへのデータの受け渡し」のセクションを参照してください。

検証ホールドアウトセットを自動的に分離する

最初に見たエンドツーエンドの例では、 validation_data引数を使用して、NumPy配列(x_val, y_val)タプルをモデルに(x_val, y_val)各エポックの終わりに検証損失と検証メトリックを評価しました。

別のオプションは次のとおりです。引数validation_split使用すると、検証用にトレーニングデータの一部を自動的に予約できます。引数値は、検証用に予約されるデータの割合を表すため、0より大きく1より小さい数値に設定する必要があります。たとえば、 validation_split=0.2は、「検証にデータの20%を使用する」ことを意味します。 validation_split=0.6は、「検証にデータの60%を使用する」ことを意味します。

検証が計算される方法は、シャッフルする前に、fit呼び出しによって受信された配列の最後のx%サンプルを取得することです。

NumPyデータを使用してトレーニングする場合にのみ、 validation_split使用できることに注意してください。

model = get_compiled_model()
model.fit(x_train, y_train, batch_size=64, validation_split=0.2, epochs=1)
625/625 [==============================] - 1s 2ms/step - loss: 0.3753 - sparse_categorical_accuracy: 0.8927 - val_loss: 0.2252 - val_sparse_categorical_accuracy: 0.9344

<tensorflow.python.keras.callbacks.History at 0x7f755826f160>

tf.dataデータセットからのトレーニングと評価

過去数段落では、あなたは損、評価指標、およびオプティマイザーをどのように処理するかを見てきた、あなたが使用する方法を見てきましたvalidation_datavalidation_splitあなたのデータはnumpyの配列として渡されたときに、フィット感で引数を。

次に、データがtf.data.Datasetオブジェクトの形式で提供される場合を見てみましょう。

tf.data APIは、高速でスケーラブルな方法でデータをロードおよび前処理するためのTensorFlow2.0のユーティリティのセットです。

Datasets作成に関する完全なガイドについては、 tf.dataのドキュメントを参照してください。

Datasetインスタンスをメソッドfit()evaluate()predict()直接渡すことができます。

model = get_compiled_model()

# First, let's create a training Dataset instance.
# For the sake of our example, we'll use the same MNIST data as before.
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
# Shuffle and slice the dataset.
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)

# Now we get a test dataset.
test_dataset = tf.data.Dataset.from_tensor_slices((x_test, y_test))
test_dataset = test_dataset.batch(64)

# Since the dataset already takes care of batching,
# we don't pass a `batch_size` argument.
model.fit(train_dataset, epochs=3)

# You can also evaluate or predict on a dataset.
print("Evaluate")
result = model.evaluate(test_dataset)
dict(zip(model.metrics_names, result))
Epoch 1/3
782/782 [==============================] - 2s 2ms/step - loss: 0.3404 - sparse_categorical_accuracy: 0.9048
Epoch 2/3
782/782 [==============================] - 2s 2ms/step - loss: 0.1596 - sparse_categorical_accuracy: 0.9529
Epoch 3/3
782/782 [==============================] - 2s 2ms/step - loss: 0.1165 - sparse_categorical_accuracy: 0.9658
Evaluate
157/157 [==============================] - 0s 1ms/step - loss: 0.1147 - sparse_categorical_accuracy: 0.9659

{'loss': 0.11471886932849884,
 'sparse_categorical_accuracy': 0.9659000039100647}

データセットは各エポックの終わりにリセットされるため、次のエポックで再利用できることに注意してください。

このデータセットの特定の数のバッチでのみトレーニングを実行する場合は、 steps_per_epoch引数を渡すことができます。この引数は、次のエポックに進む前に、このデータセットを使用してモデルが実行するトレーニングステップの数を指定します。

これを行うと、データセットは各エポックの終了時にリセットされず、代わりに次のバッチを描画し続けます。データセットは最終的にデータを使い果たします(無限にループするデータセットでない限り)。

model = get_compiled_model()

# Prepare the training dataset
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)

# Only use the 100 batches per epoch (that's 64 * 100 samples)
model.fit(train_dataset, epochs=3, steps_per_epoch=100)
Epoch 1/3
100/100 [==============================] - 0s 2ms/step - loss: 0.8448 - sparse_categorical_accuracy: 0.7734
Epoch 2/3
100/100 [==============================] - 0s 2ms/step - loss: 0.3912 - sparse_categorical_accuracy: 0.8922
Epoch 3/3
100/100 [==============================] - 0s 2ms/step - loss: 0.3399 - sparse_categorical_accuracy: 0.9011

<tensorflow.python.keras.callbacks.History at 0x7f74ec5cf7f0>

検証データセットの使用

fit() validation_data引数としてDatasetインスタンスを渡すことができます。

model = get_compiled_model()

# Prepare the training dataset
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)

# Prepare the validation dataset
val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val))
val_dataset = val_dataset.batch(64)

model.fit(train_dataset, epochs=1, validation_data=val_dataset)
782/782 [==============================] - 2s 2ms/step - loss: 0.3384 - sparse_categorical_accuracy: 0.9032 - val_loss: 0.1752 - val_sparse_categorical_accuracy: 0.9518

<tensorflow.python.keras.callbacks.History at 0x7f74ec4d2ba8>

各エポックの終わりに、モデルは検証データセットを反復処理し、検証損失と検証メトリックを計算します。

このデータセットの特定の数のバッチでのみ検証を実行する場合は、 validation_steps引数を渡すことができます。これは、検証を中断して次のエポックに進む前に、モデルが検証データセットで実行する検証ステップの数を指定します。

model = get_compiled_model()

# Prepare the training dataset
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)

# Prepare the validation dataset
val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val))
val_dataset = val_dataset.batch(64)

model.fit(
    train_dataset,
    epochs=1,
    # Only run validation using the first 10 batches of the dataset
    # using the `validation_steps` argument
    validation_data=val_dataset,
    validation_steps=10,
)
782/782 [==============================] - 2s 2ms/step - loss: 0.3503 - sparse_categorical_accuracy: 0.9021 - val_loss: 0.3226 - val_sparse_categorical_accuracy: 0.9156

<tensorflow.python.keras.callbacks.History at 0x7f74ec4caa58>

検証データセットは使用するたびにリセットされることに注意してください(そのため、エポックからエポックまで常に同じサンプルで評価することになります)。

引数validation_split (トレーニングデータからホールドアウトセットを生成する)は、 Datasetオブジェクトからトレーニングする場合はサポートされません。これは、この機能がデータセットのサンプルにインデックスをDataset機能を必要とするためです。これは、 Dataset APIでは一般的に不可能です。

サポートされている他の入力形式

NumPy配列、熱心なテンソル、TensorFlow Datasetsに加えて、Pandasデータフレームを使用して、またはデータとラベルのバッチを生成するPythonジェネレーターからKerasモデルをトレーニングすることができます。

特に、 keras.utils.Sequenceクラスは、マルチプロセッシングに対応し、シャッフルできるPythonデータジェネレーターを構築するためのシンプルなインターフェイスを提供します。

一般的に、以下を使用することをお勧めします。

  • データが小さく、メモリに収まる場合は、NumPy入力データ
  • 大規模なデータセットがあり、分散トレーニングを行う必要がある場合のDatasetオブジェクト
  • 大規模なデータセットがあり、TensorFlowでは実行できない多くのカスタムPython側処理を実行する必要がある場合(たとえば、データの読み込みや前処理を外部ライブラリに依存している場合)、オブジェクトをSequenceます。

keras.utils.Sequenceオブジェクトを入力として使用する

keras.utils.Sequenceは、サブクラス化して2つの重要なプロパティを持つPythonジェネレーターを取得できるユーティリティです。

  • マルチプロセッシングでうまく機能します。
  • シャッフルすることができます(たとえば、 fit()shuffle=Trueを渡す場合)。

Sequenceは2つのメソッドを実装する必要があります。

  • __getitem__
  • __len__

メソッド__getitem__は、完全なバッチを返す必要があります。エポック間でデータセットを変更する場合は、 on_epoch_end実装on_epoch_endます。

簡単な例を次に示します。

from skimage.io import imread
from skimage.transform import resize
import numpy as np

# Here, `filenames` is list of path to the images
# and `labels` are the associated labels.

class CIFAR10Sequence(Sequence):
    def __init__(self, filenames, labels, batch_size):
        self.filenames, self.labels = filenames, labels
        self.batch_size = batch_size

    def __len__(self):
        return int(np.ceil(len(self.filenames) / float(self.batch_size)))

    def __getitem__(self, idx):
        batch_x = self.filenames[idx * self.batch_size:(idx + 1) * self.batch_size]
        batch_y = self.labels[idx * self.batch_size:(idx + 1) * self.batch_size]
        return np.array([
            resize(imread(filename), (200, 200))
               for filename in batch_x]), np.array(batch_y)

sequence = CIFAR10Sequence(filenames, labels, batch_size)
model.fit(sequence, epochs=10)

サンプルの重み付けとクラスの重み付けの使用

デフォルト設定では、サンプルの重みはデータセット内の頻度によって決定されます。サンプルの頻度に関係なく、データに重みを付けるには2つの方法があります。

  • クラスの重み
  • サンプルの重み

クラスの重み

これは、 Model.fit() class_weight引数に辞書を渡すことによって設定されます。このディクショナリは、クラスインデックスを、このクラスに属するサンプルに使用する必要のある重みにマップします。

これは、リサンプリングせずにクラスのバランスをとったり、特定のクラスをより重要視するモデルをトレーニングしたりするために使用できます。

たとえば、クラス「0」がデータでクラス「1」として表される半分である場合、 Model.fit(..., class_weight={0: 1., 1: 0.5})使用できます。

これは、クラスの重みまたはサンプルの重みを使用して、クラス#5(MNISTデータセットの数字「5」)の正しい分類をより重要視するNumPyの例です。

import numpy as np

class_weight = {
    0: 1.0,
    1: 1.0,
    2: 1.0,
    3: 1.0,
    4: 1.0,
    # Set weight "2" for class "5",
    # making this class 2x more important
    5: 2.0,
    6: 1.0,
    7: 1.0,
    8: 1.0,
    9: 1.0,
}

print("Fit with class weight")
model = get_compiled_model()
model.fit(x_train, y_train, class_weight=class_weight, batch_size=64, epochs=1)
Fit with class weight
782/782 [==============================] - 2s 2ms/step - loss: 0.3729 - sparse_categorical_accuracy: 0.9025

<tensorflow.python.keras.callbacks.History at 0x7f74ec265358>

サンプルの重み

きめ細かい制御の場合、または分類器を作成していない場合は、「サンプルの重み」を使用できます。

  • NumPyデータからトレーニングする場合: sample_weight引数をModel.fit() sample_weightます。
  • tf.dataまたは他の種類のイテレーターからトレーニングする場合: (input_batch, label_batch, sample_weight_batch)タプルを生成します。

「サンプルの重み」配列は、バッチ内の各サンプルが総損失を計算する際に必要な重みを指定する数値の配列です。これは、不均衡な分類問題で一般的に使用されます(めったに見られないクラスにより多くの重みを与えるという考え)。

使用される重みが1と0の場合、配列は損失関数のマスクとして使用できます(総損失に対する特定のサンプルの寄与を完全に破棄します)。

sample_weight = np.ones(shape=(len(y_train),))
sample_weight[y_train == 5] = 2.0

print("Fit with sample weight")
model = get_compiled_model()
model.fit(x_train, y_train, sample_weight=sample_weight, batch_size=64, epochs=1)
Fit with sample weight
782/782 [==============================] - 2s 2ms/step - loss: 0.3837 - sparse_categorical_accuracy: 0.8984

<tensorflow.python.keras.callbacks.History at 0x7f74ec11afd0>

一致するDataset例を次に示します。

sample_weight = np.ones(shape=(len(y_train),))
sample_weight[y_train == 5] = 2.0

# Create a Dataset that includes sample weights
# (3rd element in the return tuple).
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train, sample_weight))

# Shuffle and slice the dataset.
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)

model = get_compiled_model()
model.fit(train_dataset, epochs=1)
782/782 [==============================] - 2s 2ms/step - loss: 0.3792 - sparse_categorical_accuracy: 0.9030

<tensorflow.python.keras.callbacks.History at 0x7f74d47f2208>

多入力、多出力モデルへのデータの受け渡し

前の例では、単一の入力(形状のテンソル(764,) )と単一の出力(形状の予測テンソル(10,) )を持つモデルを検討していました。しかし、複数の入力または出力を持つモデルはどうですか?

形状(32, 32, 3) 32、32、3 (height, width, channels) )の画像入力と形状(None, 10)(timesteps, features) )の時系列入力を持つ次のモデルについて考えてみます。このモデルには、これらの入力の組み合わせから計算された2つの出力があります。「スコア」(形状(1,) )と5つのクラスにわたる確率分布(形状(5,) )です。

image_input = keras.Input(shape=(32, 32, 3), name="img_input")
timeseries_input = keras.Input(shape=(None, 10), name="ts_input")

x1 = layers.Conv2D(3, 3)(image_input)
x1 = layers.GlobalMaxPooling2D()(x1)

x2 = layers.Conv1D(3, 3)(timeseries_input)
x2 = layers.GlobalMaxPooling1D()(x2)

x = layers.concatenate([x1, x2])

score_output = layers.Dense(1, name="score_output")(x)
class_output = layers.Dense(5, name="class_output")(x)

model = keras.Model(
    inputs=[image_input, timeseries_input], outputs=[score_output, class_output]
)

このモデルをプロットして、ここで何をしているのかを明確に確認しましょう(プロットに表示される形状は、サンプルごとの形状ではなく、バッチ形状であることに注意してください)。

keras.utils.plot_model(model, "multi_input_and_output_model.png", show_shapes=True)

png

コンパイル時に、損失関数をリストとして渡すことにより、さまざまな出力にさまざまな損失を指定できます。

model.compile(
    optimizer=keras.optimizers.RMSprop(1e-3),
    loss=[keras.losses.MeanSquaredError(), keras.losses.CategoricalCrossentropy()],
)

モデルに単一の損失関数のみを渡した場合、同じ損失関数がすべての出力に適用されます(これはここでは適切ではありません)。

メトリックについても同様です。

model.compile(
    optimizer=keras.optimizers.RMSprop(1e-3),
    loss=[keras.losses.MeanSquaredError(), keras.losses.CategoricalCrossentropy()],
    metrics=[
        [
            keras.metrics.MeanAbsolutePercentageError(),
            keras.metrics.MeanAbsoluteError(),
        ],
        [keras.metrics.CategoricalAccuracy()],
    ],
)

出力レイヤーに名前を付けたので、dictを介して出力ごとの損失とメトリックを指定することもできます。

model.compile(
    optimizer=keras.optimizers.RMSprop(1e-3),
    loss={
        "score_output": keras.losses.MeanSquaredError(),
        "class_output": keras.losses.CategoricalCrossentropy(),
    },
    metrics={
        "score_output": [
            keras.metrics.MeanAbsolutePercentageError(),
            keras.metrics.MeanAbsoluteError(),
        ],
        "class_output": [keras.metrics.CategoricalAccuracy()],
    },
)

3つ以上の出力がある場合は、明示的な名前とdictを使用することをお勧めします。

loss_weights引数を使用して、さまざまな出力固有の損失にさまざまな重みを与えることができます(たとえば、この例では、クラス損失の重要度を2倍にすることで、「スコア」損失に特権を与えることがloss_weightsます)。

model.compile(
    optimizer=keras.optimizers.RMSprop(1e-3),
    loss={
        "score_output": keras.losses.MeanSquaredError(),
        "class_output": keras.losses.CategoricalCrossentropy(),
    },
    metrics={
        "score_output": [
            keras.metrics.MeanAbsolutePercentageError(),
            keras.metrics.MeanAbsoluteError(),
        ],
        "class_output": [keras.metrics.CategoricalAccuracy()],
    },
    loss_weights={"score_output": 2.0, "class_output": 1.0},
)

特定の出力が予測を目的としているがトレーニングを目的としていない場合は、特定の出力の損失を計算しないことを選択することもできます。

# List loss version
model.compile(
    optimizer=keras.optimizers.RMSprop(1e-3),
    loss=[None, keras.losses.CategoricalCrossentropy()],
)

# Or dict loss version
model.compile(
    optimizer=keras.optimizers.RMSprop(1e-3),
    loss={"class_output": keras.losses.CategoricalCrossentropy()},
)

フィットで多入力または多出力モデルにデータを渡すことは、コンパイルで損失関数を指定するのと同じように機能します。NumPy配列のリストを渡すことができます(損失関数を受け取った出力に1:1のマッピングで)または出力名をNumPy配列にマッピングすることを指示します

model.compile(
    optimizer=keras.optimizers.RMSprop(1e-3),
    loss=[keras.losses.MeanSquaredError(), keras.losses.CategoricalCrossentropy()],
)

# Generate dummy NumPy data
img_data = np.random.random_sample(size=(100, 32, 32, 3))
ts_data = np.random.random_sample(size=(100, 20, 10))
score_targets = np.random.random_sample(size=(100, 1))
class_targets = np.random.random_sample(size=(100, 5))

# Fit on lists
model.fit([img_data, ts_data], [score_targets, class_targets], batch_size=32, epochs=1)

# Alternatively, fit on dicts
model.fit(
    {"img_input": img_data, "ts_input": ts_data},
    {"score_output": score_targets, "class_output": class_targets},
    batch_size=32,
    epochs=1,
)
4/4 [==============================] - 0s 6ms/step - loss: 20.0184 - score_output_loss: 0.5383 - class_output_loss: 19.4800
4/4 [==============================] - 0s 4ms/step - loss: 17.7266 - score_output_loss: 0.3122 - class_output_loss: 17.4145

<tensorflow.python.keras.callbacks.History at 0x7f755022feb8>

Datasetユースケースは次のとおりです。NumPy配列に対して行ったのと同様に、 Datasetはdictのタプルを返す必要があります。

train_dataset = tf.data.Dataset.from_tensor_slices(
    (
        {"img_input": img_data, "ts_input": ts_data},
        {"score_output": score_targets, "class_output": class_targets},
    )
)
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)

model.fit(train_dataset, epochs=1)
2/2 [==============================] - 0s 8ms/step - loss: 17.2156 - score_output_loss: 0.2522 - class_output_loss: 16.9634

<tensorflow.python.keras.callbacks.History at 0x7f75c56c1128>

コールバックの使用

Kerasのコールバックは、トレーニング中のさまざまなポイント(エポックの開始時、バッチの終了時、エポックの終了時など)で呼び出され、次のような動作を実装するために使用できるオブジェクトです。

  • トレーニング中のさまざまなポイントで検証を行う(組み込みのエポックごとの検証以外)
  • 定期的に、または特定の精度のしきい値を超えたときにモデルをチェックポイントする
  • トレーニングが頭打ちになっているように見えるときにモデルの学習率を変更する
  • トレーニングが頭打ちになっているように見えるときに最上層の微調整を行う
  • トレーニングが終了したとき、または特定のパフォーマンスしきい値を超えたときに電子メールまたはインスタントメッセージ通知を送信する
  • 等。

コールバックは、 fit()への呼び出しにリストとして渡すことができます:

model = get_compiled_model()

callbacks = [
    keras.callbacks.EarlyStopping(
        # Stop training when `val_loss` is no longer improving
        monitor="val_loss",
        # "no longer improving" being defined as "no better than 1e-2 less"
        min_delta=1e-2,
        # "no longer improving" being further defined as "for at least 2 epochs"
        patience=2,
        verbose=1,
    )
]
model.fit(
    x_train,
    y_train,
    epochs=20,
    batch_size=64,
    callbacks=callbacks,
    validation_split=0.2,
)
Epoch 1/20
625/625 [==============================] - 1s 2ms/step - loss: 0.3816 - sparse_categorical_accuracy: 0.8913 - val_loss: 0.2325 - val_sparse_categorical_accuracy: 0.9304
Epoch 2/20
625/625 [==============================] - 1s 2ms/step - loss: 0.1773 - sparse_categorical_accuracy: 0.9477 - val_loss: 0.2088 - val_sparse_categorical_accuracy: 0.9343
Epoch 3/20
625/625 [==============================] - 1s 2ms/step - loss: 0.1293 - sparse_categorical_accuracy: 0.9606 - val_loss: 0.1515 - val_sparse_categorical_accuracy: 0.9568
Epoch 4/20
625/625 [==============================] - 1s 2ms/step - loss: 0.1009 - sparse_categorical_accuracy: 0.9700 - val_loss: 0.1376 - val_sparse_categorical_accuracy: 0.9607
Epoch 5/20
625/625 [==============================] - 1s 2ms/step - loss: 0.0821 - sparse_categorical_accuracy: 0.9747 - val_loss: 0.1533 - val_sparse_categorical_accuracy: 0.9545
Epoch 6/20
625/625 [==============================] - 1s 2ms/step - loss: 0.0704 - sparse_categorical_accuracy: 0.9794 - val_loss: 0.1319 - val_sparse_categorical_accuracy: 0.9616
Epoch 00006: early stopping

<tensorflow.python.keras.callbacks.History at 0x7f74d46abdd8>

多くの組み込みのコールバックが利用可能です

  • ModelCheckpoint :モデルを定期的に保存します。
  • EarlyStopping :トレーニングで検証指標が改善されなくなっEarlyStopping 、トレーニングを停止します。
  • TensorBoardTensorBoardで視覚化できるモデルログを定期的に書き込みます(詳細については、「視覚化」のセクションを参照してください)。
  • CSVLogger :損失とメトリックのデータをCSVファイルにストリーミングします。

完全なリストについては、コールバックのドキュメントを参照してください。

独自のコールバックを書く

基本クラスkeras.callbacks.Callback拡張することにより、カスタムコールバックを作成できます。コールバックは、クラスプロパティself.model介して関連するモデルにアクセスできます。

カスタムコールバックを作成するための完全なガイドを必ずお読みください。

トレーニング中にバッチごとの損失値のリストを保存する簡単な例を次に示します。

class LossHistory(keras.callbacks.Callback):
    def on_train_begin(self, logs):
        self.per_batch_losses = []

    def on_batch_end(self, batch, logs):
        self.per_batch_losses.append(logs.get("loss"))

チェックポイントモデル

比較的大きなデータセットでモデルをトレーニングする場合、モデルのチェックポイントを頻繁に保存することが重要です。

これを実現する最も簡単な方法は、 ModelCheckpointコールバックを使用することです。

model = get_compiled_model()

callbacks = [
    keras.callbacks.ModelCheckpoint(
        # Path where to save the model
        # The two parameters below mean that we will overwrite
        # the current checkpoint if and only if
        # the `val_loss` score has improved.
        # The saved model name will include the current epoch.
        filepath="mymodel_{epoch}",
        save_best_only=True,  # Only save a model if `val_loss` has improved.
        monitor="val_loss",
        verbose=1,
    )
]
model.fit(
    x_train, y_train, epochs=2, batch_size=64, callbacks=callbacks, validation_split=0.2
)
Epoch 1/2
608/625 [============================>.] - ETA: 0s - loss: 0.3797 - sparse_categorical_accuracy: 0.8940
Epoch 00001: val_loss improved from inf to 0.23986, saving model to mymodel_1
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/training/tracking/tracking.py:111: Model.state_updates (from tensorflow.python.keras.engine.training) is deprecated and will be removed in a future version.
Instructions for updating:
This property should not be used in TensorFlow 2.0, as updates are applied automatically.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/training/tracking/tracking.py:111: Layer.updates (from tensorflow.python.keras.engine.base_layer) is deprecated and will be removed in a future version.
Instructions for updating:
This property should not be used in TensorFlow 2.0, as updates are applied automatically.
INFO:tensorflow:Assets written to: mymodel_1/assets
625/625 [==============================] - 2s 3ms/step - loss: 0.3765 - sparse_categorical_accuracy: 0.8949 - val_loss: 0.2399 - val_sparse_categorical_accuracy: 0.9276
Epoch 2/2
606/625 [============================>.] - ETA: 0s - loss: 0.1758 - sparse_categorical_accuracy: 0.9474
Epoch 00002: val_loss improved from 0.23986 to 0.19765, saving model to mymodel_2
INFO:tensorflow:Assets written to: mymodel_2/assets
625/625 [==============================] - 2s 3ms/step - loss: 0.1751 - sparse_categorical_accuracy: 0.9477 - val_loss: 0.1976 - val_sparse_categorical_accuracy: 0.9409

<tensorflow.python.keras.callbacks.History at 0x7f7550171f28>

ModelCheckpointコールバックを使用して、フォールトトレランスを実装できます。トレーニングがランダムに中断された場合に、モデルの最後に保存された状態からトレーニングを再開する機能です。基本的な例は次のとおりです。

import os

# Prepare a directory to store all the checkpoints.
checkpoint_dir = "./ckpt"
if not os.path.exists(checkpoint_dir):
    os.makedirs(checkpoint_dir)


def make_or_restore_model():
    # Either restore the latest model, or create a fresh one
    # if there is no checkpoint available.
    checkpoints = [checkpoint_dir + "/" + name for name in os.listdir(checkpoint_dir)]
    if checkpoints:
        latest_checkpoint = max(checkpoints, key=os.path.getctime)
        print("Restoring from", latest_checkpoint)
        return keras.models.load_model(latest_checkpoint)
    print("Creating a new model")
    return get_compiled_model()


model = make_or_restore_model()
callbacks = [
    # This callback saves a SavedModel every 100 batches.
    # We include the training loss in the saved model name.
    keras.callbacks.ModelCheckpoint(
        filepath=checkpoint_dir + "/ckpt-loss={loss:.2f}", save_freq=100
    )
]
model.fit(x_train, y_train, epochs=1, callbacks=callbacks)
Creating a new model
  94/1563 [>.............................] - ETA: 3s - loss: 0.9261 - sparse_categorical_accuracy: 0.7420INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.90/assets
 192/1563 [==>...........................] - ETA: 6s - loss: 0.6734 - sparse_categorical_accuracy: 0.8097INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.66/assets
 292/1563 [====>.........................] - ETA: 6s - loss: 0.5676 - sparse_categorical_accuracy: 0.8390INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.56/assets
 393/1563 [======>.......................] - ETA: 6s - loss: 0.5077 - sparse_categorical_accuracy: 0.8543INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.51/assets
 490/1563 [========>.....................] - ETA: 5s - loss: 0.4665 - sparse_categorical_accuracy: 0.8652INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.46/assets
 589/1563 [==========>...................] - ETA: 5s - loss: 0.4356 - sparse_categorical_accuracy: 0.8735INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.43/assets
 690/1563 [============>.................] - ETA: 4s - loss: 0.4077 - sparse_categorical_accuracy: 0.8813INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.41/assets
 791/1563 [==============>...............] - ETA: 4s - loss: 0.3883 - sparse_categorical_accuracy: 0.8873INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.39/assets
 892/1563 [================>.............] - ETA: 3s - loss: 0.3715 - sparse_categorical_accuracy: 0.8921INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.37/assets
 992/1563 [==================>...........] - ETA: 3s - loss: 0.3569 - sparse_categorical_accuracy: 0.8964INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.36/assets
1092/1563 [===================>..........] - ETA: 2s - loss: 0.3444 - sparse_categorical_accuracy: 0.8994INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.34/assets
1194/1563 [=====================>........] - ETA: 2s - loss: 0.3315 - sparse_categorical_accuracy: 0.9025INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.33/assets
1293/1563 [=======================>......] - ETA: 1s - loss: 0.3217 - sparse_categorical_accuracy: 0.9056INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.32/assets
1383/1563 [=========================>....] - ETA: 1s - loss: 0.3145 - sparse_categorical_accuracy: 0.9077INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.31/assets
1478/1563 [===========================>..] - ETA: 0s - loss: 0.3057 - sparse_categorical_accuracy: 0.9102INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.30/assets
1563/1563 [==============================] - 9s 6ms/step - loss: 0.2996 - sparse_categorical_accuracy: 0.9119

<tensorflow.python.keras.callbacks.History at 0x7f74ec20d668>

また、モデルを保存および復元するための独自のコールバックを記述します。

シリアル化と保存の完全なガイドについては、モデルの保存とシリアル化ガイドを参照してください

学習率スケジュールの使用

深層学習モデルをトレーニングするときの一般的なパターンは、トレーニングが進むにつれて学習を徐々に減らすことです。これは一般に「学習率の減衰」として知られています。

学習減衰スケジュールは、静的(現在のエポックまたは現在のバッチインデックスの関数として事前に修正)または動的(モデルの現在の動作、特に検証損失に対応)にすることができます。

オプティマイザーにスケジュールを渡す

オプティマイザーでlearning_rate引数としてスケジュールオブジェクトを渡すことにより、静的な学習率の減衰スケジュールを簡単に使用できます。

initial_learning_rate = 0.1
lr_schedule = keras.optimizers.schedules.ExponentialDecay(
    initial_learning_rate, decay_steps=100000, decay_rate=0.96, staircase=True
)

optimizer = keras.optimizers.RMSprop(learning_rate=lr_schedule)

ExponentialDecayPiecewiseConstantDecayPolynomialDecayInverseTimeDecayなどの組み込みのスケジュールを使用できます。

コールバックを使用して動的な学習率スケジュールを実装する

オプティマイザーは検証メトリックにアクセスできないため、動的学習率スケジュール(たとえば、検証損失が改善されなくなったときに学習率を下げる)は、これらのスケジュールオブジェクトでは実現できません。

ただし、コールバックは検証メトリックを含むすべてのメトリックにアクセスできます。したがって、オプティマイザーの現在の学習率を変更するコールバックを使用することで、このパターンを実現できます。実際、これはReduceLROnPlateauコールバックとしても組み込まれています。

トレーニング中の損失と指標の視覚化

トレーニング中にモデルを監視する最良の方法は、ローカルで実行できるブラウザベースのアプリケーションであるTensorBoardを使用することです。

  • トレーニングと評価のための損失とメトリックのライブプロット
  • (オプション)レイヤーアクティベーションのヒストグラムの視覚化
  • (オプション) Embeddingレイヤーによって学習された埋め込みスペースの3D視覚化

pipを使用してTensorFlowをインストールした場合は、コマンドラインからTensorBoardを起動できるはずです。

tensorboard --logdir=/full_path_to_your_logs

TensorBoardコールバックの使用

KerasモデルとfitメソッドでTensorBoardを使用する最も簡単な方法は、 TensorBoardコールバックです。

最も単純なケースでは、コールバックにログを書き込む場所を指定するだけで、次のようになります。

keras.callbacks.TensorBoard(
    log_dir="/full_path_to_your_logs",
    histogram_freq=0,  # How often to log histogram visualizations
    embeddings_freq=0,  # How often to log embedding visualizations
    update_freq="epoch",
)  # How often to write logs (default: once per epoch)
<tensorflow.python.keras.callbacks.TensorBoard at 0x7f74ec5179e8>

詳細については、 TensorBoardコールバックのドキュメントを参照してください。