ゲームAI備忘録

ゲームAIに使えそうな知識を備忘録として書き留める

人助けと思って何卒インストールをば! 詰碁/ アルコネ/ 五目並べ

これなら分かる!Deep Learningの学び始め方

まえおき

仕事半分趣味半分として独学でDeep Learningを学び始めて早3ヶ月が経ちました.
CNNの亜種とかを論文片手に構築したりするレベルです.
(だいたいはCNN先生で良いんじゃない?と思ったりしますが,しょうがない...)

ただ,未だにDeep Learningは極力使いたくないというか,勾配ブースティングSVMで問題ないなら使いませんし,機械学習とか使わなくても良い優れたアルゴリズムがあれば,そちらを使うようにしてます.
(保守の問題とかあるので,専門性の高い技術は使わないようにしてます.ヘタレエンジニアです.はい.)

ただ,精度だったり速度だったり諸々に問題があって,どうしても最先端の手法にすがりつきたくなる場合があったりします.(はい.泥沼です)
そういうときの奥の手のひとつとしてDeep Learningがあるのかなーというのが現状の認識だったりします.

おすすめ資料

それはさておき,今思えば最初はここから手をつけとけばよかったなと思う資料について,個人的主観で記載します.

ロジスティック回帰やニューラルネットなど機械学習入門的な内容を分かりやすく記載されていますので,CNNを学び始める前段階として読んでおいたほうが無難な気がします.

http://nnadl-ja.github.io/nnadl_site_ja/
ニューラルネットについて非常に分かりやすく,また何故こういう方法を採用しているのか記載されています.

TensorFlowの内部処理をブラックボックスとして使いたいけど,そうは言ってられなくなった時に重宝しました.
今にしてみれば,ChainerやTensorFlowとか使う前に,自前で一度は作っといたほうが良かったと思ってます.

https://www.tensorflow.org/versions/r0.7/tutorials/index.html
Google謹製のライブラリTensorFlowのチュートリアルです.これでもかってぐらい分かりやすく説明してくださっています.

  • ADAM: A METHOD FOR STOCHASTIC OPTIMIZATION

http://arxiv.org/pdf/1412.6980v8.pdf
Adamの論文です.何の気なしにAdamOptimizerとか使ってるけど,これなんぞ...と思った時に役立ちます.

なんでReLU使ってんの?なんでシグモイドじゃダメなの?って思った時に見つけた記事です.ちょっと幸せになれました.

  • Distinctive Image Features from Scale-Invariant Keypoints

https://www.cs.ubc.ca/~lowe/papers/ijcv04.pdf
SIFTの論文です.なんでプーリングとかやってんの?この人達...とか思った時に何となく役にたった論文です.
コンピュータビジョンは一般教養として知っとかないとダメだったなーと思った記憶があります.

機械学習の大会を開いているサイトです.理論的な話とかじゃなくて,もうちょい泥臭い部分が知りたいのです...とか思った時にForum読んで幸せになってます.

たぶんLSTMの記事で一番わかりやすいです.

片っ端から論文読んでいくと,今どういった方法が主流なのかがわかって幸せになれます.

AlphaGo vs. イ・セドルの第四局の感想

第四局の72手目からAlphaGoが崩れ始めたのは以下の理由だと思う.

AlphaGoもモンテカルロ碁ベースでできているので,下記A),B)のいずれかの手が採択されるようになっていると考えられます.

  • A). 勝率から考えて有望そうな手
  • B). 詰碁や手筋のような正解となる手順は少ないが,正しく読みきれるなら有望な手

B).で実際に読み切るためには,

  • 普通は考えない手は無視して探索領域を狭められるか,
  • 手数が短い

のいづれかの条件を満たす必要があります.今回の第四局のキリは上記のA), B)いづれの条件も満たさなかったので見破れなかったのではないかと考えられます.つまり,

  • ほぼ盤面全体を見ないと解けない広範囲な探索領域から見つける必要があったので,B).で正解を得ることが難しかった.
  • 勝率から考えると正解は1パターンしか存在しないので,A)でコンピュータが考慮することはまずない.

