Path: blob/master/site/ja/r1/tutorials/load_data/images.ipynb
25118 views
Copyright 2018 The TensorFlow Authors.
tf.dataを使って画像をロードする
Note: これらのドキュメントは私たちTensorFlowコミュニティが翻訳したものです。コミュニティによる 翻訳はベストエフォートであるため、この翻訳が正確であることや英語の公式ドキュメントの 最新の状態を反映したものであることを保証することはできません。 この翻訳の品質を向上させるためのご意見をお持ちの方は、GitHubリポジトリtensorflow/docsにプルリクエストをお送りください。 コミュニティによる翻訳やレビューに参加していただける方は、 [email protected] メーリングリストにご連絡ください。
このチュートリアルでは、'tf.data'を使って画像データセットをロードする簡単な例を示します。
このチュートリアルで使用するデータセットは、クラスごとに別々のディレクトリに別れた形で配布されています。
設定
データセットのダウンロードと検査
画像の取得
訓練を始める前に、ネットワークに認識すべき新しいクラスを教えるために画像のセットが必要です。最初に使うためのクリエイティブ・コモンズでライセンスされた花の画像のアーカイブを作成してあります。
218MBをダウンロードすると、花の画像のコピーが使えるようになっているはずです。
画像の検査
扱っている画像について知るために、画像のいくつかを見てみましょう。
各画像のラベルの決定
ラベルを一覧してみます。
ラベルにインデックスを割り当てます。
ファイルとラベルのインデックスの一覧を作成します。
画像の読み込みと整形
TensorFlowには画像を読み込んで処理するために必要なツールが備わっています。
以下は生のデータです。
画像のテンソルにデコードします。
モデルに合わせてリサイズします。
このあと使用するために、簡単な関数にまとめます。
tf.data.Dataset
の構築
画像のデータセット
tf.data.Dataset
を構築する最も簡単な方法は、from_tensor_slices
メソッドを使うことです。
文字列の配列をスライスすると、文字列のデータセットが出来上がります。
output_shapes
とoutput_types
という2つのフィールドが、データセット中の要素の中身を示しています。この場合には、バイナリ文字列というスカラーのセットです。
preprocess_image
をファイルパスのデータセットにマップすることで、画像を実行時にロードし整形する新しいデータセットを作成します。
(image, label)
のペアのデータセット
同じfrom_tensor_slices
メソッドを使ってラベルのデータセットを作ることができます。
これらのデータセットは同じ順番なので、zipすることで(image, label)
というペアのデータセットができます。
新しいデータセットのshapes
とtypes
は、それぞれのフィールドを示すシェイプと型のタプルです。
注:all_image_labels
やall_image_paths
のような配列がある場合、tf.data.dataset.Dataset.zip
メソッドの代わりとなるのは、配列のペアをスライスすることです。
基本的な訓練手法
このデータセットを使ってモデルの訓練を行うには、データが
よくシャッフルされ
バッチ化され
限りなく繰り返され
バッチが出来るだけ早く利用できる
ことが必要です。
これらの特性はtf.data
APIを使えば簡単に付け加えることができます。
注意すべきことがいくつかあります。
順番が重要です。
.repeat
の前に.shuffle
すると、エポックの境界を越えて要素がシャッフルされます。(他の要素がすべて出現する前に2回出現する要素があるかもしれません).batch
の後に.shuffle
すると、バッチの順番がシャッフルされますが、要素がバッチを越えてシャッフルされることはありません。
完全なシャッフルのため、
buffer_size
をデータセットと同じサイズに設定しています。データセットのサイズ未満の場合、値が大きいほど良くランダム化されますが、より多くのメモリーを使用します。シャッフルバッファがいっぱいになってから要素が取り出されます。そのため、大きな
buffer_size
がDataset
を使い始める際の遅延の原因になります。シャッフルされたデータセットは、シャッフルバッファが完全に空になるまでデータセットが終わりであることを伝えません。
.repeat
によってDataset
が再起動されると、シャッフルバッファが一杯になるまでもう一つの待ち時間が発生します。
最後の問題は、tf.data.Dataset.apply
メソッドを、融合されたtf.data.experimental.shuffle_and_repeat
関数と組み合わせることで対処できます。
データセットをモデルにつなぐ
tf.keras.applications
からMobileNet v2のコピーを取得します。
これを簡単な転移学習のサンプルに使用します。
MobileNetの重みを訓練不可に設定します。
このモデルは、入力が[-1,1]
の範囲に正規化されていることを想定しています。
... This function applies the "Inception" preprocessing which converts the RGB values from [0, 255] to [-1, 1] ...
このため、データをMobileNetモデルに渡す前に、入力を[0,1]
の範囲から[-1,1]
の範囲に変換する必要があります。
MobileNetは画像ごとに6x6
の特徴量の空間を返します。
バッチを1つ渡してみましょう。
MobileNetをラップしたモデルを作り、出力層であるtf.keras.layers.Dense
の前に、tf.keras.layers.GlobalAveragePooling2D
で空間の軸に沿って平均値を求めます。
期待したとおりの形状の出力が得られます。
訓練手法を記述するためにモデルをコンパイルします。
訓練可能な変数は2つ、全結合層のweights
とbias
です。
モデルを訓練します。
普通は、エポックごとの本当のステップ数を指定しますが、ここではデモの目的なので3ステップだけとします。
性能
注:このセクションでは性能の向上に役立ちそうな簡単なトリックをいくつか紹介します。詳しくは、Input Pipeline Performanceを参照してください。
上記の単純なパイプラインは、エポックごとにそれぞれのファイルを一つずつ読み込みます。これは、CPUを使ったローカルでの訓練では問題になりませんが、GPUを使った訓練では十分ではなく、いかなる分散訓練でも使うべきではありません。
調査のため、まず、データセットの性能をチェックする簡単な関数を定義します。
現在のデータセットの性能は次のとおりです。
キャッシュ
tf.data.Dataset.cache
を使うと、エポックを越えて計算結果を簡単にキャッシュできます。特に、データがメモリに収まるときには効果的です。
ここでは、画像が前処理(デコードとリサイズ)された後でキャッシュされます。
メモリキャッシュを使う際の欠点のひとつは、実行の都度キャッシュを再構築しなければならないことです。このため、データセットがスタートするたびに同じだけ起動のための遅延が発生します。
データがメモリに収まらない場合には、キャッシュファイルを使用します。
キャッシュファイルには、キャッシュを再構築することなくデータセットを再起動できるという利点もあります。2回めがどれほど早いか見てみましょう。
TFRecord ファイル
生の画像データ
TFRecordファイルは、バイナリの大きなオブジェクトのシーケンスを保存するための単純なフォーマットです。複数のサンプルを同じファイルに詰め込むことで、TensorFlowは複数のサンプルを一度に読み込むことができます。これは、特にGCSのようなリモートストレージサービスを使用する際の性能にとって重要です。
最初に、生の画像データからTFRecordファイルを構築します。
次に、TFRecordファイルを読み込み、以前定義したpreprocess_image
関数を使って画像のデコード/リフォーマットを行うデータセットを構築します。
これを、前に定義済みのラベルデータセットとzipし、期待通りの(image,label)
のペアを得ます。
これは、cache
バージョンよりも低速です。前処理をキャッシュしていないからです。
シリアライズしたテンソル
前処理をTFRecordファイルに保存するには、前やったように前処理した画像のデータセットを作ります。
.jpeg
文字列のデータセットではなく、これはテンソルのデータセットです。
これをTFRecordファイルにシリアライズするには、まず、テンソルのデータセットを文字列のデータセットに変換します。
前処理をキャッシュしたことにより、データはTFRecordファイルから非常に効率的にロードできます。テンソルを使用する前にデシリアライズすることを忘れないでください。
次にラベルを追加し、以前と同じような標準的な処理を適用します。