LoginSignup
2
2

More than 5 years have passed since last update.

TensorFlow-Slimを逆にたどっていきながら理解する【データセット編】

Last updated at Posted at 2018-08-16

TensorFlowの便利モジュール「Slim」ですが、使用するデータセットにはお決まりがありますので、まとめておきます。

なお、学習の仕方に関してはこちらを参照してください。

前提情報

TensorFlow-Slimは「tensorflow/contrib/slim」にあります。
そこで、すでに

import tensorflow as tf
import tensorflow.contrib.slim as slim

が行われているものとします。

呼ばれ方

通常は以下のように呼ばれて使用されます。

# 2次元畳み込み
net = slim.conv2d(images, 20, [5,5], scope='conv1')

# 途中省略

# one-hot表現に変換
one_hot_labels = slim.one_hot_encoding(
    labels,
    dataset.num_classes)
# クロスエントロピー(softmax)
slim.losses.softmax_cross_entropy(
    net,
    one_hot_labels)

「images」と「labels」がデータセットの組になります。
それぞれ内容や作り方を見ていきます。

内容

まず「images」ですが、以下のような構造のnumpy配列(float32)になっています。
※画像の場合

(バッチサイズ, 縦, 横, チャンネル)

一方「labels」の方は、以下のような構造のnumpy配列(int64)になっています。

(バッチサイズ)

作り方

バッチ分割

まずバッチサイズの配列にするには、以下の関数を使用します。

images, labels = tf.train.batch(
    [image, label],
    batch_size=batch_size,
    allow_smaller_final_batch=True)

「image」は(縦、横、チャンネル)のnumpy配列、「label」は値になります。
指定したバッチサイズで区切られたデータを作成します。

さらに、「image」と「label」を見ていきます。

「image」と「label」の取得

data_provider = slim.dataset_data_provider.DatasetDataProvider(dataset)

image, label = data_provider.get(['image', 'label'])

「dataset」から、「image」と「label」を取り出しています。
これだけではよくわからないので、「dataset」が何なのか見ていきます。

「dataset」とは

データセットの情報を保持しています。
以下の関数で作られます。

slim.dataset.Dataset(
      data_sources=file_pattern,
      reader=reader,
      decoder=decoder,
      num_samples=_SPLITS_TO_SIZES[split_name],
      num_classes=_NUM_CLASSES,
      items_to_descriptions=_ITEMS_TO_DESCRIPTIONS,
      labels_to_names=labels_to_names)

「data_sources」は読み込むデータセットファイル名になります。
今回は事前に作成したこととします。(詳細に関しては省略)
事前に作成しない場合は、ここで取得した内容と同じものを作成すればOKです。
なお、通常は学習用('train')/評価用('test')/ラベル用(値と文字列の組み合わせ)と3ファイル用意します。

画像ごとに

  • image/encoded :画像データ
  • image/format :画像フォーマット
  • image/class/label :ラベル
  • image/height :高さ
  • image/width :幅

が設定されています。

「reader」と「decoder」は、通常それぞれ「tf.TFRecordReader」「slim.tfexample_decoder.TFExampleDecoder(keys_to_features, items_to_handlers)」になります。

「keys_to_features」には

keys_to_features = {
    'image/encoded': tf.FixedLenFeature((), tf.string, default_value=''),
    'image/format': tf.FixedLenFeature((), tf.string, default_value='raw'),
    'image/class/label': tf.FixedLenFeature(
        [1], tf.int64, default_value=tf.zeros([1], dtype=tf.int64)),
}

といった感じで読み込む内容が定義されており、「items_to_handlers」には、

items_to_handlers = {
    'image': slim.tfexample_decoder.Image(shape=[28, 28, 1], channels=1),
    'label': slim.tfexample_decoder.Tensor('image/class/label', shape=[]),
}

といった感じで、読み込むデータの種類が定義されています。
(ここで「image」と「label」に分けています)

「image/encoded」と「image/format」には、バイナリデータを「tf.train.BytesList()」および「tf.train.Feature()」で変換した値が入っています。
「image/class/label」には、バイナリデータを「tf.train.Int64List()」および「tf.train.Feature()」で変換した値が入っています。

「num_samples」には、画像数を設定します。

_SPLITS_TO_SIZES = {'train': 60000, 'test': 10000}

今回は「train」の方を使用します。

「num_classes」はクラス数になります。
例えばMNISTであれは10種類にクラス分けしますので、10となります。

「items_to_descriptions」は画像データとラベルの説明文を設定します。
例えばこんな感じになります。

_ITEMS_TO_DESCRIPTIONS = {
    'image': 'A [28 x 28 x 1] grayscale image.',
    'label': 'A single integer between 0 and 9',
}

最後に「labels_to_names」ですが、これはラベル用のファイルから読み込んだ、値と文字列の組み合わせになります。

ポイント

この時点ではまだファイルは読み込んでおらず、「slim.learning.train()」等で読み込みます。
一旦ファイルにしておかないやり方だと、そのあたりがうまくいかないので、素直にデータセットを事前に作成して、Slimの関数で読み込むようにしたほうがよいです。

なお、このデータセットの作成/読み込み方法は、すでにお決まりのようになっているので、サンプル等からコピーして、使用するデータに合わせて修正するのがよいかと思います。
ここ

  • model.py [データセット読み込み]
  • datasets/mnist.py [データセット読み込み]
  • datasets/dataset_utils.py [共通]
  • datasets/download_and_convert_mnist.py [データセット作成]

あたりが参考になります。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2