TensorFlow – Readerクラスでバッチ処理

参考:
TensorFlow : How To : データを読む
Inputs and Readers
TensorFlowチュートリアル – 畳み込みニューラルネットワーク(翻訳)

tf.train.shuffle_batchというのを使う。シャッフルが不要な時は、tf.train.batchを使う。

tf.train.shuffle_batch

tf.train.shuffle_batch(tensors, batch_size, capacity, min_after_dequeue, num_threads=1, seed=None, enqueue_many=False, shapes=None, allow_smaller_final_batch=False, shared_name=None, name=None)

# min_after_dequeue はバッファ、そこからランダムにサンプリングします、がどのくらい大きいかを定義します
# – 大きければより良いシャッフリング、しかし開始が遅くなりメモリがより多く使用されることを意味します。
# capacity は min_after_dequeue よりも大きくなければなりません。
# そして the amount larger は事前読み込みする最大値を決めます。
# 推奨:
# min_after_dequeue + (num_threads + 小さい安全マージン) * batch_size
min_after_dequeue = 10000
capacity = min_after_dequeue + 3 * batch_size
example_batch, label_batch = tf.train.shuffle_batch(
[example, label], batch_size=batch_size, capacity=capacity,
min_after_dequeue=min_after_dequeue)
return example_batch, label_batch

TensorFlowのcifar10のチュートリアルのコード(cifar10_input.py)に下記のように使われている。

上記コードのmin_after_dequeue(min_queue_examples)は、下記のように取得されている。

上記のNUM_EXAMPLES_PER_EPOCH_FOR_TRAINは下記のように設定されている。

バッチもシャッフルしてくれる。シャッフルするために、事前にデータを何個か読み込んでおいて、その中からシャッフルしてくれる。事前読み込み数がmin_after_dequeueで、これが多いと沢山の中からシャッフルできるからシャッフルされ具合がいい感じになる。でも読み込み数が多いからその分遅くなる。でも途中からは裏で読み込んでおいてくれるので遅くならない。ただメモリ使用量は増える。って感じすか??上記事例だとエポック当たり5万件のデータがある場合、それに0.4をかけた数をmin_after_dequeueにしている。そして推奨値の数式に従って、capacityは、min_after_dequeue + 3 * バッチサイズにしている。

バッチ処理してみる

コードサンプル
下記のfile0.csvとfile1.csvはここで使ったものと同じ内容。

結果

TensorFlow – 学習精度を上げるために画像加工して増やす

参考:Images
上記を見ると色々な加工関数があるんですね。デコードエンコードも色々便利そうなのがあるんですね。

TensorFlowのチュートリアル「Convolutional Neural Networks」で、cifar10の画像を学習精度を上げるために画像を色々加工して増やしています。何をしていて、どうやればいいのか確認します。ソースコードはここです。

Readクラスでファイルから画像・ラベルデータを取り出した後に下記をしています。この5つの関数達を試していこうと思います。

すでに同じことをやってるサイトを発見しました。
参考:画像の水増し方法をTensorFlowのコードから学ぶ

なんか、上記5つの関数のうち最後の1つが参考サイトだと違う。参考サイトだとホワイトニングしている。参考サイトのおかげで答えが分かりましたが、一応自分でも試しておきます。

tf.random_crop

コード

結果

seek設定してないけどランダムになった。seekを明示した場合、seekが同じだと同じ結果になるってことらしい。

tf.image.per_image_standardization

これが参考サイトにない。その代りホワイトニングがなくなっている。
コード

結果は恐ろしい色合いになった。

こんな恐ろしい画像から学習しているんだなー。

チュートリアルの5関数を適用してみる

コード

結果

TensorFlow – 画像ファイルをReaderクラスで読み込む

参考:TensorFlowのReaderクラスを使ってみる

こんな風にしたら単一ファイルを読み込めるらしい。

コード

結果

TensorFlow – Readerクラスでデータを読み込んでみる

参考:TensorFlow : How To : データを読む

ファイルからデータを読む場合の処理の流れ

