INPUTしたらOUTPUT!

忘れっぽいんでメモっとく

AWSのGPUインスタンス上のDockerコンテナでTensorFlow for Rを試す

TensorFlow for RがRStudioからリリースされたので早速試してみた。環境構築が面倒になってきたのでEC2上にDocker環境を構築し、tensorflow+rstudioコンテナを作ったので手順をメモしとく。


項目 設定
リージョン オレゴン
Amazon マシンイメージ CentOS 7 (x86_64) - with Updates HVM
インスタンスタイプ g2.2xlarge
ストレージの追加 EBS Cold HDD (sc1) 500GB
CUDA 7.5

事前にCUDAのインストール、nouveauの無効化はしておくこと。


Docker, nvidia-dockerのインストール

ホストとなるEC2にInstallation on CentOSに従ってインストールする。

# yumのリポジトリにDockerを追加
$ sudo tee /etc/yum.repos.d/docker.repo <<-'EOF'
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/main/centos/7/
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg
EOF

# Dockerのインストール
$ sudo yum install -y docker-engine

# centosユーザーをdockerグループに追加
sudo usermod -aG docker centos


Dockerイメージ&コンテナの保存先をControl and configure Docker with systemdを参考にして変更する

$ sudo mkdir /etc/systemd/system/docker.service.d
$ sudo touch /etc/systemd/system/docker.service.d/docker.conf 
$ sudo vi /etc/systemd/system/docker.service.d/docker.conf

CentOS7でDockerのイメージ・コンテナの保存先を変更する設定


nvidia-dockerのインストール

Home · NVIDIA/nvidia-docker Wiki · GitHubに従ってnvidia-dockerをインストールする。

$ wget -P /tmp https://github.com/NVIDIA/nvidia-docker/releases/download/v1.0.0-rc.3/nvidia-docker-1.0.0.rc.3-1.x86_64.rpm
$ sudo rpm -i /tmp/nvidia-docker*.rpm && rm /tmp/nvidia-docker*.rpm


Dockerサービスを起動する

$ sudo systemctl status nvidia-docker


CentOS用のCUDA 7.5, cuDNN 5のDockerイメージをpullして動かしてみる。

$ sudo nvidia-docker pull nvidia/cuda:7.5-cudnn5-devel-centos7
$ sudo nvidia-docker run --rm nvidia/cuda:7.5-cudnn5-devel-centos7 nvidia-smi
Fri Sep 30 08:19:56 2016       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 367.48                 Driver Version: 367.48                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GRID K520           Off  | 0000:00:03.0     Off |                  N/A |
| N/A   30C    P8    17W / 125W |      0MiB /  4036MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID  Type  Process name                               Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+

Dockerコンテナ上からGPUにアクセスできていることが確認できた。


Python3 + TensorFlowコンテナの作成

まずPython3 + TensorFlowのイメージを作り、そのイメージを元にR, RStudioを追加していく。Python3 + TensorFlowのイメージはtensorflow/Dockerfile.gpu at master · tensorflow/tensorflow · GitHubを参考にしてDockerfileを以下のように作成した。当初Python3はpyenvでインストールしていたがRのtensorflowパッケージのインストール時にリンクが見つからず対応できなかったのでyumでインストールしている。


nvidia-docker上でTensorFlowを実行するDockerfile


上記のDockerfileを元にDockerイメージを作成する。

$ sudo nvidia-docker build -f ./Dockerfile.tensorflow -t kashitan/tensorflow:latest --no-cache=true .


できたイメージからコンテナを作成してMNISTのサンプルを実行してみる。

# ホストOSでコンテナを起動
$ sudo nvidia-docker run -it --rm -p 8888:8888 ai_team/tensorflow:latest /bin/bash

# コンテナ上でMNISTのCNNを実行
$ python3 /usr/lib/python3.4/site-packages/tensorflow/models/image/mnist/convolutional.py
I tensorflow/stream_executor/dso_loader.cc:108] successfully opened CUDA library libcublas.so locally
I tensorflow/stream_executor/dso_loader.cc:108] successfully opened CUDA library libcudnn.so locally
I tensorflow/stream_executor/dso_loader.cc:108] successfully opened CUDA library libcufft.so locally
I tensorflow/stream_executor/dso_loader.cc:108] successfully opened CUDA library libcuda.so.1 locally
I tensorflow/stream_executor/dso_loader.cc:108] successfully opened CUDA library libcurand.so locally
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
I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:925] 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: GRID K520
major: 3 minor: 0 memoryClockRate (GHz) 0.797
pciBusID 0000:00:03.0
Total memory: 3.94GiB
Free memory: 3.91GiB
I tensorflow/core/common_runtime/gpu/gpu_init.cc:126] DMA: 0 
I tensorflow/core/common_runtime/gpu/gpu_init.cc:136] 0:   Y 
I tensorflow/core/common_runtime/gpu/gpu_device.cc:838] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GRID K520, pci bus id: 0000:00:03.0)
Initialized!
Step 0 (epoch 0.00), 10.7 ms
Minibatch loss: 12.054, learning rate: 0.010000
Minibatch error: 90.6%
Validation error: 84.6%
(以下略)

ちゃんとGPUで処理できていることが確認できた。


また以下のように実行するとjupyter notebookが起動し、http://[EC2のパブリックIP]:8888でコンテナにアクセスできる。

$ sudo nvidia-docker run -d -p 8888:8888 -e PASSWORD=[パスワード] kashitan/tensorflow:latest /run_jupyter.sh


