TensorFlowをWindowsで出来るだけ手軽に使ってみる

人気のGoogle謹製機械学習フレームワークであるTensorFlowは、Linux版とMacOS版しかリリースされていません。話題のディープラーニングなどに興味があるもののWindows版がリリースされていないため手が出し辛かった方もいるでしょう。

そんななか、2016年8月のWindows 10 Anniversary UpdateでWindows10上にUbuntu(Bash)を直接インストールすることが可能になりました。そこでこのBash on Ubuntu on Windowsを利用して手軽にTensorFlowを使うための手順をまとめました。

## Bash on Ubuntu on WindowsでTensorFlowを利用する長所と短所

### 長所
・仮想環境の導入が不要
・Windowsのエディタでソースコードの編集を行う際、ファイル共有設定が不要

Linuxっぽさをそれほど感じずに済みます。

### 短所
・Windows10のみ対応 (Windows7/8は不可)
・GPUが使えない (相対的に処理性能が低い)

TensorFlowに含まれるチュートリアルやサンプルは比較的演算負荷の低いものが多いので「使ってみる」レベルならGPUは不要です。

## 環境前提

・Windows10 64bit版 (TensorFlowは64bit環境専用)

## 作業概要
1. Windows Subsystem for Linuxの有効化とBash on Ubuntu on Windowsの導入
2. python実行環境の導入
3. TensorFlowの導入
4. TensorFlow稼働確認
5. Windows環境でのソースコード編集
6. Google謹製サンプルソースコードの実行 (for Beginner)
7. Google謹製サンプルソースコードの実行 (for Expert)

## 1. Windows Subsystem for Linuxの有効化とBash on Ubuntu on Windowsの導入