それ以降,コンピュータが無茶な手を打ち始めたのは,
上記の72手目を読みきれず形勢が悪くなり,勝率を上げるための無理手で挽回しようとしたため,初級者のような手を乱発したのだと考えられます.

このように考えると,

  • 右側での助からない黒石が逃げていったのも,
  • 左下の割り込みも,

万一相手がミスってくれたら逆転できるため,つまり,ミスって勝利となる確率の方が通常の手を打って挽回するより逆転しやすいため(上記のA.に相当),ああいった手を打ってしまったのではないかと考えられます.

あと,第二局15手目のノゾキは,将棋でおなじみのフレーム問題が発生しているためなんじゃないかと考えられます.
15手目のノゾキはAlphaGoの権利といった手で,いつでも打つことができるので,
人間だとコウ材や局面の切り替えに使ったりするのが普通と考えられています.

じゃあ,結局いつ打つのかというのを,上記のA).やB).では解決できないので,
AlphaGoは不確定な要素をなるだけ除外するべく,十数手先の盤面の中では最も有望そうな手になるノゾきを打ったのではないかと思う.

そう考えると,コウが対局中現れづらいのもある程度納得いきますし.

今回の対局を見た限りでは,直感的に有望そうといった問題はコンピュータにお株を奪われていくかもしれないが,
直線的だけど深い読みが必要そうといった問題の解決には,まだ何かが必要そうな印象を受けました.

さておき,AlphaGoによって今後様々な定石が登場しそうで楽しみです.

TensorFlow - 画像を加工してみる.

TensorFlowには画像を加工するための様々な関数が用意されています.
CIFAR-10のチュートリアルでも色々と適用しているので画像加工部分のみ切り出してみました.
tensorflow/models/image/cifar10/cifar10_input.py - tensorflow - Git at Google

加えた処理
  • 画像の切り取り(ランダムに適用)
  • 明るさの変更(ランダムに適用)
  • コントラストの変更(ランダムに適用)
  • 白色化
コード
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from sklearn.datasets import load_sample_images
import matplotlib.pyplot as plt
import tensorflow as tf

def main(args):
    original_image = load_sample_images().images[0] / 255.0
    img = tf.placeholder(tf.float32, shape=[427, 640, 3])
    # 画像の切り取り
    height, width = 400, 400
    crop_img = tf.image.random_crop(img, [height, width])
    # 明るさをランダムに変更
    brightness_img = tf.image.random_brightness(img, max_delta=63)
    # コントラストをランダムに変更
    contrast_img = tf.image.random_contrast(img, lower=0.2, upper=1.8)
    # 白色化
    whitening_img = tf.image.per_image_whitening(img)
    with tf.Session() as sess:
        imgs = [original_image] + sess.run([crop_img, brightness_img, contrast_img, whitening_img], feed_dict={img: original_image})
        for i, (image, title) in enumerate(zip(imgs, ["original", "crop", "brightness", "contrast", "whitening"])):
            plt.subplot(231 + i)
            plt.imshow(image)
            plt.title(title)
        plt.show()

if __name__  == "__main__":
    tf.app.run()

結果

f:id:namakemono_srm:20160210094311p:plain

TensorFlow - GPUのちからをかりてみた

TensorFlowでMNISTにCNNを利用してみた際の雑な性能比

スペック 処理速度 終了時間
1 GTX 980 Ti 約13ms/epoch 2分ぐらい
1 GPU (g2.2xlarge) 約25ms/epoch 4分ぐらい
Core i5(Mac Book Air) 約400ms/epoch 終わらない.1時間ぐらい?

だいたいGTX 980 Tiがg2.2xlargeの2倍程度高速で,Macの40倍程度早い模様.
CIFAR-10になると相当g2.2xlargeは遅い印象(現在調査中)