・ファイルパスのリストを、tf.train.string_input_producer 関数に渡す(shuffle=Trueにしたらepochでファイル名をシャッフルする)
・読み込むデータに合わせてreaderを選択する。
・ファイル名キューをreaderのreadメソッドに渡す。readメソッドは、ファイルとレコード識別キーと、スカラ文字列値を返す。
・スカラ文字列を、サンプルを構成するテンソルに変換するためにデコーダと変換 OPs の一つ(あるいはそれ以上)を利用します。

csvファイルを読んでみる

上記コードの動きを色々なパターンでチェックしてみまっす

ちなみに、csvファイルは、下記です。

file0.csv

file1.csv

下記を試してみます。コードは基本上記と同じですが、exmapleとlabelを3回表示させています。結果は、file0.csvとfile1.csvのどちらかの1~3行目を順番に取得していることが分かりました。ファイルから取り出すのは1行目から順番ですが、取り出すファイル自体は勝手にランダムな感じにしてくれてるっぽいです。

結果(下記のときと、file1.csvの内容の時がランダムに変わる)

epochでファイルが変わるか確認する

tf.train.string_input_producerの引数にshuffle=Trueを渡すと、epochでファイル名をシャッフルすると書いてありますので、それも試してみようと思います。まずは、shuffle=Trueを設定しない場合。

結果
下記のようになりました。file0と1だけだと、シャッフルしてるか分かりづらいですね。。とりあえずこれはシャッフルはしてないです。何回かやってみます。

同じコードをもう一度実行したら下記になりました。これぞまさにシャッフルですね。ということは、デフォルトでshuffle=Trueが設定されているようです。

それでは、shuffle=False設定にしてみます。
コードで変更するのは下記だけです。

結果
何回やっても下記になりました。shffle=Falseにすると、最初に取得するファイルも、tf.train.string_input_producerに渡した順番通りで固定のようです。

何をしたらエラーになるか確認してみる

上記のコードで、csvファイルの1行当たりのカラム数が5より大きい場合はエラーになりました。

カラム数が5より小さくてもエラーになりました。

record_defaultsを下記のように変えたらエラーになりました。record_defaultsの形状をみて、想定しているデータの個数やデータ型を想定しているようです。それと合わないデータが入ってたらエラーを出すようです。

エラー

record_defaultsを下記のように変えたらエラーになりました。shapeのランクが1じゃないといけないらしいです。shapeが(5, 0)になるからダメで、(5, 1)になるようにしないといけないってことかな?

エラー

record_defaultsを下記にしたら、エラーになりました。numpyの配列だとダメっぽいです。

エラー

これだとOKでした。

固定長バイナリデータファイルを読み込む

各レコードがバイトの固定数である、バイナリ・ファイルを読むためには、 tf.decode_raw 演算とともに tf.FixedLengthRecordReader を使用します。decode_raw 演算は文字列から uint8 テンソルに変換します。

例えば、CIFAR-10 データセット は、各レコードがバイトの固定長を使用して表される、ファイルフォーマットを使用します: ラベルのための1 バイト、続いて 3072 バイトの画像データです。ひとたび uint8 テンソルを持てば、標準操作で各部分をスライスし必要に応じて再フォーマットすることができます。CIFAR-10 については、どのように読みデコードするかを tensorflow/models/image/cifar10/cifar10_input.py で見ることができ、このチュートリアル で説明されています。

コードサンプル

結果

これで、cifar10のデータを読み込めました。

TensorFlow – tf.strided_slice関数を調べる

tf.strided_sliceを調べます。TensorFlowのGithubにのってる説明ページはこれです。

