TensorFlowが推奨しているTFRecordというデータセットのフォーマットがあります。
TFRecordを使いこなせるようになると、大規模なデータを効率的に学習できるようになることがあります。
本記事では、TFRecordの使い方をマスターできるように読み書きする方法を解説し、実際にQueueRunnerを使った実装をしてみます。
TFRecordを使用する理由
TFRecordの中身はProtocol Bufferというバイナリフォーマットです。一度TFRecordを作成することで、データの生成・加工コストを下げられる場合があります。また、TFRecordの形式を使うことでCloud ML Engine用の入力データ形式として使うこともできます。
TensorFlowで機械学習するとき、学習データセットを読み込むには以下の方法があります。
(1) 事前にメモリに全データをロードする
(2) Pythonコードで少しずつ読み込みながらfeed_dictでグラフに入力する
(3) TFRecordからグラフ上でThreadingとQueues [1] を活用しながら読み込む
(4) Dataset APIを使用する
(1)はデータセットが小さい場合には効果的です。たった一度だけファイルをメモリ上に読み込めば、高速にグラフに入力することができます。しかしながら、データが大きくなったときにメモリが圧迫されると処理速度の低下やメモリアロケーションエラーが発生する場合があります。
(2)もプロトタイプとして簡易的に実装したい場合には何度もTFRecordを作成する手間が省けるので良いアイデアです。しかし、シングルスレッドで動作させている場合にはデータ読み込みと学習を同期的にしてしまう場合があるため、全体の学習時間が長くなってしまう場合があります。また、機械学習モデルを変更したり、チューニングをする際には同じ処理を何度もすることになることがあります。毎回同じようなデータ加工処理を走らせている場合には、TFRecordを作成することを検討しましょう。
TFRecordを使用する場合、(3)や(4)の方法でTensorFlowの計算グラフに入力していくことになります。計算グラフ上ではマルチスレッドのキューが使用されるために、学習とデータセットの読み込み・加工を非同期で行うことができます。
TFRecordの作り方
それでは早速TFRecordを作成していきましょう。今回は、Fashion MNIST [2] を例にTFRecordの作り方を学んでいきましょう。Fashion MNISTは、以下のような28×28の10種類の服画像を分類するデータセットです。
Fashion MNISTのページにリンクが貼ってあるので、data/fashion
ディレクトリを作成して保存します。
こうすることで、MNISTと同じようにTensorFlowからコードを読み込むことができるようになります。
ExampleレコードとSequenceExampleレコード
TFRecordは、tf.train.Example
とtf.train.SequenceExample
を1つのレコードの単位として書き込みます。tf.train.Example
は数値や画像などの固定長のリストを扱います。各レコードの値はtf.train.Feature
で指定します。tf.train.Feature
の使用できるデータ型は以下のとおりです。
- tf.train.Int64List
- tf.train.FloatList
- tf.train.BytesList
以下のように[value]
とリストの中に値を指定します。
tf.train.SequenceExample
は固定長のcontextと可変長のfeature_listsを持つデータ形式となります。テキストや時系列などのシーケンシャルデータを学習する場合にはtf.train.SequenceExample
を使用しましょう。
Fashion MNISTをTFRecord化してみる
Fashion MNISTをTFRecordの形式で保存してみます。以下のようにnumpy配列の場合はtobytes()
メソッドを使用することでリストをBytes形式に変換することができます。
このコードを実行すると、カレントディレクトリにfashion_mnist_train.tfrecord
とfashion_mnist_test.tfrecord
が保存されるはずです。
TFRecordの中身を確認する方法
過去に書き出したTFRecordの中の構造が知りたい場合には、tf.train.Example.FromString
が便利です。
featuresの中にimage
とlabel
とheight
とwidth
のfeatureが入っているということが分かります。
TFRecordの読み込み方
TFRecordは、tf.parse_single_example
を使用して読み込むことができます。BytesList
で書き込んだものは、tf.string
で読み込むことに注意してください。
実際に実装してみる
TFRecordにする前のデータとTFRecordにした場合で実際に実行してみます。Fashion MNISTの場合はそれほどデータ量が多くないので、全データメモリに入ってしまいますが、計算グラフへの入力部分が非同期になるはずです。
TFRecordを使用する
まとめ
今回の例では前処理やデータベースとのIOが発生することもなく、メモリ上にすべて展開できてしまうためにそれほどメリットはありません。
巨大なデータセットでデータのIOがリアルタイムで発生してしまう場合や複数マシンで分散学習する場合などはTFRecordにすることを検討してください。
さらにDataset APIを使用することで簡潔に書くこともできます。以前に紹介しているので、こちらも合わせて参考にしてください。
複雑な前処理も簡単に!TensorFlowのDataset APIの使い方 /tensorflow/2017/07/18/tensorflow-dataset-api.html
参考