Platform for AI (PAI) 上での TensorFlow に関する一般的な質問と解決策について説明します。内容は、データアクセス、モデルのエクスポート、トラブルシューティングにわたります。
目次
複数の Python ファイルの参照
複数のファイル間で関数を参照するには、すべての Python ファイル (例: test1.py と test2.py) を .tar.gz ファイルにパッケージ化してアップロードします。
各項目は次のとおりです:
-
[Python コードファイル]: .tar.gz パッケージ。
-
[メイン Python ファイル]: メインエントリーファイル。
OSS へのデータアップロード
ディープラーニングのデータは OSS バケットに保存されます。GPU クラスターと同じリージョンにバケットを作成すると、クラシックネットワークを利用でき、トラフィック料金を回避できます。その後、OSS コンソールからフォルダーの作成、データの整理、ファイルのアップロードができます。
API または SDK を使用して OSS にデータをアップロードします (単純アップロード)。OSS は、ossutil や osscmd などのツールも提供しており、ファイルのアップロードとダウンロードが可能です (OSS の開発者ツール)。
アップロードツールには AccessKey ID と AccessKey シークレットが必要です。これらは Alibaba Cloud コンソールで作成または表示できます。
OSS からのデータ読み取り
Python はネイティブでは OSS パスをサポートしていません。Open()、os.path.exist()、Scipy.misc.imread()、numpy.load() などの標準的なファイル操作は、OSS 上で直接実行することはできません。
PAI でデータを読み取るには、次のいずれかの方法を使用します:
-
単一の画像やテキストファイルの読み取りなど、単純な読み取り操作には、
tf.gfile関数を使用します。tf.gfile.Copy(oldpath, newpath, overwrite=False) # ファイルをコピーします。 tf.gfile.DeleteRecursively(dirname) # ディレクトリ内のすべてのファイルを再帰的に削除します。 tf.gfile.Exists(filename) # ファイルが存在するかどうかを確認します。 tf.gfile.FastGFile(name, mode='r') # ファイルをブロックせずに読み取ります。 tf.gfile.GFile(name, mode='r') # ファイルを読み取ります。 tf.gfile.Glob(filename) # フォルダー内のすべてのファイルを一覧表示します。パターンも使用できます。 tf.gfile.IsDirectory(dirname) # dirname がディレクトリであるかどうかを返します。 tf.gfile.ListDirectory(dirname) # dirname 配下のすべてのファイルを一覧表示します。 tf.gfile.MakeDirs(dirname) # dirname 配下にフォルダーを作成します。親ディレクトリが存在しない場合は自動的に作成されます。フォルダーが既に存在し、書き込み可能である場合、操作は成功します。 tf.gfile.MkDir(dirname) # dirname にフォルダーを作成します。 tf.gfile.Remove(filename) # filename を削除します。 tf.gfile.Rename(oldname, newname, overwrite=False) # ファイルの名前を変更します。 tf.gfile.Stat(dirname) # ディレクトリの統計情報を返します。 tf.gfile.Walk(top, inOrder=True) # ディレクトリのファイルツリーを返します。 -
バッチ読み取りには、
tf.gfile.Glob、tf.gfile.FastGFile、tf.WholeFileReader()、tf.train.shuffle_batch()を使用します。まずファイルリストを取得し、次にバッチを作成します。
Designer では、読み取りディレクトリやコードファイルなどのパラメーターを、-XXX の形式で渡します。ここで XXX は文字列です。
import tensorflow as tf
FLAGS = tf.flags.FLAGS
tf.flags.DEFINE_string('buckets', 'oss://{OSS Bucket}/', 'トレーニング画像が保存されているフォルダー')
tf.flags.DEFINE_integer('batch_size', 15, 'バッチサイズ')
files = tf.gfile.Glob(os.path.join(FLAGS.buckets,'*.jpg')) # バケット内のすべての JPG ファイルのパスを一覧表示します。
ファイルサイズに基づいてバッチ読み取り方法を選択します:
-
小さいファイルを読み取るには、
tf.gfile.FastGFile()を使用します。for path in files: file_content = tf.gfile.FastGFile(path, 'rb').read() # ファイルを読み取るには、必ず 'rb' を使用してください。そうしないと、多くの場合にエラーが発生する可能性があります。 image = tf.image.decode_jpeg(file_content, channels=3) # この例では JPG 画像を使用します。 -
大きいファイルを読み取るには、
tf.WholeFileReader()を使用します。reader = tf.WholeFileReader() # リーダーをインスタンス化します。 fileQueue = tf.train.string_input_producer(files) # リーダー用のキューを作成します。 file_name, file_content = reader.read(fileQueue) # キューからファイルを読み取ります。 image_content = tf.image.decode_jpeg(file_content, channels=3) # 読み取り結果を画像にデコードします。 label = XXX # ラベルの処理プロセスは省略されています。 batch = tf.train.shuffle_batch([label, image_content], batch_size=FLAGS.batch_size, num_threads=4, capacity=1000 + 3 * FLAGS.batch_size, min_after_dequeue=1000) sess = tf.Session() # セッションを作成します。 tf.train.start_queue_runners(sess=sess) # キューを開始します。このコマンドを実行しないと、スレッドはブロックされたままになります。 labels, images = sess.run(batch) # 結果を取得します。主要なコード:
-
tf.train.string_input_producer: ファイル名のリストをキューに変換します。tf.train.start_queue_runnersを呼び出して、キュー処理スレッドを開始する必要があります。 -
tf.train.shuffle_batchのパラメーター:-
batch_size: バッチ操作ごとに返されるデータエントリの数。 -
num_threads: データのエンキューに使用されるスレッドの数。通常は 4 を指定します。 -
キャパシティ: キューの最大サイズ。これにより、ランダムシャッフルの範囲が定義されます。たとえば、10,000 エントリのデータセットを、5,000 エントリのバッファサイズでシャッフルする場合、capacityを 5000 に設定します。 -
min_after_dequeue: デキュー後に保持される要素の最小数。これにより、最低限の混合レベルが保証されます。[キャパシティ] を超えることはできません。
-
-
OSS へのデータ書き込み
次のいずれかの方法を使用して、OSS にデータを書き込みます。これらの例では、出力は /model/example.txt に保存されます:
-
tf.gfile.FastGFile()を使用してデータを書き込みます:tf.gfile.FastGFile(FLAGS.checkpointDir + 'example.txt', 'wb').write('hello world') -
tf.gfile.Copy()を使用してローカルファイルを OSS にコピーします:tf.gfile.Copy('./example.txt', FLAGS.checkpointDir + 'example.txt')
実行時に OOM エラーが発生する理由
OOM は、メモリ使用量が 30 GB を超えると発生します。データセット全体をメモリに読み込むのではなく、gfile を使用して OSS からデータをストリーミングしてください。詳細については、「OSS からのデータ読み取り」をご参照ください。
TensorFlow のユースケースの例
楽曲作成: 楽曲作成のサンプルコード。
GPU を 2 つ設定した場合の model_average_iter_interval の目的
model_average_iter_interval を指定しない場合、GPU は標準の Parallel-SGD を実行し、イテレーションごとに勾配の更新を交換します。1 より大きい値に設定すると、代わりに Model Average が使用されます。この場合、model_average_iter_interval イテレーションごとに、両方の GPU 間でモデルパラメーターが平均化されます。
TensorFlow モデルの SavedModel 形式でのエクスポート
SavedModel 形式
EAS の公式ビルド済みプロセッサを使用して TensorFlow モデルをオンラインサービスとしてデプロイするには、TensorFlow が推奨する公式形式である SavedModel 形式にエクスポートします。ディレクトリ構造は以下のとおりです。
assets/
variables/
variables.data-00000-of-00001
variables.index
saved_model.pb|saved_model.pbtxt
各項目は次のとおりです:
-
assets: 予測に必要な補助ファイル (語彙ファイルなど) を保存するオプションのフォルダー。 -
variables:tf.train.Saverによって保存された変数情報を保存します。 -
saved_model.pbまたはsaved_model.pbtxt: トレーニング済みモデルのグラフ構造を含むMetaGraphDefと、予測の入力と出力を指定するSignatureDefを保存します。
SavedModel のエクスポート
SavedModel のエクスポートについては、TensorFlow ガイドの「保存と復元」で詳しく説明されています。単純なモデルの場合は、次の簡単な方法を使用します。
tf.saved_model.simple_save(
session,
"./savedmodel/",
inputs={"image": x}, ## x はモデルの入力変数です。
outputs={"scores": y} ## y はモデルの出力です。
)
オンライン予測をリクエストする際は、モデルの signature_name を指定します。simple_save() でエクスポートされたモデルの場合、デフォルトの signature_name は [serving_default] です。
複雑なモデルの場合は、手動で SavedModel にエクスポートします:
print('Exporting trained model to', export_path)
builder = tf.saved_model.builder.SavedModelBuilder(export_path)
tensor_info_x = tf.saved_model.utils.build_tensor_info(x)
tensor_info_y = tf.saved_model.utils.build_tensor_info(y)
prediction_signature = (
tf.saved_model.signature_def_utils.build_signature_def(
inputs={'images': tensor_info_x},
outputs={'scores': tensor_info_y},
method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME)
)
legacy_init_op = tf.group(tf.tables_initializer(), name='legacy_init_op')
builder.add_meta_graph_and_variables(
sess, [tf.saved_model.tag_constants.SERVING],
signature_def_map={
'predict_images': prediction_signature,
},
legacy_init_op=legacy_init_op
)
builder.save()
print('Done exporting!')
各項目は次のとおりです:
-
export_pathは、モデルがエクスポートされるパスを指定します。 -
prediction_signature: モデルの入力と出力のSignatureDef(SignatureDef)。この例では、signature_nameはpredict_imagesです。 -
builder.add_meta_graph_and_variables: エクスポートパラメーターを指定します。
-
予測用にモデルをエクスポートする場合は、タグを
tf.saved_model.tag_constants.SERVINGに設定します。 -
詳細については、「TensorFlow SavedModel」をご参照ください。
Keras モデルの SavedModel への変換
Keras の model.save() は H5 形式でエクスポートします。オンライン予測のために SavedModel に変換するには、H5 モデルを load_model() で読み込み、再エクスポートします:
import tensorflow as tf
with tf.device("/cpu:0"):
model = tf.keras.models.load_model('./mnist.h5')
tf.saved_model.simple_save(
tf.keras.backend.get_session(),
"./h5_savedmodel/",
inputs={"image": model.input},
outputs={"scores": model.output}
)
チェックポイントの SavedModel への変換
tf.train.Saver() で保存されたチェックポイントモデルは、オンライン予測のために SavedModel に変換する必要があります。saver.restore() でチェックポイントを読み込み、再エクスポートします:
import tensorflow as tf
# 変数定義...
saver = tf.train.Saver()
with tf.Session() as sess:
# saver は v1 を初期化しないため、ここで初期化します。
saver.restore(sess, "./lr_model/model.ckpt")
tensor_info_x = tf.saved_model.utils.build_tensor_info(x)
tensor_info_y = tf.saved_model.utils.build_tensor_info(y)
tf.saved_model.simple_save(
sess,
"./savedmodel/",
inputs={"image": tensor_info_x},
outputs={"scores": tensor_info_y}
)