GPUを使ってTensorFlowで遊んでみる.

EC2でGPUを使えるようにするために,以下の設定を行いました.

1. AMIの選択: "Ubuntu Server 14.04 LTS (HVM), SSD Volume Type - ami-9abea4fb"を選択
2. インスタンスタイプの選択: "g2.2xlarge"を選択
3. ストレージの追加: 64GBに増やす.
4. あとは下記URLの方の通りに設定する.(助かりました m(_ _)m)
http://www.sekailab.com/wp/2015/11/18/setup-tensorflow-gpu-ec2/

  • ただし,bazelを0.1.4でインストールする.
  • jdk-v.1.8をインストールしておく必要がある.(bazelでコンパイルするために必要)

http://askubuntu.com/questions/183867/how-do-i-update-oracle-java-7-jdk-and-jre

  • tensorflow-0.5.0-py2-none-any.whlの代わりにtensorflow-0.6.0-py2-none-any.whlを使用する.
$ cd ~/tensorflow/tensorflow/models/image/mnist
$ time python  convolutional.py
...
Step 8500 (epoch 9.89), 25.8 ms
Minibatch loss: 1.601, learning rate: 0.006302
Minibatch error: 0.0%
Validation error: 0.9%
Test error: 0.8%

real	3m44.491s
user	2m46.346s
sys	1m23.404s

Macに比べれば速いけど,維持費や速度を考えるとGPU付きのPCをおとなしく買ったほうが良さそう.

sklearn風にTensorFlowを使えるライブラリskflowを使ってみる.

TensorFlowをsklearn風に使えるライブラリskflowを発見.

GitHub - tensorflow/skflow: Simplified interface for TensorFlow (mimicking Scikit Learn) for Deep Learning

インストール方法

pip install git+git://github.com/tensorflow/skflow.git

サンプル

skflow/examples at master · tensorflow/skflow · GitHub

iris(アヤメ)の線形分類

ロジスティック回帰を用いてアヤメを分類

  • コード
import skflow
from sklearn import datasets, metrics

iris = datasets.load_iris()
classifier = skflow.TensorFlowLinearClassifier(n_classes=len(set(iris.target)))
classifier.fit(iris.data, iris.target)
score = metrics.accuracy_score(iris.target, classifier.predict(iris.data))
print("Accuracy: %f" % score)
  • 実行結果
I tensorflow/core/common_runtime/local_device.cc:40] Local device intra op parallelism threads: 4
I tensorflow/core/common_runtime/direct_session.cc:58] Direct session inter op parallelism threads: 4
Step #1, avg. loss: 5.27594
Step #21, epoch #4, avg. loss: 1.46109
Step #41, epoch #8, avg. loss: 0.80689
Step #61, epoch #12, avg. loss: 0.61384
Step #81, epoch #16, avg. loss: 0.52919
Step #101, epoch #20, avg. loss: 0.46205
Step #121, epoch #24, avg. loss: 0.63972
Step #141, epoch #28, avg. loss: 0.36715
Step #161, epoch #32, avg. loss: 0.48894
Step #181, epoch #36, avg. loss: 0.32878
Accuracy: 0.886667

real	0m3.050s
user	0m2.123s
sys	0m0.554s
bostonの線形回帰

最小二乗誤差を用いてボストンの物件価格を推定.

  • コード
import skflow
from sklearn import datasets, metrics, preprocessing

boston = datasets.load_boston()
X = preprocessing.StandardScaler().fit_transform(boston.data)
regressor = skflow.TensorFlowLinearRegressor()
regressor.fit(X, boston.target)
score = metrics.mean_squared_error(regressor.predict(X), boston.target)
print ("MSE: %f" % score)
  • 実行結果
