Keras : Getting Started : Keras FAQ (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 06/17/2018 (2.2.0)
* 本ページは、Keras 本家サイトの – Keras FAQ: Frequently Asked Keras Questions を
動作確認・翻訳した上で適宜、補足説明したものです:
* Keras 本家サイトには日本語訳も用意されていますが、それとは無関係に翻訳したものです。
* サンプルコードの動作確認はしておりますが、適宜、追加改変している場合もあります。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
どのように Keras を引用 (= cite) すべきでしょうか?
もし Keras が貴方の研究に役立つ場合には貴方の出版物で Keras を引用してください。ここに BibTeX エントリ例があります :
@misc{chollet2015keras, title={Keras}, author={Chollet, Fran\c{c}ois and others}, year={2015}, howpublished={\url{https://keras.io}}, }
※ 訳注: citation については必ず 原文 を確認してください。
Keras を GPU 上でどのように実行できますか?
もし TensorFlow か CNTK バックエンド上で実行する場合には、任意の利用可能な GPU が検出されれば貴方のコードは GPU 上で自動的に動作します。
Theano バックエンド上で実行している場合には、次のメソッドの一つが使用できます :
メソッド 1: Theano フラグを使用する。
THEANO_FLAGS=device=gpu,floatX=float32 python my_keras_script.py
名前 ‘gpu’ は貴方のデバイス識別子 (e.g. gpu0, gpu1, etc) に依拠して変更されなければならないかもしれません。
メソッド 2: .theanorc を設定する: 手順
メソッド 3: 貴方のコードの冒頭で theano.config.device, theano.config.floatX を設定する :
import theano theano.config.device = 'gpu' theano.config.floatX = 'float32'
Keras モデルをマルチ GPU 上でどのように実行できますか?
TensorFlow バックエンドを使用してそれを行なうことを推奨します。シングル・モデルをマルチ GPU 上で実行するには 2 つの方法があります : データ並列 と デバイス並列 です。
殆どの場合、貴方が必要なものはまず間違いなくデータ並列です。
データ並列
データ並列は各デバイス上に対象モデルを一度レプリカを作成し、そして入力データの異なる断片を処理するために各レプリカを使用することにあります。Keras は組み込みユティリティ keras.utils.multi_gpu_model を持ち、これは任意のモデルのデータ並列バージョンを生成して、8 GPUs 上まで順線形のスピードアップを獲得することができます。
更なる情報のためには、multi_gpu_model のためのドキュメントを見てください。ここに素早いサンプルがあります :
from keras.utils import multi_gpu_model # `model` を 8 GPUs 上にレプリカを作成する。 # これは貴方のマシンが 8 個の利用可能な GPUs を持つものと仮定しています。 parallel_model = multi_gpu_model(model, gpus=8) parallel_model.compile(loss='categorical_crossentropy', optimizer='rmsprop') # この `fit` 呼び出しは 8 GPUs 上に分散されます。 # バッチサイズは 256 なので、各 GPU は 32 サンプルを処理します。 parallel_model.fit(x, y, epochs=20, batch_size=256)
デバイス並列
デバイス並列は同じモデルの異なる部分を異なるデバイス上で実行することにあります。それは並列アーキテクチャを持つモデルに対して最善に動作するでしょう、e.g. 2 つの分岐を持つモデル。
これは TensorFlow device scope を使用することにより達成できます。ここに簡単なサンプルがあります :
# 2 つの異なるシークエンスを並列にエンコードする共有 LSTM が使用されるモデル。 input_a = keras.Input(shape=(140, 256)) input_b = keras.Input(shape=(140, 256)) shared_lstm = keras.layers.LSTM(64) # 一つの GPU 上で最初のシークエンスを処理する。 with tf.device_scope('/gpu:0'): encoded_a = shared_lstm(tweet_a) # もう一つの GPU 上で次のシークエンスを処理する。 with tf.device_scope('/gpu:1'): encoded_b = shared_lstm(tweet_b) # CPU 上で結果を結合する。 with tf.device_scope('/cpu:0'): merged_vector = keras.layers.concatenate([encoded_a, encoded_b], axis=-1)
「サンプル」「バッチ」「エポック」はどのような意味ですか?
以下は Keras を正しく活用するために知って理解する必要がある幾つかの一般的な定義です :
- サンプル: データセットの 1 要素。
- 例: 1 つの画像は畳み込みネットワークのサンプルです。
- 例: 1 つの音声ファイルは発話認識モデルのためのサンプルです。
- バッチ: N サンプルのセット。バッチのサンプルは独立的に、並列に処理されます。訓練では、バッチはモデルへの一つだけの更新という結果になります。
- バッチは一般に単一入力よりも入力データの分布をより良く近似します。よりバッチが大きいほど、近似もより良くなります ; けれども、バッチは処理するのにより長くかかり一つの更新という結果になることもまた真実です。推論 (評価/予測) のために、メモリ不足になることのない余裕があるだけの十分に大きいバッチサイズを選択することを推奨します (何故ならばより大きなバッチは通常はより高速な評価/予測という結果になるからです)。
- エポック: 任意のカットオフ (分断) で、一般的には “データセット全体に渡る 1 パス” として定義され、訓練を別々の段階に分割するために使用されます、これはロギングと定期的な評価のために有用です。
- Keras モデルの fit メソッドとともに evaluation_data や evaluation_split を使用するとき、総てのエポックの最後に評価が実行されます。
- Keras 内部では、エポックの最後に実行されるように特に設計された callbacks を追加するアビリティがあります。これらの例は学習率の変更とモデル・チェックポイント (セービング) です。
Keras モデルをどのようにセーブできますか?
モデル全体の保存/ロード (アーキテクチャ + 重み + optimizer 状態)
Keras モデルをセーブするために pickle や cPicle を使用することは推奨されません。
Keras モデルを (以下を含む) 単一の HDF5 ファイルにセーブするために model.save(filepath) を使用することができます :
- モデルのアーキテクチャ、モデルを再作成することを可能にします。
- モデルの重み
- 訓練の configuration (損失、optimizer)
- optimizer の状態、貴方が中止したところから正確に訓練を再開することを可能にします。
それからモデルを再インスタンス化するために keras.models.load_model(filepath) を使用できます。load_model はまたセーブされた訓練 configuration を使用してモデルのコンパイルもケアします (モデルが最初にまだ決してコンパイルされていないということがない限りは)。
サンプル :
from keras.models import load_model model.save('my_model.h5') # HDF5 ファイル 'my_model.h5' を作成します。 del model # 既存のモデルを削除します # コンパイルされたモデルを返します。 # 前のものと同一です。 model = load_model('my_model.h5')
モデルのアーキテクチャだけをセーブ/ロードする
モデルのアーキテクチャだけをセーブする必要があり、その重みや訓練 configuration は不要である場合には、次のように行なうことができます :
# JSON としてセーブする json_string = model.to_json() # YAML としてセーブする yaml_string = model.to_yaml()
生成された JSON / YAML ファイルは (人の目で) 可読で必要ならば手動で編集可能です。
それからこのデータから新しいモデルを構築できます :
# JSON からモデル再構築 : from keras.models import model_from_json model = model_from_json(json_string) # YAML からモデル再構築 from keras.models import model_from_yaml model = model_from_yaml(yaml_string)
モデルの重みだけをセーブ/ロードする
モデルの重みをセーブする必要がある場合、下のコードで HDF5 でそれを行なうことができます。
model.save_weights('my_model_weights.h5')
モデルをインスタンス化するためのコードを持つと仮定すれば、セーブした重みを同じアーキテクチャを持つモデルにロードできます :
model.load_weights('my_model_weights.h5')
重みを (共通の幾つかの層を持つ) 異なるアーキテクチャにロードする必要がある場合、例えば再調整や転移学習のために、層の名前で重みをロードできます :
model.load_weights('my_model_weights.h5', by_name=True)
例えば :
""" 元のモデルがこのように見えるものと仮定します : model = Sequential() model.add(Dense(2, input_dim=3, name='dense_1')) model.add(Dense(3, name='dense_2')) ... model.save_weights(fname) """ # 新しいモデル model = Sequential() model.add(Dense(2, input_dim=3, name='dense_1')) # ロードされます model.add(Dense(10, name='new_dense')) # ロードされません # 最初のモデルから重みをロードします ; 最初の層、dense_1 にだけ影響を与えます。 model.load_weights(fname, by_name=True)
セーブされたモデル内でカスタム層 (または他のカスタム・オブジェクト) を扱う
ロードすることを望むモデルがカスタム層か他のカスタム・クラスまたは関数を含む場合、custom_objects 引数を通してそれらをローディング・メカニズムに渡すことができます :
from keras.models import load_model # モデルが "AttentionLayer" クラスのインスタンスを含むものと仮定します。 model = load_model('my_model.h5', custom_objects={'AttentionLayer': AttentionLayer})
代わりに、custom object scope を使用できます :
from keras.utils import CustomObjectScope with CustomObjectScope({'AttentionLayer': AttentionLayer}): model = load_model('my_model.h5')
カスタム・オブジェクト処理は load_model, model_from_json, model_from_yaml と同様に動作します :
from keras.models import model_from_json model = model_from_json(json_string, custom_objects={'AttentionLayer': AttentionLayer})
何故訓練損失はテスト損失よりも遥かに高いのでしょう?
Keras モデルは 2 つのモードを持ちます: 訓練とテストです。Dropout と L1/L2 重み正則化のような正則化メカニズムはテスト時には無効にされます。
更に、訓練損失は訓練データの各バッチに渡る損失の平均です。モデルは徐々に変化しますので、エポックの最初のバッチに渡る損失は一般的に最後のバッチに渡るものよりも高いです。他方、エポックのためのテスト損失はエポックの最後にあるモデルを使用して計算されますので、低い損失という結果になります。
中間層の出力をどのようにして得られますか?
一つの単純な方法は関心のある層を出力する新しい Model を作成することです :
from keras.models import Model model = ... # 元のモデルを作成する。 layer_name = 'my_layer' intermediate_layer_model = Model(inputs=model.input, outputs=model.get_layer(layer_name).output) intermediate_output = intermediate_layer_model.predict(data)
代わりに、ある入力が与えられた場合に特定の層の出力を返すような Keras 関数を構築することもできます、例えば :
from keras import backend as K # with a Sequential model get_3rd_layer_output = K.function([model.layers[0].input], [model.layers[3].output]) layer_output = get_3rd_layer_output([x])[0]
同様に、Theano と TensorFlow 関数を直接構築することもできます。
モデルが訓練とテスト段階で異なる挙動を持つ場合には (e.g. それが Dropout, BatchNormalization, etc. を使用する場合)、 関数に学習段階フラグを渡す必要があることに注意してください :
get_3rd_layer_output = K.function([model.layers[0].input, K.learning_phase()], [model.layers[3].output]) # output in test mode = 0 layer_output = get_3rd_layer_output([x, 0])[0] # output in train mode = 1 layer_output = get_3rd_layer_output([x, 1])[0]
メモリにフィットしないデータセットで Keras をどのように使用できますか?
model.train_on_batch(x, y) と model.test_on_batch(x, y) を使用してバッチ訓練を行なうことができます。models ドキュメント を見てください。
代わりに、訓練データのバッチを yield するジェネレータを書いてメソッド model.fit_generator(data_generator, steps_per_epoch, epochs) を使用することができます。
CIFAR10 サンプル で実際にバッチ訓練を見ることができます。
検証損失がもはや減少しないとき訓練をどのようにして中断できますか?
EarlyStopping callback を使用できます :
from keras.callbacks import EarlyStopping early_stopping = EarlyStopping(monitor='val_loss', patience=2) model.fit(x, y, validation_split=0.2, callbacks=[early_stopping])
callbacks ドキュメント で更に見つかるでしょう。
検証分割 (= validation split) はどのように計算されますか?
model.fit で validation_split 引数を e.g. 0.1 に設定する場合、使用される検証データはデータの最後の 10 % です。それを 0.25 に設定する場合、それはデータの最後の 25 % です、等々。データは検証分割を抜き出す前にシャッフルされないので、検証 (セット) は文字通り渡した入力のサンプルの丁度最後の x % であることに注意してください。
(fit への同じ呼び出し内で) 総てのエポックに対して同じ検証セットが使用されます。
データは訓練中にシャッフルされますか?
はい、model.fit の shuffle 引数が True (これはデフォルトです) に設定される場合、訓練データは各エポックでランダムにシャッフルされます。
検証データは決してシャッフルされません。
各エポックの訓練/検証の損失/精度をどのようにして記録できますか?
model.fit メソッドは History コールバックを返し、これは逐次的な損失と他のメトリクスのリストを含む history 属性を持ちます。
hist = model.fit(x, y, validation_split=0.2) print(hist.history)
Keras 層をどのようにして「凍結 (= freeze)」できるでしょう?
層を「凍結する」とはそれを訓練から除外することを意味します、i.e. その重みは決して更新されません。これはモデルの再調整やテキスト入力のための固定された埋め込みを使用するコンテキストで有用です。
層を非訓練可能に (訓練できないように) 設定するために trainable 引数 (boolean) を層コンストラクタに渡すことができます :
frozen_layer = Dense(32, trainable=False)
更にまた、インスタンス化後に層の trainable プロパティを True か False に設定することができます。これを有効にするためには、trainable プロパティを修正後にモデル上で compile() を呼び出す必要があります。ここにサンプルがあります :
x = Input(shape=(32,)) layer = Dense(32) layer.trainable = False y = layer(x) frozen_model = Model(x, y) # 下のモデルでは、`layer` の重みは訓練中に更新されません。 frozen_model.compile(optimizer='rmsprop', loss='mse') layer.trainable = True trainable_model = Model(x, y) # このモデルでは層の重みは訓練中に更新されます。 # (これはまた上のモデルにも影響を与えます、何故ならばそれは同じ層インスタンスを使用しているからです) trainable_model.compile(optimizer='rmsprop', loss='mse') frozen_model.fit(data, labels) # これは `layer` の重みを更新しません trainable_model.fit(data, labels) # これは `layer` の重みを更新します
ステートフル RNN をどのように使用できますか?
RNN をステートフルにするとは各バッチのサンプルのための状態を次のバッチのサンプルのための初期状態として再利用することを意味します。
ステートフル RNN を使用するとき、従って以下が想定されます :
- 総てのバッチはサンプルの同じ数を持ちます。
- x1 と x2 がサンプルの連続するバッチである場合、総ての i に対して、x2[i] は x1[i] の追跡 (= follow-up) シークエンスです。
RNN のステートフルネス (状態を持つ性質) を使用するためには、以下が必要です :
- 使用しているバッチサイズをモデルの最初の層に batch_size 引数を渡すことにより明示的に指定します。E.g. タイムステップ毎に 16 特徴を持つ 10 タイムステップのシークエンスの 32-サンプル・バッチのために batch_size=32。
- RNN 層 (群) で stateful=True を設定する。
- fit() を呼び出すとき shuffle=False を指定する。
累積された状態をリセットするには :
- モデルの総ての層の状態をリセットするためには model.reset_states() を使用します。
- 特定のステートフル RNN 層の状態をリセットするためには layer.reset_states() を使用します。
例 :
x # これは shape (32, 21, 16) の入力データです。 # それを長さ 10 のシークエンスでモデルに供給します。 model = Sequential() model.add(LSTM(32, input_shape=(10, 16), batch_size=32, stateful=True)) model.add(Dense(16, activation='softmax')) model.compile(optimizer='rmsprop', loss='categorical_crossentropy') # 最初の 10 が与えられた場合に 11th タイムステップを予測するネットワークを訓練します : model.train_on_batch(x[:, :10, :], np.reshape(x[:, 10, :], (32, 16))) # ネットワークの状態は変わりました。follow-up シークエンスを供給できます : model.train_on_batch(x[:, 10:20, :], np.reshape(x[:, 20, :], (32, 16))) # LSTM 層の状態をリセットしましょう : model.reset_states() # この場合それを行なうもう一つの方法です : model.layers[0].reset_states()
メソッド predict, fit, train_on_batch, predict_classes, etc. は総てモデルのステートフル層の状態を更新することに注意してください。これはステートフルな訓練だけでなく、ステートフルな予測を行なうことも可能にします。
Sequential モデルからどのように層を除去できますか?
Sequential モデルの最後に追加された層を .pop() を呼び出すことにより 除去できます :
model = Sequential() model.add(Dense(32, activation='relu', input_dim=784)) model.add(Dense(32, activation='relu')) print(len(model.layers)) # "2" model.pop() print(len(model.layers)) # "1"
Keras で事前訓練されたモデルをどのように使えますか?
コードと事前訓練された重みは次の画像分類モデルについて利用可能です :
- Xception
- VGG16
- VGG19
- ResNet50
- Inception v3
- Inception-ResNet v2
- MobileNet v1
それらはモジュール keras.applications からインポート可能です :
from keras.applications.xception import Xception from keras.applications.vgg16 import VGG16 from keras.applications.vgg19 import VGG19 from keras.applications.resnet50 import ResNet50 from keras.applications.inception_v3 import InceptionV3 from keras.applications.inception_resnet_v2 import InceptionResNetV2 from keras.applications.mobilenet import MobileNet model = VGG16(weights='imagenet', include_top=True)
幾つかの単純な使用例については、Applications モジュールのためのドキュメント を見てください。
そのような事前訓練されたモデルを特徴抽出や再調整のためにどのように使用するかの詳細なサンプルについては、このブログ投稿 を見てください。
VGG16 モデルはまた幾つかの Keras サンプル・スクリプトのための基礎です :
Keras で HDF5 入力をどのように使用できますか?
keras.utils.io_utils からの HDF5Matrix クラスを使用できます。詳細は HDF5Matrix ドキュメント を見てください。
HDF5 データセットを直接使用することもできます :
import h5py with h5py.File('input/file.hdf5', 'r') as f: x_data = f['x_data'] model.predict(x_data)
Keras configuration ファイルはどこにストアされていますか?
総ての Keras データがストアされているデフォルト・ディレクトリは :
$HOME/.keras/
Keras が上のディレクトリを作成できないケースでは (e.g. permission 問題が原因で)、 /tmp/.keras/ がバックアップとして使用されます。
Keras configutation ファイルは $HOME/.keras/keras.json にストアされる JSON ファイルです。デフォルト configuration ファイルはこのように見えます :
{ "image_data_format": "channels_last", "epsilon": 1e-07, "floatx": "float32", "backend": "tensorflow" }
それは次のようなフィールドを含みます :
- 画像処理層とユティリティによりデフォルトとして使用される画像データ・フォーマット (channels_last か channels_first のいずれか)。
- epsilon numerical fuzz factor、これは幾つかの演算でゼロ除算を防ぐために使用されます。
- デフォルト float データ型。
- デフォルト・バックエンド。backend ドキュメント を見てください。
同様に、(get_file() でダウンロードされたような) キャッシュされたデータセットファイルはデフォルトで $HOME/.keras/datasets/ にストアされます。
開発中に Keras を使用して再現可能な結果をどのようにして得ることができますか?
モデルの開発中、パフォーマンスの変化が実際のモデルかデータ変更か、単なる新しいランダム・サンプルの結果が原因なのか決定するために実行から再現可能な結果を得られることは時に有用です。下のコード・スニペットは再現可能な結果をどのように得るかのサンプルを提供します – これは Python 3 環境のための TensorFlow バックエンドに向けて適合しています。
import numpy as np import tensorflow as tf import random as rn # The below is necessary in Python 3.2.3 onwards to # have reproducible behavior for certain hash-based operations. # See these references for further details: # https://docs.python.org/3.4/using/cmdline.html#envvar-PYTHONHASHSEED # https://github.com/keras-team/keras/issues/2280#issuecomment-306959926 import os os.environ['PYTHONHASHSEED'] = '0' # The below is necessary for starting Numpy generated random numbers # in a well-defined initial state. np.random.seed(42) # The below is necessary for starting core Python generated random numbers # in a well-defined state. rn.seed(12345) # Force TensorFlow to use single thread. # Multiple threads are a potential source of # non-reproducible results. # For further details, see: https://stackoverflow.com/questions/42022950/which-seeds-have-to-be-set-where-to-realize-100-reproducibility-of-training-res session_conf = tf.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1) from keras import backend as K # The below tf.set_random_seed() will make random number generation # in the TensorFlow backend have a well-defined initial state. # For further details, see: https://www.tensorflow.org/api_docs/python/tf/set_random_seed tf.set_random_seed(1234) sess = tf.Session(graph=tf.get_default_graph(), config=session_conf) K.set_session(sess) # Rest of code follows ...
Keras でモデルをセーブするために HDF5 または h5py をどのようにインストールできますか?
Keras モデルを HDF5 ファイルとしてセーブするために、e.g. keras.callbacks.ModelCheckpoint を通して、Keras は h5py Python パッケージを使用します。それは Keras の依存性でデフォルトでインストールされるべきです。Debian ベースのディストリビューションでは、追加で libhdf5 もインストールしなければなりません :
sudo apt-get install libhdf5-serial-dev
h5py がインストールされているか不確かであれば、Python シェルをオープンして次を通してモジュールをロードできます :
import h5py
以上