とりいそぎ{PythonInR}でRからTensorFlowを動かしてみた

　GoogleのTensorFlowがPythonで使えるということだったので、とりいそぎ{PythonInR}で動かしてみました。TensorFlowがどういうものかについては、「参考」の項目に記載の記事などをご参照ください。

　「{PythonInR}って何？」という方のために簡単に説明すると、RからPythonを呼び出すパッケージです。

- [PythonInR: Use Python from Within R](https://cran.fhcrc.org/web/packages/PythonInR/index.html)
- [PythonInR - Makes accessing Python from within R as easy as pie.](https://cran.r-project.org/web/packages/PythonInR/README.html)


　下記のような使い方ができます。

 - [第51回R勉強会＠東京(TokyoR)にてLT発表しました](http://yamano357.hatenadiary.com/entry/2015/10/13/033135)
 - ["An R package for creating and exploring word2vec and other vector models"を試す（+ GloVeと比較）](http://yamano357.hatenadiary.com/entry/2015/11/04/000332)  


# TensorFlowのインストール 
`pip install https://storage.googleapis.com/tensorflow/mac/tensorflow-0.5.0-py2-none-any.whl`

　自分のMac環境だと下記の症状に直面してimportできませんでしたが、記事の通りに実行したところ無事に動作しました。

- [MacでTensorFlowのTypeError: __init__() got an unexpected keyword argument 'syntax'を解決する](http://qiita.com/light14/items/31ee6ff5f7823bab917f)


# {PythonInR}で"Try your first TensorFlow program"を動かす

```r:pyin-first-tensorflow.R
# Try your first TensorFlow program
# https://github.com/tensorflow/tensorflow

> library(PythonInR)
Initialize Python Version 2.7.10 (default, Aug 22 2015, 20:33:39) 
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.1)]

# Python環境に複数混在しているときにインストールした先を直指定
# pip show tensorflow で確認可能
PythonInR::pyImport(import = "os")
PythonInR::pyExec(code = 'sys.path = ["/usr/local/lib/python2.7/site-packages/"] + sys.path')
# PythonInR::pyPrint(objName = "sys.path")

PythonInR::pyImport(import = "numpy")
PythonInR::pyImport(import = "tensorflow", as = "tf")


# Pythonコードを文字列として与えて実行
say_hello <- '
hello = tf.constant("Hello, TensorFlow!")
sess = tf.Session()
print sess.run(hello)
'
> PythonInR::pyExec(code = say_hello)
Hello, TensorFlow!

run_addition <- '
a = tf.constant(10)
b = tf.constant(32)
print sess.run(a+b)
'
> PythonInR::pyExec(code = run_addition)
42

> PythonInR::pyGet(key = "a")
Tensor("Const_1:0", shape=TensorShape([]), dtype=int32)
```
　無事に動作したようです。

# 『初心者用のMNISTチュートリアル』を試してみる
　下記の記事と同じことを、{PythonInR}でやってみます。

 - [TensorFlow 畳み込みニューラルネットワークで手書き認識率99.2%の分類器を構築](http://qiita.com/haminiku/items/36982ae65a770565458d)

```r:pyin-mnist-beginner.R
# 各種Pythonライブラリをimport
PythonInR::pyImport(import = "os")
PythonInR::pyImport(import = "gzip")
PythonInR::pyImport(import = "urllib")
PythonInR::pyImport(import = "numpy")

# 参照先の記事同様にinput_data.pyを用意しておく
# https://github.com/tensorflow/tensorflow/blob/db0b5da485e1d1f23003ee08ed2e191451ee0319/tensorflow/g3doc/tutorials/mnist/input_data.py
PythonInR::pyImport(import = "input_data")

# 上記同様にtensorflowをimport
PythonInR::pyImport(import = "os")
PythonInR::pyExec(code = 'sys.path = ["/usr/local/lib/python2.7/site-packages/"] + sys.path')
PythonInR::pyImport(import = "tensorflow", as = "tf")

# MNISTデータ読み込み
> PythonInR::pyExecp(code = 'mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)')
('Succesfully downloaded', 'train-images-idx3-ubyte.gz', 9912422, 'bytes.')
('Extracting', 'MNIST_data/train-images-idx3-ubyte.gz')
('Succesfully downloaded', 'train-labels-idx1-ubyte.gz', 28881, 'bytes.')
('Extracting', 'MNIST_data/train-labels-idx1-ubyte.gz')
('Succesfully downloaded', 't10k-images-idx3-ubyte.gz', 1648877, 'bytes.')
('Extracting', 'MNIST_data/t10k-images-idx3-ubyte.gz')
('Succesfully downloaded', 't10k-labels-idx1-ubyte.gz', 4542, 'bytes.')
('Extracting', 'MNIST_data/t10k-labels-idx1-ubyte.gz')

# モデル構築
## BEGIN.Python()で囲まれたコードはPythonとしてR上で処理
PythonInR::BEGIN.Python()
x = tf.placeholder("float", [None, 784])
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
y = tf.nn.softmax(tf.matmul(x, W) + b)
y_ = tf.placeholder("float", [None, 10])
cross_entropy = -tf.reduce_sum(y_ * tf.log(y))
END.Python

# xというPythonのオブジェクトが作成されている
> PythonInR::pyGet0(key = "x")
Tensor("Placeholder_2:0", shape=TensorShape([Dimension(None), Dimension(784)]), dtype=float32)

# トレーニングステップの定義
PythonInR::pyExecp(code = 'train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)')

# 初期化
init_session <- '
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)
'
> PythonInR::pyExec(code = init_session)
I tensorflow/core/common_runtime/local_device.cc:25] Local device intra op parallelism threads: 4
I tensorflow/core/common_runtime/local_session.cc:45] Local session inter op parallelism threads: 4

# 学習
PythonInR::pyExec(code = '
for i in range(1000):
  batch_xs, batch_ys = mnist.train.next_batch(100)
  sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
')

# 結果表示
> PythonInR::pyExec(code = '
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
print sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels})
')
0.9137
```

　問題なく動作しているようです。


# Recurrent Neural Networksの例を試す（追記: 2015.11.12）
- MNISTだけでは差別化が欠けそうなので、リカレントニューラルネットワークとLSTMによる言語モデルの例（tensorflow/models/rnn/ptb/ptb_word_lm.py）も動かしてみました。
- [Tutorials and Machine Learning Examples - Recurrent Neural Networks](http://tensorflow.org/tutorials/recurrent/index.md)
- [tensorflow/tensorflow/models/rnn/ptb/](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/models/rnn/ptb)

```r:pyin-rnns-ptb.R
library(PythonInR)

# wget http://www.fit.vutbr.cz/~imikolov/rnnlm/simple-examples.tgz
## 上記のファイルを解凍して、ptb.train.txt, ptb.valid.txt, ptb.test.txtを用意

SET_PARAM <- list(
  # ptb.*.txtを解凍したディレクトリパス
  INPUT_PATH = "./"
)

# ライブラリのimport
PythonInR::pyImport(import = "time")
PythonInR::pyImport(import = "numpy", as = "np")

PythonInR::pyImport(import = "os")
PythonInR::pyExec(code = 'sys.path = ["/usr/local/lib/python2.7/site-packages/"] + sys.path')
PythonInR::pyImport(import = "tensorflow", as = "tf")

PythonInR::pyImport(import = "tensorflow.python.platform")
PythonInR::pyImport(from = "tensorflow.models.rnn", import = "rnn_cell")
PythonInR::pyImport(from = "tensorflow.models.rnn", import = "seq2seq")


# https://github.com/tensorflow/tensorflow/blob/master/tensorflow/models/rnn/ptb/reader.py
## 上記のreader.pyを用意しておく
PythonInR::pyImport(import = "reader")

# https://github.com/tensorflow/tensorflow/blob/master/tensorflow/models/rnn/ptb/ptb_word_lm.py
## 上記からPTBModelとSmall/Medium/Large/のConfigのクラス定義、run_epochとget_configの関数定義だけ使う
## importはPythonInR::pyImportで、定数定義とmainは下記で別途定義する
PythonInR::pyExecfile(filename = "ptb_word_lm_for_R.py")


# 入力データの設定をRからPythonオブジェクトへ
PythonInR::pySet(key = "data_path", value = SET_PARAM$INPUT_PATH)


# ptb_word_lm.py内にあった定数定義を行う
## 今回はmodelをsmallで
PythonInR::BEGIN.Python()
FLAGS = tf.flags.FLAGS
FLAGS.model = "small"
config = get_config()
eval_config = get_config()
eval_config.batch_size = 1
eval_config.num_steps = 1
END.Python
# PythonInR::pyGet(key = "FLAGS.model")

# ファイル読み込み
PythonInR::pyExecp(code = 'train_data, valid_data, test_data, _ = reader.ptb_raw_data(data_path)')


# 学習
run_training <- '
with tf.Graph().as_default(), tf.Session() as session:
  initializer = tf.random_uniform_initializer(-config.init_scale, config.init_scale)
  with tf.variable_scope("model", reuse=None, initializer=initializer):
    m = PTBModel(is_training=True, config=config)
  with tf.variable_scope("model", reuse=True, initializer=initializer):
    mvalid = PTBModel(is_training=False, config=config)
    mtest = PTBModel(is_training=False, config=eval_config)
  tf.initialize_all_variables().run()
  for i in range(config.max_max_epoch):
    lr_decay = config.lr_decay ** max(i - config.max_epoch, 0.0)
    m.assign_lr(session, config.learning_rate * lr_decay)
  
    print("Epoch: %d Learning rate: %.3f" % (i + 1, session.run(m.lr)))
    train_perplexity = run_epoch(session, m, train_data, m.train_op, verbose=True)
    print("Epoch: %d Train Perplexity: %.3f" % (i + 1, train_perplexity))
    valid_perplexity = run_epoch(session, mvalid, valid_data, tf.no_op())
    print("Epoch: %d Valid Perplexity: %.3f" % (i + 1, valid_perplexity))
    
  test_perplexity = run_epoch(session, mtest, test_data, tf.no_op())
  print("Test Perplexity: %.3f" % test_perplexity)
'
> PythonInR::pyExec(code = run_training)
I tensorflow/core/common_runtime/local_device.cc:25] Local device intra op parallelism threads: 4
I tensorflow/core/common_runtime/local_session.cc:45] Local session inter op parallelism threads: 4
Epoch: 1 Learning rate: 1.000
0.004 perplexity: 5281.647 speed: 416 wps
0.104 perplexity: 842.289 speed: 436 wps
0.204 perplexity: 625.980 speed: 436 wps
0.304 perplexity: 505.553 speed: 436 wps
0.404 perplexity: 436.171 speed: 436 wps
0.504 perplexity: 390.876 speed: 436 wps
0.604 perplexity: 352.165 speed: 436 wps
0.703 perplexity: 325.571 speed: 436 wps
0.803 perplexity: 304.489 speed: 436 wps
0.903 perplexity: 284.968 speed: 436 wps
Epoch: 1 Train Perplexity: 270.484
Epoch: 1 Valid Perplexity: 178.798
Epoch: 2 Learning rate: 1.000
0.004 perplexity: 211.812 speed: 435 wps
0.104 perplexity: 151.674 speed: 436 wps
0.204 perplexity: 159.031 speed: 437 wps
0.304 perplexity: 153.895 speed: 437 wps
0.404 perplexity: 150.939 speed: 436 wps
0.504 perplexity: 148.556 speed: 436 wps
0.604 perplexity: 143.708 speed: 436 wps
0.703 perplexity: 141.546 speed: 436 wps
0.803 perplexity: 139.509 speed: 436 wps
0.903 perplexity: 135.853 speed: 436 wps
Epoch: 2 Train Perplexity: 133.796
Epoch: 2 Valid Perplexity: 144.369
Epoch: 3 Learning rate: 1.000
0.004 perplexity: 144.571 speed: 435 wps
0.104 perplexity: 105.449 speed: 436 wps
0.204 perplexity: 114.526 speed: 436 wps
0.304 perplexity: 111.624 speed: 436 wps
0.404 perplexity: 110.695 speed: 436 wps
0.504 perplexity: 109.884 speed: 436 wps
0.604 perplexity: 107.141 speed: 436 wps
0.703 perplexity: 106.491 speed: 436 wps
0.803 perplexity: 105.827 speed: 436 wps
0.903 perplexity: 103.580 speed: 436 wps
Epoch: 3 Train Perplexity: 102.608
Epoch: 3 Valid Perplexity: 133.411
Epoch: 4 Learning rate: 1.000
0.004 perplexity: 116.489 speed: 434 wps
0.104 perplexity: 85.386 speed: 435 wps
0.204 perplexity: 93.969 speed: 436 wps
0.304 perplexity: 91.774 speed: 436 wps
0.404 perplexity: 91.300 speed: 436 wps
0.504 perplexity: 90.858 speed: 436 wps
0.604 perplexity: 88.896 speed: 436 wps
0.703 perplexity: 88.710 speed: 436 wps
0.803 perplexity: 88.441 speed: 436 wps
0.903 perplexity: 86.841 speed: 436 wps
Epoch: 4 Train Perplexity: 86.248
Epoch: 4 Valid Perplexity: 128.786
Epoch: 5 Learning rate: 1.000
0.004 perplexity: 99.743 speed: 434 wps
0.104 perplexity: 73.674 speed: 437 wps
0.204 perplexity: 81.126 speed: 437 wps
0.304 perplexity: 79.424 speed: 437 wps
0.404 perplexity: 79.306 speed: 437 wps
0.504 perplexity: 79.166 speed: 437 wps
0.604 perplexity: 77.693 speed: 437 wps
0.703 perplexity: 77.704 speed: 437 wps
0.803 perplexity: 77.674 speed: 437 wps
0.903 perplexity: 76.398 speed: 436 wps
Epoch: 5 Train Perplexity: 76.075
Epoch: 5 Valid Perplexity: 129.141
Epoch: 6 Learning rate: 0.500
0.004 perplexity: 89.435 speed: 433 wps
0.104 perplexity: 64.475 speed: 437 wps
0.204 perplexity: 69.678 speed: 437 wps
0.304 perplexity: 67.070 speed: 437 wps
0.404 perplexity: 66.096 speed: 437 wps
0.504 perplexity: 65.207 speed: 437 wps
0.604 perplexity: 63.308 speed: 437 wps
0.703 perplexity: 62.653 speed: 437 wps
0.803 perplexity: 61.950 speed: 437 wps
0.903 perplexity: 60.239 speed: 437 wps
Epoch: 6 Train Perplexity: 59.351
Epoch: 6 Valid Perplexity: 121.139
Epoch: 7 Learning rate: 0.250
0.004 perplexity: 73.172 speed: 434 wps
0.104 perplexity: 53.176 speed: 436 wps
0.204 perplexity: 57.739 speed: 437 wps
0.304 perplexity: 55.559 speed: 437 wps
0.404 perplexity: 54.689 speed: 437 wps
0.504 perplexity: 53.844 speed: 436 wps
0.604 perplexity: 52.164 speed: 436 wps
0.703 perplexity: 51.506 speed: 437 wps
0.803 perplexity: 50.789 speed: 437 wps
0.903 perplexity: 49.229 speed: 437 wps
Epoch: 7 Train Perplexity: 48.342
Epoch: 7 Valid Perplexity: 121.124
Epoch: 8 Learning rate: 0.125
0.004 perplexity: 65.315 speed: 434 wps
0.104 perplexity: 47.156 speed: 437 wps
0.204 perplexity: 51.336 speed: 437 wps
0.304 perplexity: 49.347 speed: 437 wps
0.404 perplexity: 48.533 speed: 437 wps
0.504 perplexity: 47.753 speed: 437 wps
0.604 perplexity: 46.210 speed: 437 wps
0.703 perplexity: 45.589 speed: 437 wps
0.803 perplexity: 44.906 speed: 437 wps
0.903 perplexity: 43.472 speed: 437 wps
Epoch: 8 Train Perplexity: 42.625
Epoch: 8 Valid Perplexity: 122.176
Epoch: 9 Learning rate: 0.062
0.004 perplexity: 60.844 speed: 433 wps
0.104 perplexity: 44.074 speed: 436 wps
0.204 perplexity: 48.118 speed: 436 wps
0.304 perplexity: 46.220 speed: 436 wps
0.404 perplexity: 45.445 speed: 437 wps
0.504 perplexity: 44.698 speed: 436 wps
0.604 perplexity: 43.224 speed: 437 wps
0.703 perplexity: 42.619 speed: 437 wps
0.803 perplexity: 41.953 speed: 437 wps
0.903 perplexity: 40.583 speed: 437 wps
Epoch: 9 Train Perplexity: 39.766
Epoch: 9 Valid Perplexity: 122.860
Epoch: 10 Learning rate: 0.031
0.004 perplexity: 58.749 speed: 434 wps
0.104 perplexity: 42.488 speed: 436 wps
0.204 perplexity: 46.469 speed: 437 wps
0.304 perplexity: 44.619 speed: 437 wps
0.404 perplexity: 43.874 speed: 437 wps
0.504 perplexity: 43.140 speed: 437 wps
0.604 perplexity: 41.703 speed: 437 wps
0.703 perplexity: 41.105 speed: 437 wps
0.803 perplexity: 40.445 speed: 437 wps
0.903 perplexity: 39.105 speed: 437 wps
Epoch: 10 Train Perplexity: 38.298
Epoch: 10 Valid Perplexity: 123.096
Epoch: 11 Learning rate: 0.016
0.004 perplexity: 57.550 speed: 435 wps
0.104 perplexity: 41.623 speed: 436 wps
0.204 perplexity: 45.553 speed: 437 wps
0.304 perplexity: 43.723 speed: 437 wps
0.404 perplexity: 42.996 speed: 437 wps
0.504 perplexity: 42.278 speed: 437 wps
0.604 perplexity: 40.870 speed: 437 wps
0.703 perplexity: 40.274 speed: 437 wps
0.803 perplexity: 39.617 speed: 437 wps
0.903 perplexity: 38.294 speed: 437 wps
Epoch: 11 Train Perplexity: 37.492
Epoch: 11 Valid Perplexity: 122.920
Epoch: 12 Learning rate: 0.008
0.004 perplexity: 56.783 speed: 435 wps
0.104 perplexity: 41.115 speed: 437 wps
0.204 perplexity: 45.020 speed: 437 wps
0.304 perplexity: 43.202 speed: 437 wps
0.404 perplexity: 42.484 speed: 437 wps
0.504 perplexity: 41.777 speed: 437 wps
0.604 perplexity: 40.389 speed: 437 wps
0.703 perplexity: 39.797 speed: 437 wps
0.803 perplexity: 39.146 speed: 437 wps
0.903 perplexity: 37.834 speed: 437 wps
Epoch: 12 Train Perplexity: 37.036
Epoch: 12 Valid Perplexity: 122.650
Epoch: 13 Learning rate: 0.004
0.004 perplexity: 56.278 speed: 434 wps
0.104 perplexity: 40.812 speed: 436 wps
0.204 perplexity: 44.704 speed: 436 wps
0.304 perplexity: 42.901 speed: 436 wps
0.404 perplexity: 42.193 speed: 436 wps
0.504 perplexity: 41.494 speed: 437 wps
0.604 perplexity: 40.117 speed: 437 wps
0.703 perplexity: 39.530 speed: 437 wps
0.803 perplexity: 38.883 speed: 437 wps
0.903 perplexity: 37.578 speed: 437 wps
Epoch: 13 Train Perplexity: 36.784
Epoch: 13 Valid Perplexity: 122.449
Test Perplexity: 117.094
```

　今回使用した"small"のモデルでは、テストセットのperplexityが120を下回るくらいになると記載があったので（"large"だと80）、どうやら動作しているようです。


# 追記(2016.01.03)
　RStudio社から{tensorflow}というパッケージが公開され、TensorFlow以外にPythonのライブラリも活用できるので、今後はこちらを使っていくといいと思います。

- [TensorFlow for R](https://rstudio.github.io/tensorflow/)
- [{tensorflow}をirisデータで試してみる](http://qiita.com/yamano357/items/b6f566c9eb6f19538008)


## 実行環境
```r 
> devtools::session_info()
Session info ------------------------------------------------------------------------------------
 setting  value                       
 version  R version 3.2.2 (2015-08-14)
 system   x86_64, darwin13.4.0        
 ui       RStudio (0.99.486)          
 language (EN)                        
 collate  ja_JP.UTF-8                 
 tz       Asia/Tokyo                  

Packages ----------------------------------------------------------------------------------------
 package   * version date       source                        
 curl        0.9     2015-06-19 CRAN (R 3.2.0)                
 devtools    1.8.0   2015-05-09 CRAN (R 3.2.0)                
 digest      0.6.8   2014-12-31 CRAN (R 3.2.0)                
 git2r       0.10.1  2015-05-07 CRAN (R 3.2.0)                
 memoise     0.2.1   2014-04-22 CRAN (R 3.2.0)                
 pack        0.1-1   2015-04-21 local                         
 PythonInR * 0.1-1   2015-09-19 CRAN (R 3.2.0)                
 R6          2.1.1   2015-08-19 CRAN (R 3.2.0)                
 Rcpp        0.12.0  2015-07-26 Github (RcppCore/Rcpp@6ae91cc)
 rversions   1.0.1   2015-06-06 CRAN (R 3.2.0)                
 xml2        0.1.1   2015-06-02 CRAN (R 3.2.0)     
```

## 参考
- [TensorFlow: Google 最新の機械学習ライブラリをオープンソース公開](http://googledevjp.blogspot.jp/2015/11/tensorflow-google.html)
- [Neural Networkをちょっとかじった人のための、はじめてのTensorFlow](http://qiita.com/sergeant-wizard/items/55256ac6d5d8d7c53a5a)
- [TensorFlowのTutrialの解説と機械学習の実験をした。](http://nonbiri-tereka.hatenablog.com/entry/2015/11/10/230414)
- [Googleのtensorflowをちょろっと試してみた](http://chotchy-inc.hatenablog.com/entry/2015/11/10/135224)