I tensorflow/core/common_runtime/local_device.cc:40] Local device intra op parallelism threads: 4
I tensorflow/core/common_runtime/direct_session.cc:58] Direct session inter op parallelism threads: 4
Step #1, avg. loss: 477.46436
Step #21, epoch #1, avg. loss: 392.31329
Step #41, epoch #2, avg. loss: 150.05814
Step #61, epoch #3, avg. loss: 33.18234
Step #81, epoch #5, avg. loss: 25.03089
Step #101, epoch #6, avg. loss: 22.11081
Step #121, epoch #7, avg. loss: 26.25769
Step #141, epoch #8, avg. loss: 24.56068
Step #161, epoch #10, avg. loss: 21.69363
Step #181, epoch #11, avg. loss: 23.11506
MSE: 22.851618

real	0m3.734s
user	0m2.203s
sys	0m0.632s
iris(アヤメ)の分類

隠れ層が[10,20,10]となるDNNを用いてアヤメの分類

  • コード
import skflow
from sklearn import datasets, metrics

iris = datasets.load_iris()
classifier = skflow.TensorFlowDNNClassifier(hidden_units=[10, 20, 10], n_classes=len(set(iris.target)))
classifier.fit(iris.data, iris.target)
score = metrics.accuracy_score(iris.target, classifier.predict(iris.data))
print("Accuracy: %f" % score)
  • 実行結果
I tensorflow/core/common_runtime/local_device.cc:40] Local device intra op parallelism threads: 4
I tensorflow/core/common_runtime/direct_session.cc:58] Direct session inter op parallelism threads: 4
Step #1, avg. loss: 1.75397
Step #21, epoch #4, avg. loss: 0.88171
Step #41, epoch #8, avg. loss: 0.71925
Step #61, epoch #12, avg. loss: 0.56106
Step #81, epoch #16, avg. loss: 0.49119
Step #101, epoch #20, avg. loss: 0.42057
Step #121, epoch #24, avg. loss: 0.45917
Step #141, epoch #28, avg. loss: 0.36405
Step #161, epoch #32, avg. loss: 0.40900
Step #181, epoch #36, avg. loss: 0.30453
Accuracy: 0.920000

real	0m5.406s
user	0m2.905s
sys	0m1.039s

TensorFlow - CIFA10のチュートリアルを試してみる

  • 原文

https://www.tensorflow.org/versions/master/tutorials/deep_cnn/index.html#convolutional-neural-networks

  • 翻訳

http://qiita.com/KojiOhki/items/e218f36840df10ae358d

概要

  • Cuda-Convnet(CNN)を構築してCIFAR-10の分類
  • 自分で大規模ニューラルネットを構築するためのノウハウ紹介
  • 学習中のデータを視覚化する方法の紹介
  • GPUを用いた訓練方法の紹介

所感

  • CNNのチュートリアルというよりは大規模なネットワークを構築するためのチュートリアル
  • 画像データの前処理についても書かれており個人的には学ぶこと多数.(多分常識なんだろうなー)
  • チュートリアルを読んで理解するというより,コードを読んでノウハウを学び取る方式みたい.

注意点

実験結果

$ wget https://tensorflow.googlesource.com/tensorflow/+archive/0.6.0/tensorflow/models/image/cifar10.tar.gz
$ tar xzvf cifar10.tar.gz 
$ python cifar10_train.py # 時間がかかるので同ファイルのmax_stepの値を下げたほうが無難かも.
$ python cifar10_eval.py

チュートリアルを実行するだけなら上のコマンドで大丈夫です.(最新版だとcifar10_eval.pyで下記のエラーを吐くのでv0.6.0を利用しています.)

AttributeError: 'ExponentialMovingAverage' object has no attribute 'variables_to_restore'

cifar10_train.pyではモデルの評価をしないので,分類精度を知りたい場合はcifar10_eval.pyを実行する必要があります.
cifar10_train.pyでは反復処理1000回ごとに一度,モデルの全パラメータを保存したcheckpointを生成してくれるので,3000回程度反復させてから精度を調べてみると良いかもしれません.

コード

