Keras 2 : ガイド : 組込みメソッドで訓練と評価 (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 10/24/2021 (keras 2.6.0)
* 本ページは、Keras の以下のドキュメントを翻訳した上で適宜、補足説明したものです:
- Training & evaluation with the built-in methods (Author: fchollet)
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
- 人工知能研究開発支援
- 人工知能研修サービス(経営者層向けオンサイト研修)
- テクニカルコンサルティングサービス
- 実証実験(プロトタイプ構築)
- アプリケーションへの実装
- 人工知能研修サービス
- PoC(概念実証)を失敗させないための支援
- テレワーク & オンライン授業を支援
- お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
- ウェビナー運用には弊社製品「ClassCat® Webinar」を利用しています。
◆ お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。
株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション |
E-Mail:sales-info@classcat.com ; WebSite: https://www.classcat.com/ ; Facebook |
Keras 2 : ガイド : 組込みメソッドで訓練と評価
セットアップ
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
イントロダクション
このガイドは (Model.fit(), Model.evaluate() と Model.predict() のような) 訓練 & 検証のための組込み API を使用するときの訓練、評価と予測 (推論) モデルをカバーします。
独自の訓練ステップ関数を指定する間に fit() を利用することに関心がある場合には、Customizing what happens in fit() ガイドを見てください。
独自の訓練 & 評価ループをスクラッチから書くことに関心がある場合には、ガイド “writing a training loop from scratch” を見てください。
一般に、組み込みループを使用していようが独自のものを書いていようが、モデル訓練 & 評価は総ての種類の Keras モデル — シーケンシャル・モデル、関数型 API で構築されたモデル、そしてモデル・サブクラス化を通してスクラッチから書かれたモデル — に渡り厳密に同じように動作します。
このガイドは分散訓練はカバーしません、これは multi-GPU & distributed training へのガイドでカバーされます。
API 概要: 最初の end-to-end サンプル
データをモデルの組み込み訓練ループに渡すとき、(もしデータが小さくてメモリに収まるのであれば) Numpy 配列 か tf.data Dataset オブジェクトを使用するべきです。次の幾つかのパラグラフでは、optimizer、損失そしてメトリクスの使用方法を実演するために、MNIST データセットを Numpy 配列として使用します。
次のモデルを考えましょう (ここでは、関数型 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)
ここに典型的な end-to-end ワークフローがどのようなものかがあり、以下から成ります :
- 訓練
- 元の訓練データから生成された取り置いたセット上の検証
- テストデータ上の評価
このサンプルのために 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]
訓練 configuration を指定します (optimizer、損失、メトリクス) :
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 の “batches” にスライスし、そして与えられた数の epochs のためにデータセット全体に渡り繰り返し反復します。
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.3402 - sparse_categorical_accuracy: 0.9048 - val_loss: 0.1810 - val_sparse_categorical_accuracy: 0.9475 Epoch 2/2 782/782 [==============================] - 1s 978us/step - loss: 0.1561 - sparse_categorical_accuracy: 0.9537 - val_loss: 0.1637 - val_sparse_categorical_accuracy: 0.9529
返された history オブジェクトは訓練の間の損失値とメトリック値の記録を保持しています :
history.history
{'loss': [0.3402276635169983, 0.15610544383525848], 'sparse_categorical_accuracy': [0.9048200249671936, 0.9537400007247925], 'val_loss': [0.1809607595205307, 0.16366209089756012], 'val_sparse_categorical_accuracy': [0.9474999904632568, 0.9528999924659729]}
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 846us/step - loss: 0.1587 - sparse_categorical_accuracy: 0.9513 test loss, test acc: [0.15874555706977844, 0.9513000249862671] Generate predictions for 3 samples predictions shape: (3, 10)
今は、このワークフローの各ピースを詳細にレビューしましょう。
compile() メソッド: 損失、メトリクス、そして optimizer を指定する
fit でモデルを訓練するためには、損失関数、optimizer そしてオプションで監視するための幾つかのメトリクスを指定する必要があります。
これらをモデルに compile() メソッドへの引数として渡します :
model.compile(
optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
loss=keras.losses.SparseCategoricalCrossentropy(),
metrics=[keras.metrics.SparseCategoricalAccuracy()],
)
metrics 引数はリストであるべきです — モデルは任意の数のメトリクスを持つことができます。
モデルがマルチ出力を持つ場合、各出力に対して異なる損失とメトリクスを指定できて、そしてモデルのトータル損失への各出力の寄与を調節できます。これについての更なる詳細を “Passing data to multi-input, multi-output models” セクションで見つけるでしょう。
デフォルト設定で満足できる場合には、多くの場合 optimizer、損失とメトリクスはショートカットとして文字列識別子で指定できることに注意してください :
model.compile(
optimizer="rmsprop",
loss="sparse_categorical_crossentropy",
metrics=["sparse_categorical_accuracy"],
)
後で再利用するために、モデル定義と compile ステップを関数内に配置しましょう ; それらをこのガイドの異なるサンプルに渡り幾度か呼び出します。
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
多くの組み込み optimizer、損失とメトリクスが利用可能です
一般に、独自の損失、メトリクスや optimizer をスクラッチから作成しなくてもかまいません、何故ならば必要なものは既に Keras API の一部でありがちだからです :
Optimizers :
- SGD() (with or without モメンタム)
- 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 756us/step - loss: 0.0279 <tensorflow.python.keras.callbacks.History at 0x14d2534d0>
y_true と y_pred の他のパラメータを取る損失関数を必要とする場合、tf.keras.losses.Loss クラスをサブクラス化して次の 2 つのメソッドを実装することができます :
- __init__(self) : 損失関数の呼び出しの間に渡すためのパラメータを受け取ります。
- call(self, y_true, y_pred) : モデルの損失を計算するためにターゲット (y_true) とモデル予測 (y_pred) を使用します。
平均二乗誤差を使用することを望むとしましょう、但し 0.5 から遠い予測値に刺激を与えないような (= de-incentivize) 追加項とともに (categorical ターゲットは one-hot エンコードされて 0 と 1 の間の値を取るものと仮定します)。これはモデルが確信し過ぎないようにインセンティブを作成します、これは overfitting を減じるのに役立つかもしれません (それが動作するかは試すまで分かりません!)。
ここにそれをどのように行なうかがあります :
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 787us/step - loss: 0.0484 <tensorflow.python.keras.callbacks.History at 0x14d43edd0>
カスタム・メトリクス
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() で) 別々にしておきます、何故ならばある場合には、結果計算は非常に高価であるかもしれないためで、それは定期的にだけ行われるでしょう。
ここに CatgoricalTruePositives メトリックを実装する方法を示す単純なサンプルがあります、それは与えられたクラスに属するものとして正しく分類されたサンプルが幾つかを数えます :
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 871us/step - loss: 0.5631 - categorical_true_positives: 22107.3525 Epoch 2/3 782/782 [==============================] - 1s 826us/step - loss: 0.1679 - categorical_true_positives: 23860.3078 Epoch 3/3 782/782 [==============================] - 1s 823us/step - loss: 0.1102 - categorical_true_positives: 24231.2771 <tensorflow.python.keras.callbacks.History at 0x14d578bd0>
標準的なシグネチャに当てはまらない損失とメトリクスを扱う
損失とメトリクスの圧倒的な大部分は y_true と y_pred から計算できます、ここで y_pred はモデルの出力です — しかし総てではありません。例えば、正則化損失は層の活性を必要とするだけかもしれません (この場合ターゲットはありません)、そしてこの活性はモデル出力ではないかもしれません。
そのような場合、カスタム層の call メソッドの内側から self.add_loss(loss_value) を呼び出すことができます。このように追加された損失は訓練の間は “main” 損失に追加されます (compile() に渡された 1 つ)。ここに activity 正則化を追加する単純なサンプルがあります (activity 正則化は総ての 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 828us/step - loss: 3.5361 <tensorflow.python.keras.callbacks.History at 0x14d6de210>
add_metric() を使用して、logging メトリック値に対しても同じことを行うことができます :
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 859us/step - loss: 0.5469 - std_of_activation: 0.9414 <tensorflow.python.keras.callbacks.History at 0x14d827ed0>
関数型 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 875us/step - loss: 3.4905 - std_of_activation: 0.0019 <tensorflow.python.keras.callbacks.History at 0x14d944790>
add_loss() を通して損失を渡すとき損失関数なしで compile() を呼び出すことが可能になることに注意してください、何故ならばモデルは既に最小化するための損失を持っているからです。
次の LogisticEndpoint 層を考えます : それは入力として targets & logits を取り、そしてそれは add_loss() を通して交差エントロピー損失を追跡します。それはまた 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)
それを 2 つの入力 (入力データ & ターゲット) を持つ (loss 引数なしでコンパイルされた) モデルで使用することができます、このようにです :
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 241ms/step - loss: 0.9990 - binary_accuracy: 0.0000e+00 <tensorflow.python.keras.callbacks.History at 0x14da49f10>
マルチ入力モデルの訓練についてより多くの情報のためには、セクション Passing data to multi-input, multi-output models を見てください。
検証取り置き (= holdout) セットを自動的に分離する
貴方が見た最初の end-to-end サンプルでは、各エポックの終わりに検証損失と検証メトリクスを評価するために NumPy 配列のタプル (x_val, y_val) をモデルに渡すために validation_data 引数を使用しました。
ここにもう一つのオプションがあります : 引数 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 1ms/step - loss: 0.6263 - sparse_categorical_accuracy: 0.8288 - val_loss: 0.2548 - val_sparse_categorical_accuracy: 0.9206 <tensorflow.python.keras.callbacks.History at 0x14db21a90>
tf.data Datasets からの訓練 & 評価
前の 2, 3 のパラグラフでは、損失、メトリクスと optimizer をどのように扱うかを見ました、そしてデータが NumPy 配列として渡されるとき、fit で validation_data と validation_split 引数をどのように使用するかを見ました。
今は貴方のデータが tf.data Dataset の形式で現れる場合を見ましょう。
tf.data API はデータを高速でスケーラブルな方法でロードして前処理するための TensorFlow 2.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 [==============================] - 1s 1ms/step - loss: 0.5631 - sparse_categorical_accuracy: 0.8472 Epoch 2/3 782/782 [==============================] - 1s 1ms/step - loss: 0.1676 - sparse_categorical_accuracy: 0.9497 Epoch 3/3 782/782 [==============================] - 1s 1ms/step - loss: 0.1211 - sparse_categorical_accuracy: 0.9638 Evaluate 157/157 [==============================] - 0s 790us/step - loss: 0.1231 - sparse_categorical_accuracy: 0.9625 {'loss': 0.1230572983622551, 'sparse_categorical_accuracy': 0.9624999761581421}
Dataset は各エポックの最後にリセットされますので、それは次のエポックで再利用できることに注意してください。
このデータセットから特定の数のバッチ上でだけ訓練を実行することを望む場合、steps_per_epoch 引数を渡すことができます、これは次のエポックに移る前にこの Dataset を使用してモデルが幾つの訓練ステップを実行するべきかを指定します。
これを行なう場合、dataset は各エポックの最後にリセットされません、代わりに次のバッチを単にドローし続けます。dataset はやがてデータを使い果たします (それが無限ループな 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)
# 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 1ms/step - loss: 1.2444 - sparse_categorical_accuracy: 0.6461 Epoch 2/3 100/100 [==============================] - 0s 1ms/step - loss: 0.3783 - sparse_categorical_accuracy: 0.8929 Epoch 3/3 100/100 [==============================] - 0s 1ms/step - loss: 0.3543 - sparse_categorical_accuracy: 0.8988 <tensorflow.python.keras.callbacks.History at 0x14de00790>
検証 dataset を使用する
Dataset インスタンスを fit の validation_data 引数として渡すことができます :
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 [==============================] - 1s 1ms/step - loss: 0.5465 - sparse_categorical_accuracy: 0.8459 - val_loss: 0.1943 - val_sparse_categorical_accuracy: 0.9435 <tensorflow.python.keras.callbacks.History at 0x14df31d10>
各エポックの最後に、モデルは検証 Dataset に渡り反復して検証損失と検証メトリクスを計算します。
この Dataset から特定の数のバッチ上でだけ検証を実行することを望む場合、validation_steps 引数を渡すことができます、これはモデルが検証を中断して次のエポックに進む前に検証 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,
# 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 [==============================] - 1s 1ms/step - loss: 0.5561 - sparse_categorical_accuracy: 0.8464 - val_loss: 0.2889 - val_sparse_categorical_accuracy: 0.9156 <tensorflow.python.keras.callbacks.History at 0x14df31810>
検証 Dataset は各使用の後にリセットされることに注意してください (その結果エポックからエポックへ同じサンプル上で常に評価しています)。
Dataset オブジェクトから訓練するときには (訓練データから取り置いたセットを生成する) 引数 validation_split はサポートされません、何故ならばこの機能は (Dataset API では一般に可能ではない) dataset のサンプルをインデックスする機能を必要とするからです。
サポートされる他の入力フォーマット
Numpy 配列、eager テンソルと TensorFlow Dataset の他にも、Pandas データフレームを使用したりデータ & ラベルのバッチを生成する Python ジェネレータから Keras モデルを訓練することが可能です。
特に、keras.utils.Sequence クラスは (マルチプロセッシング-aware でシャッフル可能な) Python データ・ジェネレータを構築するための単純なインターフェイスを提供します。
一般に、以下を利用することを勧めます :
- データが小さくてメモリに収まるのであれば NumPy 入力データ
- 大規模なデータセットを持ち分散訓練を行なうことを必要とするのであれば Dataset オブジェクト
- 大規模なデータセットを持ち TensorFlow では成せない多くのカスタム Python-側処理を行なう必要があれば Sequence オブジェクト (e.g. データロードや前処理のために外部ライブラリに依存する場合)。
入力として keras.utils.Sequence オブジェクトを使用する
keras.utils.Sequence は 2 つの重要な特性を持つ Python ジェネレータを得るためにサブクラス化できるユティリティです :
- それはマルチプロセッシングと上手く動作します。
- それはシャッフルできます (e.g. fit() で shuffle=True を渡すとき)。
シークエンスは 2 つのメソッドを実装しなければなりません :
- __getitem__
- __len__
メソッド __getitem__ は完全なバッチを返すべきです。エポック間でデータセットを変更することを望む場合、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}) を使用できるでしょう。
ここに NumPy サンプルがあります、そこではクラス #5 (これは MNIST データセットの数字 “5” です) の正しい分類により多くの重要性を与えるためにクラス重みかサンプル重みを使用します。
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 [==============================] - 1s 933us/step - loss: 0.6334 - sparse_categorical_accuracy: 0.8297 <tensorflow.python.keras.callbacks.History at 0x14e20f990>
サンプル重み
極め細かい制御のため、あるいは分類器を構築していない場合、”sample weights” を利用できます。
- NumPy データから訓練するとき : Model.fit() に sample_weight 引数を渡す。
- tf.data か任意の他の種類の iterator から訓練するとき : (input_batch, label_batch, sample_weight_batch) タプルを生成します。
“sample weights” 配列は、トータル損失を計算するときにバッチの各サンプルがどのくらいの重みを持つべきであるかを指定する数字の配列です。それは一般に不均衡な分類問題で使用されます (滅多に見られないクラスにより大きな重みを与えるアイデアです)。
使用される重みが ones か zeros であるとき、配列は損失関数のためのマスクとして使用できます (特定のサンプルのトータル損失への寄与を完全に捨てます)。
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 [==============================] - 1s 899us/step - loss: 0.6337 - sparse_categorical_accuracy: 0.8355 <tensorflow.python.keras.callbacks.History at 0x14e3538d0>
ここに適合している 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 [==============================] - 1s 1ms/step - loss: 0.6539 - sparse_categorical_accuracy: 0.8364 <tensorflow.python.keras.callbacks.History at 0x14e49c390>
データをマルチ入力、マルチ出力モデルに渡す
前のサンプルでは、単一の入力 (shape (764,) のテンソル) と単一の出力 (shape (10,) の予測テンソル) を持つモデルを考えていました。しかしマルチ入力や出力を持つモデルについてはどうでしょう?
次のモデルを考えます、これは shape (32, 32, 3) (それは (高さ、幅、チャネル)) の画像入力と shape (None, 10) (それは (時間ステップ, 特徴)) の時系列入力を持ちます。私達のモデルはこれらの入力の組み合わせから計算された 2 つの出力を持ちます : (shape (1,) の) 「スコア」と (shape (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]
)
このモデルをプロットしましょう、そうすれば私達がここで何をしているかを明瞭に見ることができます (プロットで示される shape はサンプル毎 shape ではなくバッチ shape であることに注意してください)。
keras.utils.plot_model(model, "multi_input_and_output_model.png", show_shapes=True)
コンパイル時、損失関数をリストとして渡すことにより、異なる出力に対して異なる損失を指定できます :
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()],
],
)
出力層に名前を与えましたので、辞書を通して出力毎の損失とメトリクスを指定することもできるでしょう :
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()],
},
)
2 出力以上を持つ場合、明示的な名前と辞書の使用を勧めます。
loss_weights 引数を使用して、異なる出力固有の損失に異なる重みを与えることも可能です (例えば、私達の例の「スコア」損失にクラス損失の 2 倍の重要性を与えることにより、特権を与えることを望むかもしれません) :
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()},
)
マルチ入力やマルチ出力モデルに fit でデータを渡すことは compile で損失関数を指定するのと同様な方法で動作します : (損失関数を受け取った出力への 1:1 マッピングを持つ) NumPy 配列のリスト や 出力名を 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 [==============================] - 1s 5ms/step - loss: 13.0462 - score_output_loss: 2.7483 - class_output_loss: 10.2979 4/4 [==============================] - 0s 4ms/step - loss: 11.9004 - score_output_loss: 1.7583 - class_output_loss: 10.1420 <tensorflow.python.keras.callbacks.History at 0x14e67af50>
ここに Dataset のユースケースがあります : NumPy 配列のために行なったことと同様です、Dataset は辞書のタプルを返すべきです。
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 6ms/step - loss: 11.5102 - score_output_loss: 1.3747 - class_output_loss: 10.1355 <tensorflow.python.keras.callbacks.History at 0x14dc5ce90>
コールバックを使用する
Keras の Callbacks は訓練の間に様々なポイント (エポックの最初、バッチの最後、エポックの最後, etc.) で呼び出されるオブジェクトです。それらは次のような動作を実装するために使用できます :
- 訓練の間に様々なポイントで検証を行なう (組込みのエポック毎検証とは別に)
- 定期の間隔であるいはそれが特定の精度しきい値を超えたときにモデルをチェックポイントする
- 訓練が頭打ちになったように見えるときにモデルの学習率を変更する
- 訓練が頭打ちになったように見えるときに top 層の再調整を行なう
- 訓練が終わるときあるいは特定のパフォーマンスしきい値を超えたところで電子メールかインスタントメッセージ通知を送る
- 等々。
Callback は 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 1ms/step - loss: 0.6032 - sparse_categorical_accuracy: 0.8355 - val_loss: 0.2303 - val_sparse_categorical_accuracy: 0.9306 Epoch 2/20 625/625 [==============================] - 1s 1ms/step - loss: 0.1855 - sparse_categorical_accuracy: 0.9458 - val_loss: 0.1775 - val_sparse_categorical_accuracy: 0.9471 Epoch 3/20 625/625 [==============================] - 1s 1ms/step - loss: 0.1280 - sparse_categorical_accuracy: 0.9597 - val_loss: 0.1585 - val_sparse_categorical_accuracy: 0.9531 Epoch 4/20 625/625 [==============================] - 1s 1ms/step - loss: 0.0986 - sparse_categorical_accuracy: 0.9704 - val_loss: 0.1418 - val_sparse_categorical_accuracy: 0.9593 Epoch 5/20 625/625 [==============================] - 1s 1ms/step - loss: 0.0774 - sparse_categorical_accuracy: 0.9761 - val_loss: 0.1319 - val_sparse_categorical_accuracy: 0.9628 Epoch 6/20 625/625 [==============================] - 1s 1ms/step - loss: 0.0649 - sparse_categorical_accuracy: 0.9798 - val_loss: 0.1465 - val_sparse_categorical_accuracy: 0.9580 Epoch 00006: early stopping <tensorflow.python.keras.callbacks.History at 0x14e899ad0>
多くの組込みコールバックが利用可能です
以下のような、Keras で既に利用可能な多くの組込みコールバックがあります :
- ModelCheckpoint: 定期的にモデルをセーブする。
- EarlyStopping: 訓練がもはや検証メトリクスを改善しないときに訓練を停止する。
- TensorBoard: TensorBoard で可視化できるモデルログを定期的に書く (セクション「可視化」で更なる詳細)。
- CSVLogger: 損失とメトリクス・データを CSV ファイルにストリームする。
- etc.
完全なリストについては callbacks ドキュメント を見てください。
独自のコールバックを書く
基底クラス keras.callbacks.Callback を拡張することでカスタム callback を作成できます。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 625/625 [==============================] - 1s 1ms/step - loss: 0.6380 - sparse_categorical_accuracy: 0.8226 - val_loss: 0.2283 - val_sparse_categorical_accuracy: 0.9317 Epoch 00001: val_loss improved from inf to 0.22825, saving model to mymodel_1 INFO:tensorflow:Assets written to: mymodel_1/assets Epoch 2/2 625/625 [==============================] - 1s 1ms/step - loss: 0.1787 - sparse_categorical_accuracy: 0.9466 - val_loss: 0.1877 - val_sparse_categorical_accuracy: 0.9440 Epoch 00002: val_loss improved from 0.22825 to 0.18768, saving model to mymodel_2 INFO:tensorflow:Assets written to: mymodel_2/assets <tensorflow.python.keras.callbacks.History at 0x14e899b90>
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 98/1563 [>.............................] - ETA: 1s - loss: 1.3456 - sparse_categorical_accuracy: 0.6230INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.90/assets 155/1563 [=>............................] - ETA: 5s - loss: 1.1479 - sparse_categorical_accuracy: 0.6822INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.66/assets 248/1563 [===>..........................] - ETA: 5s - loss: 0.9643 - sparse_categorical_accuracy: 0.7340INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.57/assets 353/1563 [=====>........................] - ETA: 5s - loss: 0.8454 - sparse_categorical_accuracy: 0.7668INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.50/assets 449/1563 [=======>......................] - ETA: 5s - loss: 0.7714 - sparse_categorical_accuracy: 0.7870INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.47/assets 598/1563 [==========>...................] - ETA: 4s - loss: 0.6930 - sparse_categorical_accuracy: 0.8082INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.43/assets 658/1563 [===========>..................] - ETA: 4s - loss: 0.6685 - sparse_categorical_accuracy: 0.8148INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.41/assets 757/1563 [=============>................] - ETA: 4s - loss: 0.6340 - sparse_categorical_accuracy: 0.8241INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.39/assets 856/1563 [===============>..............] - ETA: 3s - loss: 0.6051 - sparse_categorical_accuracy: 0.8319INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.37/assets 956/1563 [=================>............] - ETA: 3s - loss: 0.5801 - sparse_categorical_accuracy: 0.8387INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.35/assets 1057/1563 [===================>..........] - ETA: 2s - loss: 0.5583 - sparse_categorical_accuracy: 0.8446INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.34/assets 1153/1563 [=====================>........] - ETA: 2s - loss: 0.5399 - sparse_categorical_accuracy: 0.8495INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.33/assets 1255/1563 [=======================>......] - ETA: 1s - loss: 0.5225 - sparse_categorical_accuracy: 0.8542INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.32/assets 1355/1563 [=========================>....] - ETA: 1s - loss: 0.5073 - sparse_categorical_accuracy: 0.8583INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.31/assets 1457/1563 [==========================>...] - ETA: 0s - loss: 0.4933 - sparse_categorical_accuracy: 0.8621INFO:tensorflow:Assets written to: ./ckpt/ckpt-loss=0.30/assets 1563/1563 [==============================] - 8s 5ms/step - loss: 0.4800 - sparse_categorical_accuracy: 0.8657 <tensorflow.python.keras.callbacks.History at 0x14ec08390>
モデルをセーブしてリストアするための独自のコールバックを書くこともできます。
シリアライゼーションとセービングについての完全なガイドは、Saving and Serializing Models へのガイドを見てください。
学習率スケジュールを使用する
深層学習モデルを訓練するときの共通のパターンは訓練が進むにつれて学習率を徐々に減じることです。これは一般に「学習率減衰 (= decay)」として知られています。
学習率減衰スケジュールは静的 (現在のエポックや現在のバッチインデックスの関数として、前もって固定) でも動的 (モデルの現在の動作に呼応、特に検証損失) でもあり得るでしょう。
スケジュールを optimizer に渡す
スケジュール・オブジェクトを optimizer の 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)
幾つかの組込みスケジュールが利用可能です : ExponentialDecay, PiecewiseConstantDecay, PolynomialDecay そして InverseTimeDecay.
動的学習率スケジュールを実装するためにコールバックを使用する
動的学習率スケジュール (例えば、検証損失がもはや改善しないときに学習率を減じます) はこれらのスケジュール・オブジェクトでは達成できません、何故ならば optimizer は検証メトリクスへのアクセスを持たないからです。
けれども、コールバックは検証メトリクスを含む、総てのメトリクスへのアクセスを持ちます!こうして optimizer の現在の学習率を変更するコールバックを使用してこのパターンを達成できます。実際に、これは ReduceLROnPlateau コールバックとして組込みでさえあります。
訓練の間の損失とメトリクスを可視化する
訓練の間にモデルを監視する最善の方法は TensorBoard を使用することです、これは以下を提供する、貴方がローカルで実行できるブラウザ・ベースのアプリケーションです :
- 訓練と評価のための損失とメトリクスのライブプロット
- (オプションで) 層活性のヒストグラムの可視化
- (オプションで) Embedding 層で学習された埋め込み空間の 3D 可視化
TensorFlow を pip でインストールしたのであれば、次のコマンドラインから 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 0x14ecb1d10>
For more information, see the documentation for the TensorBoard callback.
以上