tf.strided_slice(input_, begin, end, strides=None, begin_mask=0, end_mask=0, ellipsis_mask=0, new_axis_mask=0, shrink_axis_mask=0, var=None, name=None) {#strided_slice}

実験してみる

コード

結果

とりあえず、inputは元データ、beginは開始位置、endは終了位置、stridesは間隔のようです。以前はstridesを指定しない場合、デフォルトでstridesを1とみなしていたようですが、最近のtensorflowのアップデートで、stridesも明示しないとエラーになるようになったようです。ちなみに、終了位置は普通の配列のスライスと同じで、指定したインデックスのひとつ前までになります。

これだけなら簡単なのですが、他にも色々引数があるし、inputもbeginも多次元配列に対応しているようです。

コード

結果

begin、end、stridesはnumpyのshapeのような感じで入れていくようです。コードだとbeginは[0, 5]ですが、これは1次元目は0から始まり、2次元目は5から始まるということになるようです。

Python3 – cifar10をダウンロードして画像を表示させてみる

参考:
Convolutional Neural Networks
https://github.com/tensorflow/models/tree/master/tutorials/image/cifar10/

上記githubに実際のコードがあります。
Cifar10というのは、10種類のカラー画像が沢山入ってるやつで、機械学習によく使われるようです。場所は下記です。
http://www.cs.toronto.edu/~kriz/cifar.html
Cifar100というのもあるようです。

データは、pythonバージョンとかバイナリバージョンとかありますが、TensorFlowが使ってるのは、バイナリバージョンです。バイナリバージョンの説明として、上記本家サイトに下記のように書いてあります。

The binary version contains the files data_batch_1.bin, data_batch_2.bin, …, data_batch_5.bin, as well as test_batch.bin. Each of these files is formatted as follows:
<1 x label><3072 x pixel>

<1 x label><3072 x pixel>
In other words, the first byte is the label of the first image, which is a number in the range 0-9. The next 3072 bytes are the values of the pixels of the image. The first 1024 bytes are the red channel values, the next 1024 the green, and the final 1024 the blue. The values are stored in row-major order, so the first 32 bytes are the red channel values of the first row of the image.

Each file contains 10000 such 3073-byte “rows” of images, although there is nothing delimiting the rows. Therefore each file should be exactly 30730000 bytes long.

There is another file, called batches.meta.txt. This is an ASCII file that maps numeric labels in the range 0-9 to meaningful class names. It is merely a list of the 10 class names, one per row. The class name on row i corresponds to numeric label i.

ダウンロード&展開

ここにダウンロードのコードをいくつか書きました。ここではTensorFlowのコードサンプルと同じくurllib.request.urlretrieveを使います。

展開された内容

最初の1バッチがラベル、その次からは赤、緑、青の順で1024バイトずつ入ってる。画像の大きさは32 x 32(=1024)。画像は各ファイルに1万枚分ある。
(1024 x 3 + 1) x 10000 = 30,730,000(bytes)

試しに画像を表示させてみる

試しにdata_batch_1.binから1枚分取得して表示させてみます。下記のreshapeとかtransposeで頭がこんがらがったのでここテストして頭を整理しました。

10枚取得してラベルもあわせて表示してみる

コードサンプル

結果

Python3 – PIL.Imageで画像を合体してテキストを書く

コードサンプル

結果

Numpy – 配列の形を変えるテスト

TensorFlowでは頻繁に配列の形を変換しますが、結構混乱して理解するのに時間がかかります。Numpy.reshapeとかNumpy.transposeの動きをシンプルな配列で確認してみます。

これから操作する配列は、下記のようなCifar10の画像データの構造をイメージしてます。
最初の4個は赤。次の4個は緑、最後の4個は青。
最初は上記が一次元の配列に格納されている状態にして、最終的にはこれを下記の並びにしたいです。縦、横、チャンネルの3次元配列にしたいということです。

4個ずつ赤・緑・青があるとういことは、2×2の画像サイズになります。よって、配列のshapeは、[2, 2, 3]になることを想定しております。このshapeになりつつ、配列データの構造に不整合がなければ形の変換が成功したことになります。

コード

結果

Python3 – Clint (コマンドライン入出力を色々できるモジュール)

面白そうだからやってみる。
参考:https://github.com/kennethreitz/clint/tree/master/examples
参考:PythonのコマンドラインツールClintを試す

インストール

文字に色つける

コードサンプル

プログレスバー

コードサンプル

Python3 – ファイルのダウンロード

urllib.request.urlretrieveを使うとできます。本家の説明ページはここです。なんか廃止されるかもしれないとか書いてあるけど。他にはRequestsパッケージを使う方法もあります。

urllib.request.urlretrieveを使う

圧縮ファイルをダウンロードして展開する

ダウンロード中に進捗を表示する

Requestsパッケージを使う

画像ファイルをダウンロードして表示する

コードサンプル

圧縮ファイルをダウンロードして展開する

ダウンロード中に進捗を表示する

TensorFlow – tf.gfile.Exists

tf.gfile.Existsを調べます。

コード例

サンプルコード

hogeディレクトリがない状態で実行すると、hogeディレクトリが作られる。
空のhogeディレクトリがある状態で実行すると、hogeディレクトリが削除されて、また作られる。
適当なファイルやディレクトリを入れたhogeディレクトリがある状態で実行すると、hogeディレクトリが削除されて、また作られる。

なんかただディレクトリあったら消してつくってるだけで、何か特別なファイルがあったらそのファイルだけ消すとかそういう特別なことしてるわけじゃないっぽい。なんでわざわざこれ使うのかな?

Python3 – if __name__ == ‘__main__’:

参考:Python – if __name__ == ‘__main__’: の意味

コマンドラインからスクリプトファイルを指定してPythonインタプリタを起動すると、指定されたファイルは、__main__という名前のモジュールとしてPythonに読み込まれる。実行中スクリプトのモジュールの名前は、__name__という名前の変数に設定されているため、この値を参照して、ファイルがコマンドラインから実行されたのか、それともimport文でインポートされたのかを識別できる。

__name__は、モジュール名で、コマンドラインから実行するとそのファイルのモジュール名は、__main__になる。importすると、そのファイルのモジュール名は、hoge.pyだったらhogeになる。(importするときもimport hoge.pyじゃなくて、import hogeとする)

コードサンプル
test.py

test2.py

実行

結果

TensorFlow – tf.app.flags.FLAGS(ファイル実行時にパラメタを付与できるようにする)

tf.app.flags.FLAGSを使うと、TensorFlowのPythonファイルを実行する際にパラメタを付与できるようになる。

下記のようにすると、パラメタ付与が可能になり、デフォルト値やヘルプ画面の説明文を登録できる。tf.app.flags.DEFINE_stringは、String型用で、他にtf.app.flags.DEFINE_boolean、tf.app.flags.DEFINE_integer等を型に合わせて使う。

コードサンプル (test.py)

ヘルプを表示する

結果

実行例

結果

IEでみるとスクロールバーと画面のコンテンツが重なっている

参考:IE でスクロールバーがコンテンツに重なる問題を解決する

viewportが原因だそうです。今viewportの設定は、となってますが、IE11とかは、device-widthが入ってるとスクロールバーも含めてしまうらしい。CSSに下記のように書けばいいらしい。

おーできた。

TensorFlow – TensorBoard

TensorBoardを使うと、設定したノード間の繋がりや、訓練状況等をグラフで表示できます。

シンプルな使い方

コードサンプル

tf.summary.FileWriter()の第一引数はTensorBoard用ログファイルの保存ディレクトリパスです。FileWriterを使うと、あとはsess.runで何かを実行すると勝手にログに保存されます。

TensorBoardの起動

TensorFlowをPIPでインストールしてない場合は、下記使えないかもしれない。

実行すると、下記のようなのが出てくるので、そこにブラウザでアクセスすると確認できます。

正解率のグラフを表示させてみる

下記コードで、正解率accuracyの推移をTensorBoardで表示させています。

やり方

下記で、accuracyという名前のグラフを、accuracyという変数の値で作成できます。

tf.summary.scalar等を利用した場合、tf.summary.merge_all()という関数を使う必要があります。

sess.run時に、上記のmergedも一緒に実行して、その結果を、下記のようにしてTensorBoardに追加します。

コードサンプル

グループ分けして、Graphを見やすくする

下記のように、with tf.name_scope(‘グループ名’):でくくったものは、表示されるグラフでもくくられます。

コードサンプル

こんな感じで見やすくなります。