あとMNISTのチュートリアルのコードを基に,保存処理や視覚化,GPU演算などを取り払ってチュートリアルの訓練部分を書き直してみたのが下記コードとなります..

# cifar10_train.py
import os
import tensorflow as tf
import cPickle
import numpy as np
import cv2
import time

IMAGE_SIZE = 24
NUM_CLASSES = 10

def unpickle(filename):
    with open(filename, 'rb') as fp:
        return cPickle.load(fp)

def maybe_download():
    if not os.path.exists("cifar-10-batches-py"):
        os.system("curl http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz -o cifar-10-python.tar.gz")
        os.system("tar xzvf cifar-10-python.tar.gz")

def shuffle(images, labels):
    perm = np.arange(len(labels))
    np.random.shuffle(perm)
    return np.array(images)[perm], np.array(labels)[perm]

def dense_to_one_hot(labels_dense, num_classes=10):
    num_labels = labels_dense.shape[0]
    index_offset = np.arange(num_labels) * num_classes
    labels_one_hot = np.zeros((num_labels, num_classes))
    labels_one_hot.flat[index_offset + labels_dense.ravel()] = 1
    return labels_one_hot

def crop_to_bounding_box(image, offset_height, offset_width, target_height, target_width):
    return image[offset_width:offset_width+target_width, offset_height:offset_height+target_height]

def random_contrast(image, lower, upper, seed=None):
    contrast_factor = np.random.uniform(lower, upper)
    avg = np.mean(image)
    return (image - avg) * contrast_factor + avg

def random_brightness(image, max_delta, seed=None):
    delta = np.random.randint(-max_delta, max_delta)
    return image - delta

def per_image_whitening(image):
    return (image - np.mean(image)) / np.std(image)

def random_flip_left_right(image):
    if np.random.random() < 0.5:
        image = cv2.flip(image, 1)
    return image

def random_crop(image, size):
    W, H, D = image.shape
    w, h, d = size
    left, top = np.random.randint(W - w + 1), np.random.randint(H - h + 1)
    return image[left:left+w, top:top+h]
  
def distort(images, is_train=True):
    for i, image in enumerate(images):
        image = np.array(image)
        image = image.astype(float)
        if is_train:
            image = random_crop(image, (24, 24, 3))
            image = random_flip_left_right(image)
            image = random_brightness(image, max_delta=63)
            image = random_contrast(image, lower=0.2, upper=1.8)
        else:
            image = crop_to_bounding_box(image, 4, 4, 24, 24)
        images[i] = per_image_whitening(image)
    return images

def load(is_train=True):
    images, labels = [], []
    if is_train:
        for j in range(1, 6):
            cifar10 = unpickle("cifar-10-batches-py/data_batch_%d" % j)
            for i in range(len(cifar10["labels"])):
                image = np.reshape(cifar10["data"][i], (3, 32, 32))
                image = np.transpose(image, (1, 2, 0))
                images.append(image)
                labels.append(cifar10["labels"][i])
    else:
        cifar10 = unpickle("cifar-10-batches-py/test_batch")
        for i in range(len(cifar10["labels"])):
            image = np.reshape(cifar10["data"][i], (3, 32, 32))
            image = np.transpose(image, (1, 2, 0))
            images.append(image)
            labels.append(cifar10["labels"][i])
    images = distort(images, is_train) 
    one_hot_labels = dense_to_one_hot(np.array(labels))    
    return shuffle(images, one_hot_labels)
 
def _variable_on_cpu(name, shape, initializer):
    with tf.device('/cpu:0'):
        var = tf.get_variable(name, shape, initializer=initializer)
    return var

def _variable_with_weight_decay(name, shape, stddev, wd):
    var = _variable_on_cpu(name, shape, tf.truncated_normal_initializer(stddev=stddev))
    if wd is not None:
        weight_decay = tf.mul(tf.nn.l2_loss(var), wd, name='weight_loss')
        tf.add_to_collection('losses', weight_decay)
    return var

