In [ ]:
#@title Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
Note: これらのドキュメントは私たちTensorFlowコミュニティが翻訳したものです。コミュニティによる 翻訳はベストエフォートであるため、この翻訳が正確であることや英語の公式ドキュメントの 最新の状態を反映したものであることを保証することはできません。 この翻訳の品質を向上させるためのご意見をお持ちの方は、GitHubリポジトリtensorflow/docsにプルリクエストをお送りください。 コミュニティによる翻訳やレビューに参加していただける方は、 docs-ja@tensorflow.org メーリングリストにご連絡ください。
Kerasは、深層学習モデルを構築・学習するための高水準APIです。
迅速なプロトタイピングから先端研究、実運用にも使用されており、3つの特徴があります:
tf.keras は、TensorFlow版 Keras API 仕様 です。
モデルを構築・学習するための高水準APIであり、TensorFlow特有の機能である
Eagerモードやtf.data パイプライン、 Estimators にも正式に対応しています。
tf.keras は、TensorFlowの柔軟性やパフォーマンスを損ねることなく使いやすさを向上しています。
TensorFlowプログラムの準備として、先ずは tf.keras をインポートしましょう:
In [ ]:
!pip install tensorflow=="1.*"
In [ ]:
!pip install pyyaml # YAML形式でモデルを保存する際に必要です。
In [ ]:
import tensorflow.compat.v1 as tf
from tensorflow.keras import layers
print(tf.version.VERSION)
print(tf.keras.__version__)
tf.keras ではKerasと互換性のあるコードを実行できますが、注意点もあります:
tf.keras のバージョンと、pipインストールした最新の keras のバージョンが同一とは限りません。バージョンは tf.keras.__version__ の出力をご確認ください。tf.keras のデフォルトの保存形式は チェックポイント形式です。
HDF5形式にて保存する場合は、 save_format='h5' オプションを指定してください。
In [ ]:
model = tf.keras.Sequential()
# ユニット数が64の全結合層をモデルに追加します:
model.add(layers.Dense(64, activation='relu'))
# 全結合層をもう一つ追加します:
model.add(layers.Dense(64, activation='relu'))
# 出力ユニット数が10のソフトマックス層を追加します:
model.add(layers.Dense(10, activation='softmax'))
tf.keras.layers はさまざまな層を提供していますが、共通のコンストラクタ引数があります:
activation: 層の活性化関数を設定します。組み込み関数、もしくは呼び出し可能オブジェクトの名前で指定します。デフォルト値は、活性化関数なし。kernel_initializer ・ bias_initializer: 層の重み(カーネルとバイアス)の初期化方式。名前、もしくは呼び出し可能オブジェクトで指定します。デフォルト値は、 "Glorot uniform" 。kernel_regularizer ・ bias_regularizer:層の重み(カーネルとバイアス)に適用する、L1やL2等の正則化方式。デフォルト値は、正則化なし。コンストラクタ引数を使って tf.keras.layers.Dense 層をインスタンス化する例を以下に示します:
In [ ]:
# シグモイド層を1層作る場合:
layers.Dense(64, activation='sigmoid')
# 別の記法:
layers.Dense(64, activation=tf.sigmoid)
# カーネル行列に係数0,01のL1正則化を課した全結合層:
layers.Dense(64, kernel_regularizer=tf.keras.regularizers.l1(0.01))
# バイアスベクトルに係数0,01のL2正則化を課した全結合層:
layers.Dense(64, bias_regularizer=tf.keras.regularizers.l2(0.01))
# カーネルをランダム直交行列で初期化した全結合層:
layers.Dense(64, kernel_initializer='orthogonal')
# バイアスベクトルを2.0で初期化した全結合層:
layers.Dense(64, bias_initializer=tf.keras.initializers.constant(2.0))
In [ ]:
model = tf.keras.Sequential([
# ユニット数64の全結合層をモデルに追加する:
layers.Dense(64, activation='relu', input_shape=(32,)),
# もう1層追加する:
layers.Dense(64, activation='relu'),
# 出力ユニット数10のソフトマックス層を追加する:
layers.Dense(10, activation='softmax')])
model.compile(optimizer=tf.train.AdamOptimizer(0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
tf.keras.Model.compile には3つの重要な引数があります:
optimizer: このオブジェクトが訓練方式を規定します。 tf.train モジュールから
tf.train.AdamOptimizerや tf.train.RMSPropOptimizer、
tf.train.GradientDescentOptimizer等のオプティマイザ インスタンスを指定します。loss: 最適化の過程で最小化する関数を指定します。平均二乗誤差(mse)やcategorical_crossentropy、
binary_crossentropy等が好んで使われます。損失関数は名前、もしくは tf.keras.losses モジュールから呼び出し可能オブジェクトとして指定できます。metrics: 学習の監視に使用します。 名前、もしくはtf.keras.metrics モジュールから呼び出し可能オブジェクトとして指定できます。学習用モデルの構成例を2つ、以下に示します:
In [ ]:
# 平均二乗誤差 回帰モデルを構成する。
model.compile(optimizer=tf.train.AdamOptimizer(0.01),
loss='mse', # 平均二乗誤差
metrics=['mae']) # 平均絶対誤差
# 多クラス分類モデルを構成する。
model.compile(optimizer=tf.train.RMSPropOptimizer(0.01),
loss=tf.keras.losses.categorical_crossentropy,
metrics=[tf.keras.metrics.categorical_accuracy])
小規模なデータセットであれば、モデルを学習・評価する際にインメモリの NumPy配列を使いましょう。
モデルは fit メソッドを使って学習データに適合させます。
In [ ]:
import numpy as np
def random_one_hot_labels(shape):
n, n_class = shape
classes = np.random.randint(0, n_class, n)
labels = np.zeros((n, n_class))
labels[np.arange(n), classes] = 1
return labels
data = np.random.random((1000, 32))
labels = random_one_hot_labels((1000, 10))
model.fit(data, labels, epochs=10, batch_size=32)
tf.keras.Model.fit は3つの重要な引数があります:
epochs: エポック は学習の構成単位で、(バッチに分割した)全入力データを一巡したものを1エポックと換算します。batch_size: NumPyデータを渡されたモデルは、データをバッチに分割し、それを順繰りに舐めて学習を行います。一つのバッチに配分するサンプル数を、バッチサイズとして整数で指定します。全サンプル数がバッチサイズで割り切れない場合、最後のバッチだけ小さくなる可能性があることに注意しましょう。validation_data: モデルの試作中に評価データを使って簡単にパフォーマンスを監視したい場合は、この引数に入力とラベルの対を渡すことで、各エポックの最後に推論モードで評価データの損失と評価指標を表示することができます。validation_data の使用例:
In [ ]:
import numpy as np
data = np.random.random((1000, 32))
labels = random_one_hot_labels((1000, 10))
val_data = np.random.random((100, 32))
val_labels = random_one_hot_labels((100, 10))
model.fit(data, labels, epochs=10, batch_size=32,
validation_data=(val_data, val_labels))
大規模なデータセット、もしくは複数デバイスを用いた学習を行う際は Datasets API を使いましょう。 fitメソッドにtf.data.Dataset インスタンスを渡します:
In [ ]:
# データセットのインスタンス化の例:
dataset = tf.data.Dataset.from_tensor_slices((data, labels))
dataset = dataset.batch(32)
dataset = dataset.repeat()
# `fit` にデータセットを渡す際は、`steps_per_epoch` の指定をお忘れなく:
model.fit(dataset, epochs=10, steps_per_epoch=30)
fit メソッドの引数 steps_per_epoch には、1エポックあたりの学習ステップ数を指定します。
Dataset がバッチを生成するため batch_sizeの指定は不要です。
Dataset は評価データにも使えます:
In [ ]:
dataset = tf.data.Dataset.from_tensor_slices((data, labels))
dataset = dataset.batch(32).repeat()
val_dataset = tf.data.Dataset.from_tensor_slices((val_data, val_labels))
val_dataset = val_dataset.batch(32).repeat()
model.fit(dataset, epochs=10, steps_per_epoch=30,
validation_data=val_dataset,
validation_steps=3)
In [ ]:
data = np.random.random((1000, 32))
labels = random_one_hot_labels((1000, 10))
model.evaluate(data, labels, batch_size=32)
model.evaluate(dataset, steps=30)
推論 結果を最終層のNumPy配列として出力する例を示します:
In [ ]:
result = model.predict(data, batch_size=32)
print(result.shape)
tf.keras.Sequential モデルは層を積み重ねる単純なつくりであり、あらゆるモデルに対応しているわけではありません。
以下に挙げる複雑な構成のモデルを構築するには
Keras functional API
を使いましょう:
Functional API を用いたモデル構築の流れ:
tf.keras.Modelインスタンスを定義します。Sequentialモデルと同様の方法で学習します。Functional API を使って全結合ネットワークを構築する例を示します:
In [ ]:
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)
inputsとoutputsを引数にモデルをインスタンス化します。
In [ ]:
model = tf.keras.Model(inputs=inputs, outputs=predictions)
# コンパイル時に学習方法を指定します。
model.compile(optimizer=tf.train.RMSPropOptimizer(0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
# 5エポック学習します。
model.fit(data, labels, batch_size=32, epochs=5)
tf.keras.Model を継承し順伝播を定義することでカスタムモデルを構築できます。
__init__ メソッドにクラス インスタンスの属性として層をつくります。
call メソッドに順伝播を定義します。
順伝播を命令型で記載できるため、モデルの派生は Eagerモード でより威力を発揮します。
キーポイント:目的にあったAPIを選択しましょう。派生モデルは柔軟性を与えてくれますが、その代償にモデルはより複雑になりエラーを起こしやすくなります。目的がFunctional APIで賄えるのであれば、そちらを使いましょう。
tf.keras.Modelを継承して順伝播をカスタマイズした例を以下に示します:
In [ ]:
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)
def compute_output_shape(self, input_shape):
# 派生モデルを使用する場合、
# このメソッドをオーバーライドすることになります。
# 派生モデルを使用しない場合、このメソッドは省略可能です。
shape = tf.TensorShape(input_shape).as_list()
shape[-1] = self.num_classes
return tf.TensorShape(shape)
今定義した派生モデルをインスンス化します。
In [ ]:
model = MyModel(num_classes=10)
# コンパイル時に学習方法を指定します。
model.compile(optimizer=tf.train.RMSPropOptimizer(0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
# 5エポック学習します。
model.fit(data, labels, batch_size=32, epochs=5)
In [ ]:
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):
shape = tf.TensorShape((input_shape[1], self.output_dim))
# 学習可能な重みを指定します。
self.kernel = self.add_weight(name='kernel',
shape=shape,
initializer='uniform',
trainable=True)
# 最後に`build` メソッドを呼ぶのをお忘れなく。
super(MyLayer, self).build(input_shape)
def call(self, inputs):
return tf.matmul(inputs, self.kernel)
def compute_output_shape(self, input_shape):
shape = tf.TensorShape(input_shape).as_list()
shape[-1] = self.output_dim
return tf.TensorShape(shape)
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)
カスタマイズした層を使ってモデルを構築します:
In [ ]:
model = tf.keras.Sequential([
MyLayer(10),
layers.Activation('softmax')])
# コンパイル時に学習方法を指定します。
model.compile(optimizer=tf.train.RMSPropOptimizer(0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
# 5エポック学習します。
model.fit(data, labels, batch_size=32, epochs=5)
コールバックは、学習中のモデルの挙動をカスタマイズするためにモデルに渡されるオブジェクトです。
コールバック関数は自作する、もしくは以下に示すtf.keras.callbacksが提供する組み込み関数を利用できます:
tf.keras.callbacks.ModelCheckpoint:モデルのチェックポイントを一定間隔で保存します。tf.keras.callbacks.LearningRateScheduler:学習率を動的に変更します。tf.keras.callbacks.EarlyStopping:評価パフォーマンスが向上しなくなったら学習を中断させます。tf.keras.callbacks.TensorBoard: モデルの挙動を
TensorBoardで監視します。tf.keras.callbacks.Callbackを使用するには、モデルの fit メソッドにコールバック関数を渡します:
In [ ]:
callbacks = [
# `val_loss` が2エポック経っても改善しなければ学習を中断させます。
tf.keras.callbacks.EarlyStopping(patience=2, monitor='val_loss'),
# TensorBoard用ログを`./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))
In [ ]:
model = tf.keras.Sequential([
layers.Dense(64, activation='relu', input_shape=(32,)),
layers.Dense(10, activation='softmax')])
model.compile(optimizer=tf.train.AdamOptimizer(0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
In [ ]:
# TensorFlow チェックポイント ファイルに重みを保存します。
model.save_weights('./weights/my_model')
# モデルの状態を復元します。
# 復元対象のモデルと保存されていた重みのモデル構造が同一である必要があります。
model.load_weights('./weights/my_model')
デフォルトでは、モデルの重みは TensorFlow チェックポイント 形式で保存されます。 重みはKerasのHDF5形式でも保存できます(マルチバックエンド実装のKerasではHDF5形式がデフォルト):
In [ ]:
# 重みをHDF5形式で保存します。
model.save_weights('my_model.h5', save_format='h5')
# モデルの状態を復元します。
model.load_weights('my_model.h5')
In [ ]:
# JSON形式にモデルをシリアライズします
json_string = model.to_json()
json_string
In [ ]:
import json
import pprint
pprint.pprint(json.loads(json_string))
JSONから(新たに初期化して)モデルを再構築します:
In [ ]:
fresh_model = tf.keras.models.model_from_json(json_string)
YAML形式でモデルを保存するには、
TensorFlowをインポートする前に あらかじめpyyamlをインストールしておく必要があります:
In [ ]:
yaml_string = model.to_yaml()
print(yaml_string)
YAMLからモデルを再構築します:
In [ ]:
fresh_model = tf.keras.models.model_from_yaml(yaml_string)
注意:callメソッド内ににPythonコードでモデル構造を定義するため、派生モデルはシリアライズできません。
In [ ]:
# 層の浅いモデルを構築します。
model = tf.keras.Sequential([
layers.Dense(64, activation='relu', input_shape=(32,)),
layers.Dense(10, activation='softmax')
])
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
model.fit(data, labels, batch_size=32, epochs=5)
# HDF5ファイルにモデル全体を保存します。
model.save('my_model.h5')
# 重みとオプティマイザを含む 全く同一のモデルを再構築します。
model = tf.keras.models.load_model('my_model.h5')
Eagerモード は、オペレーションを即時に評価する命令型のプログラミング環境です。
Kerasでは必要ありませんが、tf.kerasでサポートされておりプログラムを検査しデバッグするのに便利です。
すべてのtf.kerasモデル構築用APIは、Eagerモード互換性があります。
Sequential や Functional APIも使用できますが、
Eagerモードは特に派生モデル の構築や
層のカスタマイズに有益です。
(既存の層の組み合わせでモデルを作成するAPIの代わりに)
順伝播をコードで実装する必要があります。
詳しくは Eagerモード ガイド
(カスタマイズした学習ループとtf.GradientTapeを使ったKerasモデルの適用事例)をご参照ください。
Estimators は分散学習を行うためのAPIです。 実運用に耐えるモデルを巨大なデータセットを用いて分散学習するといった産業利用を目的にすえています。
tf.keras.Modelでtf.estimator APIによる学習を行うには、
tf.keras.estimator.model_to_estimatorを使ってKerasモデルを tf.estimator.Estimatorオブジェクトに変換する必要があります。
KerasモデルからEstimatorsを作成するをご参照ください。
In [ ]:
model = tf.keras.Sequential([layers.Dense(64, activation='relu', input_shape=(32,)),
layers.Dense(10,activation='softmax')])
model.compile(optimizer=tf.train.RMSPropOptimizer(0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
estimator = tf.keras.estimator.model_to_estimator(model)
注意:Estimator input functionsをデバッグしてデータの検査を行うにはEagerモードで実行してください。
tf.kerasモデルはtf.contrib.distribute.DistributionStrategyを使用することでマルチGPU上で実行できます。
このAPIを使えば、既存コードをほとんど改変することなく分散学習へ移行できます。
目下、分散方式としてtf.contrib.distribute.MirroredStrategyのみサポートしています。
MirroredStrategy は、シングルマシン上でAllReduce を使った同期学習によりin-grapnレプリケーションを行います。
KerasでDistributionStrategyを使用する場合は、tf.keras.estimator.model_to_estimatorを使って
tf.keras.Model をtf.estimator.Estimatorに変換し、Estimatorインスタンスを使って分散学習を行います。
以下の例では、シングルマシンのマルチGPUにtf.keras.Modelを分散します。
まず、単純なモデルを定義します:
In [ ]:
model = tf.keras.Sequential()
model.add(layers.Dense(16, activation='relu', input_shape=(10,)))
model.add(layers.Dense(1, activation='sigmoid'))
optimizer = tf.train.GradientDescentOptimizer(0.2)
model.compile(loss='binary_crossentropy', optimizer=optimizer)
model.summary()
入力パイプラインを定義します。input_fn は、複数デバイスにデータを配置するのに使用する tf.data.Dataset を返します。
各デバイスは、入力バッチの一部(デバイス間で均等に分割)を処理します。
In [ ]:
def input_fn():
x = np.random.random((1024, 10))
y = np.random.randint(2, size=(1024, 1))
x = tf.cast(x, tf.float32)
dataset = tf.data.Dataset.from_tensor_slices((x, y))
dataset = dataset.repeat(10)
dataset = dataset.batch(32)
return dataset
次に、 tf.estimator.RunConfigを作成し、 train_distribute 引数にtf.contrib.distribute.MirroredStrategy インスタンスを設定します。MirroredStrategyを作成する際、デバイスの一覧を指定する、もしくは引数でnum_gpus(GPU数)を設定することができます。デフォルトでは、使用可能なすべてのGPUを使用する設定になっています:
In [ ]:
strategy = tf.contrib.distribute.MirroredStrategy()
config = tf.estimator.RunConfig(train_distribute=strategy)
Kerasモデルを tf.estimator.Estimator インスタンスへ変換します。
In [ ]:
keras_estimator = tf.keras.estimator.model_to_estimator(
keras_model=model,
config=config,
model_dir='/tmp/model_dir')
最後に、input_fn と steps引数を指定して Estimator インスタンスを学習します:
In [ ]:
keras_estimator.train(input_fn=input_fn, steps=10)