TensorFlow for Rイメージの作成

上記で作成したDockerイメージを元にTensorFlow for Rイメージを作成する。Dockerfileは以下の通り。RStudio-Serverにログインするためのcentosユーザーを追加している。またdevtools::install_github("rstudio/tensorflow")で/usr/lib64/libpython3.4.soが見つからずエラーとなるのでワークアラウンドとしてシンボリックリンクを作成している。

nvidia-docker上でTensorFlow for Rを実行するDockerfile


上記のDockerfileを元にDockerイメージを作成する。

$ sudo nvidia-docker build -f ./Dockerfile.rstudio --build-arg PASSWORD=[centosユーザーのパスワード] -t ai_team/tensorflow:rstudio  --no-cache=true .


以下のように実行するとRStudio-Serverが起動し、http://[EC2のパブリックIP]:8787でコンテナにアクセスできる。

# コンテナを起動
$ sudo nvidia-docker run -it --rm -p 8787:8787 kashitan/tensorflow:rstudio /bin/bash

# コンテナ上でRStudio-Serverを起動
$ /etc/init.d/rstudio-server start
Starting rstudio-server:                                   [  OK  ]


TensorFlow for Rのインストール&確認

あとはGitHub - rstudio/tensorflow: TensorFlow for Rに従ってRのパッケージをインストールするだけ。

install.packages("devtools")
library(devtools)
Sys.setenv(TENSORFLOW_PYTHON_VERSION = 3)
devtools::install_github("rstudio/tensorflow")


ちゃんとCUDAが読み込めていることも確認できた。

> library(tensorflow)
I tensorflow/stream_executor/dso_loader.cc:108] successfully opened CUDA library libcublas.so locally
I tensorflow/stream_executor/dso_loader.cc:108] successfully opened CUDA library libcudnn.so locally
I tensorflow/stream_executor/dso_loader.cc:108] successfully opened CUDA library libcufft.so locally
I tensorflow/stream_executor/dso_loader.cc:108] successfully opened CUDA library libcuda.so.1 locally
I tensorflow/stream_executor/dso_loader.cc:108] successfully opened CUDA library libcurand.so locally
> sess = tf$Session()
I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:925] 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: GRID K520
major: 3 minor: 0 memoryClockRate (GHz) 0.797
pciBusID 0000:00:03.0
Total memory: 3.94GiB
Free memory: 3.91GiB
I tensorflow/core/common_runtime/gpu/gpu_init.cc:126] DMA: 0 
I tensorflow/core/common_runtime/gpu/gpu_init.cc:136] 0:   Y 
I tensorflow/core/common_runtime/gpu/gpu_device.cc:838] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GRID K520, pci bus id: 0000:00:03.0)
> hello <- tf$constant('Hello, TensorFlow!')
> sess$run(hello)
b'Hello, TensorFlow!'
> 



以下のTweetにもあるようにgithub上のアクティビティはTensorFlowが一番活発で、最近の論文のリファレンス実行もtorchかTensorFlowが多いとか。

ちょうどTensorFlowの解説書も発売されたので勉強してみる。



以下MNIST For ML Beginnersを実行した結果。

# ライブラリの読み込みとMNISTデータセットのロード
> library(tensorflow)
> datasets <- tf$contrib$learn$datasets
> mnist <- datasets$mnist$read_data_sets("MNIST-data", one_hot = TRUE)
> str(mnist)
List of 3
 $ train     : $ validation: $ test      :
> 
> x <- tf$placeholder(tf$float32, shape(NULL, 784L))
> 
> # ウエイト
> W <- tf$Variable(tf$zeros(shape(784L, 10L)))
> 
> # バイアス
> b <- tf$Variable(tf$zeros(shape(10L)))
> 
> # softmax関数
> y <- tf$nn$softmax(tf$matmul(x, W) + b)
> 
> # 正解データを格納するためのプレースホルダ
> y_ <- tf$placeholder(tf$float32, shape(NULL, 10L))
> 
> # Cross Entropy関数の定義
> cross_entropy <- tf$reduce_mean(-tf$reduce_sum(y_ * tf$log(y), reduction_indices=1L))
> 
> # オプティマイザの設定
> optimizer <- tf$train$GradientDescentOptimizer(0.5)
> train_step <- optimizer$minimize(cross_entropy)
> 
> # 初期化
> init <- tf$initialize_all_variables()
> sess <- tf$Session()
I tensorflow/core/common_runtime/gpu/gpu_device.cc:838] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GRID K520, pci bus id: 0000:00:03.0)
> sess$run(init)
> 
> # 学習の実行
> for (i in 1:1000) {
+   batches <- mnist$train$next_batch(100L)
+   batch_xs <- batches[[1]]
+   batch_ys <- batches[[2]]
+   sess$run(train_step,
+            feed_dict = dict(x = batch_xs, y_ = batch_ys))
+ }
> 
> # モデルの評価
> correct_prediction <- tf$equal(tf$argmax(y, 1L), tf$argmax(y_, 1L))
> accuracy <- tf$reduce_mean(tf$cast(correct_prediction, tf$float32))
> sess$run(accuracy, feed_dict=dict(x = mnist$test$images, y_ = mnist$test$labels))
[1] 0.9218001
> 

Deep MNIST for Expertsを見る限りCNNも簡単に定義できそうだけどmxnetの方が記述は少なくて済みそう。。。