def conv2d(x, W):
    return tf.nn.conv2d(x, W, strides=[1,1,1,1], padding='SAME')

def inference(images, keep_prob):
    with tf.variable_scope('conv1') as scope:
        dim1 = 64
        W1 = _variable_with_weight_decay('weights', shape=[5, 5, 3, dim1], stddev=1e-4, wd=0.0)
        b1 = _variable_on_cpu('biases', [dim1], tf.constant_initializer(0.0))
        conv1 = tf.nn.relu(conv2d(images, W1) + b1)
        pool1 = tf.nn.max_pool(conv1, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], padding='SAME', name='pool1')
    h1 = tf.nn.lrn(pool1, 4, bias=1.0, alpha=0.001 / 9.0, beta=0.75, name='norm1')
    with tf.variable_scope('conv2') as scope:
        dim2 = 64
        W2 = _variable_with_weight_decay('weights', shape=[5, 5, dim1, dim2], stddev=1e-4, wd=0.0)
        b2 = _variable_on_cpu('biases', [dim2], tf.constant_initializer(0.1))
        conv2 = tf.nn.relu(conv2d(h1, W2) + b2)
        pool2 = tf.nn.max_pool(conv2, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], padding='SAME', name='pool2')
    h2 = tf.nn.lrn(pool2, 4, bias=1.0, alpha=0.001 / 9.0, beta=0.75, name='norm2')
    with tf.variable_scope('local3') as scope:
        dim3 = 384
        W3 = _variable_with_weight_decay('weights', shape=[IMAGE_SIZE*IMAGE_SIZE*dim2 / 16, dim3], stddev=0.04, wd=0.004)
        b3 = _variable_on_cpu('biases', [dim3], tf.constant_initializer(0.1))
        h3 = tf.nn.relu(tf.matmul(tf.reshape(h2, [-1, IMAGE_SIZE*IMAGE_SIZE*dim2 / 16]), W3) + b3)
    with tf.variable_scope('local4') as scope:
        dim4 = 192
        W4 = _variable_with_weight_decay('weights', shape=[dim3, dim4], stddev=0.04, wd=0.004)
        b4 = _variable_on_cpu('biases', [dim4], tf.constant_initializer(0.1))    
        h4 = tf.nn.relu(tf.matmul(h3, W4) + b4) 
    with tf.variable_scope('softmax_linear') as scope:
        W5 = _variable_with_weight_decay('weights', shape=[dim4, NUM_CLASSES], stddev=1/192.0, wd=0.0) 
        b5 = _variable_on_cpu('biases', [NUM_CLASSES], tf.constant_initializer(0.0))    
        y = tf.nn.softmax(tf.matmul(h4, W5) + b5)
    return y

def loss(labels, logits):
    return -tf.reduce_mean(labels * tf.log(tf.clip_by_value(logits, 1e-10, 1.0)))

def train(total_loss):
    return tf.train.AdamOptimizer(1e-4).minimize(total_loss)