こちらは[Arunekoさん](http://qiita.com/Aruneko)の記事[Bash on Ubuntu on Windowsをインストールしてみよう！](http://qiita.com/Aruneko/items/c79810b0b015bebf30bb)の手順をそのまま利用させて頂きましょう。

**上記の記事に従い「諸注意」の項まで作業を行って下さい。**

## 2.python実行環境の導入

TensorFlowを実行するためにPythonインタプリタが必要となります。
Python本体はBash on Ubuntu on Windowsに含まれていますが、周辺パッケージやツールが不足しています。

そのため**Bash on Ubuntu on Windows**(Windowsのコマンドプロンプトではない)を起動し、下記のコマンドを実行して周辺パッケージを導入します。

`$ sudo apt-get install python-pip python-dev`

## 3.TensorFlowの導入

Python実行環境の準備が整ったところで下記のコマンドを実行し、TensorFlowの導入を行います。

`$ sudo pip install --upgrade https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.10.0-cp27-none-linux_x86_64.whl`

インストール中にgccより大量のWarningが出力されますが全て無視して下さい。

尚、上記URLは2016/09/19現在の最新版である、TensorFlow r0.10用となっているため、後日r0.11などがリリースされた場合には、[TensorFlow公式サイト](https://www.tensorflow.org/)より新しいダウンロードURLを確認して下さい。

## 4.TensorFlow稼働確認

Pythonを起動しTensorFlow用の簡単なスクリプトを実行してみましょう。

```console:Python起動
$ python
Python 2.7.6 (default, Jun 22 2015, 17:58:13)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
```

```console:テストスクリプト
>>> import tensorflow as tf
>>> a = tf.constant(1)
>>> b = tf.constant(2)
>>> c = a + b
>>> tf.Session().run(c)
3
```

コンソールに3と出力されればTensorFlowは正常に稼働しています。
pythonインタプリタを終了するにはCtrl+Dを押下して下さい。

## 5.Windows環境でのソースコード編集

Bash on Ubuntu on Windows環境には標準でvimやnanoなどのテキストエディタが導入されています。
しかし、Windowsのテキストエディタを使いたいと思う方もいらっしゃるでしょう。

Windows環境とBash on Ubuntu on Windowsは相互にファイルの読み書きが可能です。

**(例1) Bash on Ubuntu on WindowsからWindowsのファイルシステムをアクセスする**
/mnt/c/Windows/ → C:\Windows\ 

**(例2) WindowsからBash on Ubuntu on Windowsのファイルシステムをアクセスする**
C:\Users\tensorflow\AppData\Local\lxss\home\testuser → \home\testuser

但し、lxssディレクトリはWindowsのエクスプローラなどから参照すると「保護されたオペレーティングシステムファイル」に該当するためディフォルトでは表示されません。

**(注)**
上記(例2)のケースでBash on Ubuntu on Windows側のファイルシステムにあるファイルをWindowsから更新すると、Bash on Ubuntu on Windowsからファイルが見えなかったり、一定時間後に更新内容が消える(戻る)ような現象がありました。(仕様?)

前述の通り「保護されたオペレーティングシステムファイル」であることから、Bash on Ubuntu on Windows側のファイルシステムはWindowsからアクセスするべきではないのかもしれません。

**従って(例1)のようにWindows側ファイルシステムをBash on Ubuntu on Windowsからアクセスする方式の方が安全なようです。**

## 6.Google謹製サンプルソースコードの実行 (for Beginner)

「機械学習界のHello, World!」とも呼ばれる[ビギナー向け](https://www.tensorflow.org/versions/r0.10/tutorials/mnist/beginners/index.html#mnist-for-ml-beginners)MNIST手書き数字認識問題のサンプルスクリプトを実行してみます。

処理の概要としては60,000件の手書き数字データ(画像)を自動でダウンロードし、うち55,000件を用いて学習を実施。その学習結果を使用して、残りの5,000件に書かれた数字の認識率を測定するものです。入門者向けのチュートリアルなのでシンプルなアルゴリズムが使われており、ソースコードはコメントと空行を除くと25行程度に収まります。

githubの[TensorFlowリポジトリ](https://github.com/tensorflow/tensorflow)より最もシンプルなチュートリアルである[mnist_softmap.py](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/tutorials/mnist/mnist_softmax.py)をダウンロードしてpythonインタプリタにて実行します。

```python:mnist_softmax.py
# Copyright 2015 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================

"""A very simple MNIST classifier.

See extensive documentation at
http://tensorflow.org/tutorials/mnist/beginners/index.md
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

# Import data
from tensorflow.examples.tutorials.mnist import input_data

import tensorflow as tf

flags = tf.app.flags
FLAGS = flags.FLAGS
flags.DEFINE_string('data_dir', '/tmp/data/', 'Directory for storing data')

mnist = input_data.read_data_sets(FLAGS.data_dir, one_hot=True)

sess = tf.InteractiveSession()

# Create the model
x = tf.placeholder(tf.float32, [None, 784])
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
y = tf.nn.softmax(tf.matmul(x, W) + b)

# Define loss and optimizer
y_ = tf.placeholder(tf.float32, [None, 10])
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

# Train
tf.initialize_all_variables().run()
for i in range(1000):
  batch_xs, batch_ys = mnist.train.next_batch(100)
  train_step.run({x: batch_xs, y_: batch_ys})

# Test trained model
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print(accuracy.eval({x: mnist.test.images, y_: mnist.test.labels}))
```

ここではC:\TensorFlow\mnist_softmax.pyとして保存しました。

```console:Pythonインタプリタでの実行
$ python mnist.py
(テストデータダウンロードのため暫く待ち状態)
Successfully downloaded train-images-idx3-ubyte.gz 9912422 bytes.
Extracting /tmp/data/train-images-idx3-ubyte.gz
Successfully downloaded train-labels-idx1-ubyte.gz 28881 bytes.
Extracting /tmp/data/train-labels-idx1-ubyte.gz
Successfully downloaded t10k-images-idx3-ubyte.gz 1648877 bytes.
Extracting /tmp/data/t10k-images-idx3-ubyte.gz
Successfully downloaded t10k-labels-idx1-ubyte.gz 4542 bytes.
Extracting /tmp/data/t10k-labels-idx1-ubyte.gz
0.9189

```
初回起動時のみテストデータをダウンロードするため数分間の待ち時間が生じますが、2回目以降は一般的なPCであれば数秒で処理が終了するはずです。

最後に出力されている0.9189は認識精度が91.89%であることを示していますが、サンプルスクリプトを改良することで認識率を向上させることが可能です。

尚、55,000件の学習用データと5,000件の検証用データに分割するために乱数が用いられているため、認識精度は実行するたびに僅かに変化します。

## 7.Google謹製サンプルソースコードの実行 (for Expert)

次にディープラーニングと畳み込みニューラルネットワークを用いた[エキスパート向け](https://www.tensorflow.org/versions/r0.10/tutorials/mnist/pros/index.html#deep-mnist-for-experts)MNIST手書き数字認識問題のサンプルスクリプトを実行してみます。

ソースコードはgithubにもありますが、先程の作業で導入したTensorFlow本体にも添付されているため、そちらのソースコードをWindowsファイルシステムにコピーして利用します。

```console:pythonスクリプトのコピー
$ cp /usr/local/lib/python2.7/dist-packages/tensorflow/models/image/mnist/convolutional.py (Windowsファイルシステム内のディレクトリ) # C:/TensorFlow　など
```

Windowsファイルシステム内にコピーしたpythonスクリプトを先程と同じ要領で実行します。

```console:pythonスクリプト実行
$ cd (コピー先ディレクトリ)
$ python convolutional.py
(テストデータダウンロードのため暫く待ち状態)
Successfully downloaded train-images-idx3-ubyte.gz 9912422 bytes.
Successfully downloaded train-labels-idx1-ubyte.gz 28881 bytes.
Successfully downloaded t10k-images-idx3-ubyte.gz 1648877 bytes.
Successfully downloaded t10k-labels-idx1-ubyte.gz 4542 bytes.
Extracting data/train-images-idx3-ubyte.gz
Extracting data/train-labels-idx1-ubyte.gz
Extracting data/t10k-images-idx3-ubyte.gz
Extracting data/t10k-labels-idx1-ubyte.gz
Initialized!
Step 0 (epoch 0.00), 3.1 ms
Minibatch loss: 12.054, learning rate: 0.010000
Minibatch error: 90.6%
Validation error: 84.6%
Step 100 (epoch 0.12), 185.8 ms
Minibatch loss: 3.287, learning rate: 0.010000
Minibatch error: 6.2%
Validation error: 7.0%

(中略)

Step 8400 (epoch 9.77), 186.0 ms
Minibatch loss: 1.596, learning rate: 0.006302
Minibatch error: 0.0%
Validation error: 0.7%
Step 8500 (epoch 9.89), 184.3 ms
Minibatch loss: 1.603, learning rate: 0.006302
Minibatch error: 0.0%
Validation error: 0.9%
Test error: 0.8%
```

こちらも初回実行時のみテストデータのダウンロードを行うため、暫くの間は何も表示されないことがあります。

私が利用した環境(Intel Core i7-4790k)では初回のダウンロード時間を除き、約26分で計算処理が終了しました。

また、最後に出力されているTest error:は判定のエラー率です。
つまり99.2%の確率で手書きの数字を認識したことになります。

Beginner編では約91.9%でしたので大幅に認識率が向上しています。

## まとめ

今回導入したTensorFlowはBash on Ubuntu on Windows用ではなく本物のUbuntu用になります。
そのためファイルシステム関連を中心に互換性の問題がありそうです。
しかし、機械学習は計算処理が中心ですので大きな問題にはならなそうです。

GPUやPython用の統合開発環境が利用出来ないところは残念ですが、TensorFlowについて簡単に学ぶ程度であればBash on Ubuntu on Windowsも一つの選択肢になりそうです。