TensorFlow 大量の画像から学習するには・・・（未解決問題）→12/18解決

# はじめに
改めて、前回までの自分の投稿を見てみましたが、非常に見難いですねぇ・・・書き方を少しずつ工夫していかなければ。
どうも、ikkiです。先日ロボット展で拝見した[Preferred Networks](https://www.preferred-networks.jp/)さんが[FANUC](http://www.fanuc.co.jp/)さんと共同で開発した”[深層学習でバラ積みロボットの0から学習](https://research.preferred.jp/2015/12/robot_binpick_deep_learning/)”についてのブログが更新されていましたね。というか、前回投稿時にはすでに掲載されていましたが。。。
ワークショップで話を聞いていましたが、このロボットを3ヶ月で作ったと言うんだから驚きです。「普通の人だったら3年はかかっていたでしょうねー(笑)」なんて西川社長はおっしゃっていましたが、私は3年かかってもできる自身が無いですねー

ということで、前置きが長くなってしまいましたが、今回は、[以前の記事](http://qiita.com/ikki8412/items/d50a6200b2d317fe0a68)に引き続き、”Out of GPU Memory”の問題についてです。

# 問題点
以前の記事に対する、ReoAoki様とMATS様の助言からエラーを吐くことなく、画像を学習させて画像認識させるプログラムを作ることはできたのですが、食わせることのできる画像の枚数が少なく、いまいち認識精度がよくありません。
学習させる画像(データセット)を工夫すればいいのかな？とも思うのですが、できればプログラム内で解決させたい。
将来的に言えば、どれだけ大量の画像を食わせてもエラー吐くことなく学習データを作るようにしたい！と考えています。("どれだけ"にも限度はありますが)

# プログラム
現状のプログラムは以下です。今回も[kivantium活動日記 TensorFlowでアニメゆるゆりの制作会社を識別する](http://kivantium.hateblo.jp/entry/2015/11/18/233834)を参考にさせて頂いております。ありがとうございます。

```
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import cv2
import numpy as np
import tensorflow as tf
import tensorflow.python.platform

NUM_CLASSES = 2
IMAGE_SIZE = 28
IMAGE_PIXELS = IMAGE_SIZE*IMAGE_SIZE*3

flags = tf.app.flags
FLAGS = flags.FLAGS
flags.DEFINE_string('save_model', 'models/model.ckpt', 'File name of model data')
flags.DEFINE_string('train', 'training/train_.txt', 'File name of train data')
flags.DEFINE_string('test', 'training/test_.txt', 'File name of test data')
flags.DEFINE_string('train_dir', '/tmp/pict_data', 'Directory to put the training data.')
flags.DEFINE_integer('max_steps', 200, 'Number of steps to run trainer.')
flags.DEFINE_integer('batch_size', 128, 'Batch size'
                     'Must divide evenly into the dataset sizes.')
flags.DEFINE_float('learning_rate', 1e-4, 'Initial learning rate.')

def inference(images_placeholder, keep_prob):
    ####################################################################
    #  予測モデルを作成する関数
    #引数: 
    #  images_placeholder: 画像のplaceholder
    #  keep_prob: dropout率のplaceholder
    #返り値:
    #  y_conv: 各クラスの確率(のようなもの)
    ####################################################################

    # 重みを標準偏差0.1の正規分布で初期化
    def weight_variable(shape):
      initial = tf.truncated_normal(shape, stddev=0.1)
      return tf.Variable(initial)

    # バイアスを標準偏差0.1の正規分布で初期化
    def bias_variable(shape):
      initial = tf.constant(0.1, shape=shape)
      return tf.Variable(initial)

    # 畳み込み層の作成
    def conv2d(x, W):
      return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

    # プーリング層の作成
    def max_pool_2x2(x):
      return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
                            strides=[1, 2, 2, 1], padding='SAME')
    
    # 入力を28x28x3に変形
    x_images = tf.reshape(images_placeholder, [-1, IMAGE_SIZE, IMAGE_SIZE, 3])

    # 畳み込み層1の作成
    with tf.name_scope('conv1') as scope:
        W_conv1 = weight_variable([5, 5, 3, 32])
        b_conv1 = bias_variable([32])
        h_conv1 = tf.nn.relu(conv2d(x_images, W_conv1) + b_conv1)

    # プーリング層1の作成
    with tf.name_scope('pool1') as scope:
        h_pool1 = max_pool_2x2(h_conv1)
    
    # 畳み込み層2の作成
    with tf.name_scope('conv2') as scope:
        W_conv2 = weight_variable([5, 5, 32, 64])
        b_conv2 = bias_variable([64])
        h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)

    # プーリング層2の作成
    with tf.name_scope('pool2') as scope:
        h_pool2 = max_pool_2x2(h_conv2)

    # 全結合層1の作成
    with tf.name_scope('fc1') as scope:
        W_fc1 = weight_variable([7*7*64, 1024])
        b_fc1 = bias_variable([1024])
        h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
        h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
        # dropoutの設定
        h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

    # 全結合層2の作成
    with tf.name_scope('fc2') as scope:
        W_fc2 = weight_variable([1024, NUM_CLASSES])
        b_fc2 = bias_variable([NUM_CLASSES])

    # ソフトマックス関数による正規化
    with tf.name_scope('softmax') as scope:
        y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)

    # 各ラベルの確率のようなものを返す
    return y_conv

def loss(logits, labels):
    ####################################################################
    #  lossを計算する関数
    #引数:
    #  logits: ロジットのtensor, float - [batch_size, NUM_CLASSES]
    #  labels: ラベルのtensor, int32 - [batch_size, NUM_CLASSES]
    #返り値:
    #  cross_entropy: 交差エントロピーのtensor, float
    ####################################################################

    # 交差エントロピーの計算
    cross_entropy = -tf.reduce_sum(labels*tf.log(logits))
    # TensorBoardで表示するよう指定
    tf.scalar_summary("cross_entropy", cross_entropy)
    return cross_entropy

def training(loss, learning_rate):
    ####################################################################
    #  訓練のopを定義する関数
    #引数:
    #  loss: 損失のtensor, loss()の結果
    #  learning_rate: 学習係数
    #返り値:
    #  train_step: 訓練のop
    ####################################################################

    train_step = tf.train.AdamOptimizer(learning_rate).minimize(loss)
    return train_step

def accuracy(logits, labels):
    ####################################################################
    #  正解率(accuracy)を計算する関数
    #引数: 
    #  logits: inference()の結果
    #  labels: ラベルのtensor, int32 - [batch_size, NUM_CLASSES]
    #返り値:
    #  accuracy: 正解率(float)
    ####################################################################
    correct_prediction = tf.equal(tf.argmax(logits, 1), tf.argmax(labels, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
    tf.scalar_summary("accuracy", accuracy)
    return accuracy

if __name__ == '__main__':
    # ファイルを開く
    with open(FLAGS.train, 'r') as f: # train.txt
        train_image = []
        train_label = []
        for line in f:
            line = line.rstrip()
            l = line.split()
            img = cv2.imread(l[0])
            img = cv2.resize(img, (IMAGE_SIZE, IMAGE_SIZE))
            train_image.append(img.flatten().astype(np.float32)/255.0)
            tmp = np.zeros(NUM_CLASSES)
            tmp[int(l[1])] = 1
            train_label.append(tmp)
        train_image = np.asarray(train_image)
        train_label = np.asarray(train_label)
        print len(train_image)

    with open(FLAGS.test, 'r') as f: # test.txt
        test_image = []
        test_label = []
        for line in f:
            line = line.rstrip()
            l = line.split()
            img = cv2.imread(l[0])
            img = cv2.resize(img, (IMAGE_SIZE, IMAGE_SIZE))
            test_image.append(img.flatten().astype(np.float32)/255.0)
            tmp = np.zeros(NUM_CLASSES)
            tmp[int(l[1])] = 1
            test_label.append(tmp)
        test_image = np.asarray(test_image)
        test_label = np.asarray(test_label)
    
    with tf.Graph().as_default():
        images_placeholder = tf.placeholder("float", shape=(None, IMAGE_PIXELS))
        labels_placeholder = tf.placeholder("float", shape=(None, NUM_CLASSES))
        keep_prob = tf.placeholder("float")

        logits = inference(images_placeholder, keep_prob)
        loss_value = loss(logits, labels_placeholder)
        train_op = training(loss_value, FLAGS.learning_rate)
        acc = accuracy(logits, labels_placeholder)

        # 保存の準備
        saver = tf.train.Saver()
        sess = tf.Session()
        sess.run(tf.initialize_all_variables())
        # TensorBoardで表示する値の設定
        summary_op = tf.merge_all_summaries()
        summary_writer = tf.train.SummaryWriter(FLAGS.train_dir, sess.graph_def)
        
        for step in range(FLAGS.max_steps):
            for i in range(len(train_image)/FLAGS.batch_size):
                batch = FLAGS.batch_size*i
                sess.run(train_op, feed_dict={
                  images_placeholder: train_image[batch:batch+FLAGS.batch_size],
                  labels_placeholder: train_label[batch:batch+FLAGS.batch_size],
                  keep_prob: 0.5})

            train_accuracy = sess.run(acc, feed_dict={
                images_placeholder: train_image,
                labels_placeholder: train_label,
                keep_prob: 1.0})
            print "step %d, training accuracy %g"%(step, train_accuracy)

            summary_str = sess.run(summary_op, feed_dict={
                images_placeholder: train_image,
                labels_placeholder: train_label,
                keep_prob: 1.0})
            summary_writer.add_summary(summary_str, step)

    print "test accuracy %g"%sess.run(acc, feed_dict={
        images_placeholder: test_image,
        labels_placeholder: test_label,
        keep_prob: 1.0})

    # 最終的なモデルを保存
    save_path = saver.save(sess, FLAGS.save_model)
```

プログラムの内容としては、
・２クラスの画像をtrain.txtとtest.txtから読み込み学習
・画像のサイズは様々だが、resizeによって28*28の画像にリサイズされている
・学習した結果をmodel.ckptというファイルに出力
GPUには"GeForce GTX TITAN X 12GB"を用いております。

この問題はメモリアロケータの問題でTensorFlowを最新のものに更新すれば解決するという[スレッド](https://github.com/tensorflow/tensorflow/issues/136)も見ましたが、結局解決せず・・・

2万、3万の画像を食わせるにはどうすれば・・・？
引き続き調査を進めていきます。。。

**おそらく解決しました！！**→[TensorFlow 大量の画像から学習するには・・・〜(ほぼ)解決編〜](http://qiita.com/ikki8412/items/6784370f73dc7734372a)