def accuracy_score(labels, logits):
    correct_prediction = tf.equal(tf.argmax(logits, 1), tf.argmax(labels, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float")) 
    return accuracy

def main(argv):
    maybe_download()
    train_images, train_labels = load(is_train=True)
    test_images, test_labels = load(is_train=False)
    max_epoch, batch_size = 200, 50
    with tf.Session() as sess:
        images = tf.placeholder("float", shape=[None, IMAGE_SIZE, IMAGE_SIZE, 3])
        labels = tf.placeholder("float", shape=[None, NUM_CLASSES])
        keep_prob = tf.placeholder("float")
        is_train = tf.placeholder("bool")
        logits = inference(images, keep_prob)
        total_loss = loss(labels, logits)
        if is_train:
            train_op = train(total_loss) 
        accuracy = accuracy_score(labels, logits) 
        sess.run(tf.initialize_all_variables())
        feed_dict={images: test_images, labels: test_labels, keep_prob: 1.0, is_train: False}
        test_logits, test_total_loss, test_acc = sess.run(fetches=[logits, total_loss, accuracy], feed_dict=feed_dict)
        best_test_acc, best_test_total_loss, num_keep = test_acc, test_total_loss, 0
        print "total test loss:%.1f, test accuracy:%.2f" % (best_test_total_loss, best_test_acc)
        for epoch in range(max_epoch):
            train_images, train_labels = load(is_train=True)
            start_time = time.time()
            for i in range(0, len(train_images), batch_size):
                batch_images, batch_labels = train_images[i:i+batch_size], train_labels[i:i+batch_size]
                feed_dict={images: batch_images, labels: batch_labels, keep_prob: 0.5, is_train: True}
                _, train_logits, train_total_loss, train_acc = sess.run(fetches=[train_op, logits, total_loss, accuracy], feed_dict=feed_dict)
            duration = time.time() - start_time
            feed_dict={images: test_images, labels: test_labels, keep_prob: 1.0, is_train: False}
            test_logits, test_total_loss, test_acc = sess.run(fetches=[logits, total_loss, accuracy], feed_dict=feed_dict)
            examples_per_sec = (len(train_images) / duration)
            print "[%d][cifar10]train-loss:%.3f, train-accuracy:%.2f," % (epoch, train_total_loss, 100 * train_acc),
            print "test-loss:%.3f(best: %.3f), test-accuracy:%.2f(best: %.2f)" % (test_total_loss, best_test_total_loss, 100 * test_acc, 100 * best_test_acc),
            print '(%.1f examples/sec)' % examples_per_sec
            if best_test_acc < test_acc: 
                print "[BEST] Acc: %.3f -> %.3f, Loss: %.3f -> %.3f" % (best_test_acc, test_acc, best_test_total_loss, test_total_loss)
                best_test_acc, best_test_total_loss = test_acc, test_total_loss
        
if __name__ == "__main__":
    tf.app.run() 

実行結果

$ time python cifar10_train.py
I tensorflow/stream_executor/dso_loader.cc:105] successfully opened CUDA library libcublas.so locally
I tensorflow/stream_executor/dso_loader.cc:105] successfully opened CUDA library libcudnn.so locally
I tensorflow/stream_executor/dso_loader.cc:105] successfully opened CUDA library libcufft.so locally
I tensorflow/stream_executor/dso_loader.cc:105] successfully opened CUDA library libcuda.so.1 locally
I tensorflow/stream_executor/dso_loader.cc:105] successfully opened CUDA library libcurand.so locally
I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:900] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
I tensorflow/core/common_runtime/gpu/gpu_init.cc:102] Found device 0 with properties: 
name: GeForce GTX TITAN X
major: 5 minor: 2 memoryClockRate (GHz) 1.076
...
total test loss:0.2, test accuracy:0.10
[0][cifar10]train-loss:0.177, train-accuracy:34.00, test-loss:0.160(best: 0.230), test-accuracy:40.74(best: 10.00) (563.9 examples/sec)
[BEST] Acc: 0.100 -> 0.407, Loss: 0.230 -> 0.160
[1][cifar10]train-loss:0.152, train-accuracy:56.00, test-loss:0.151(best: 0.160), test-accuracy:44.96(best: 40.74) (545.4 examples/sec)
[BEST] Acc: 0.407 -> 0.450, Loss: 0.160 -> 0.151
[2][cifar10]train-loss:0.162, train-accuracy:40.00, test-loss:0.137(best: 0.151), test-accuracy:51.04(best: 44.96) (552.1 examples/sec)
[BEST] Acc: 0.450 -> 0.510, Loss: 0.151 -> 0.137
[3][cifar10]train-loss:0.121, train-accuracy:62.00, test-loss:0.128(best: 0.137), test-accuracy:54.03(best: 51.04) (549.5 examples/sec)
[BEST] Acc: 0.510 -> 0.540, Loss: 0.137 -> 0.128
...