この記事を読む前に
この記事は2018年のChainerアドベントカレンダーの一つとしてかかれました。
当時のChainerXはリリースされたばかりであり、動作するプラットフォームは限られていましたが、ChainerのV6の正式版がリリースされている現在では多くのOS,プラットフォームでChainerXの導入が可能となっています。(ただし、あくまでもインストールのみを確認しており、プログラマの意図通りに動作するかは非自明です。)
本日は
師走の月になってきました。
Chainerのカレンダー空いていたというのと
ChainerXどうやら無事にマージされたようだ。めでたい☺https://t.co/Iw4zLszbvN
— Keisuke Umezawa (Chainer Evangelist) (@kmechann) 2018年11月30日
ChainerXでAdvent Calender 書くマンおらんか〜 https://t.co/zPrwAmpQQl
— Keisuke Umezawa (Chainer Evangelist) (@kmechann) 2018年11月30日
のもあったので書くマンになります。
ふだん、Chainerにはおせわになっているし、なにか貢献できれば・・・。
ChainerX
ChainerのPR #5725 でマージされました。
ChainerX is a new ndarray+autograd implementation for Chainer. It aims at reducing Python overhead for host-heavy workloads, providing Python-free basis for application coding, and making device support pluggable.
This PR is to move the development to the main repository. It includes:
- C++ implementation of the new ndarray and related routines (chainerx_cc),
- Python binding of ChainerX (chainerx_cc/python and chainerx),
- Modifications on Chainer to support the new ndarray, and
- Documentation of ChainerX
We are planning to include this feature in the next beta release.
This PR is very big so that it's impossible to run review here, but we still use PR instead of silently merging it for visibility of changes included in the release. I'd like to merge it once CI is made ready and we confirm that this PR passes that.
cupy とか ideep4py のように多次元配列をあつかう(しかも自動微分付き)新しいバックエンドの追加のようなものでしょうか??
下記のTweetがよくまとまっています。
ChainerXをざっと眺めた
— not (@not_522) 2018年11月28日
・Chainer自体の更新ではなく、backendの追加
・C++で書かれたNumPy/CuPy風のライブラリ
・CPU/GPU両方で動く
・Pythonのオーバーヘッドを削減することによる高速化を目指す
・ChainerXそのものにNN用の関数や自動微分が入っているhttps://t.co/IMWdeJlKc1
出たばかりでなんとも言えませんが、PythonをさけてC++での深層学習の CPU/GPU の学習・(および推論も?)できるのかもしれませんね。
入れてみよう
ChainerのGitHubのページからたどると ChainerXのインストール方法がかかれています
$ export CHAINER_BUILD_CHAINERX=1
$ export MAKEFLAGS=-j8 # Using 8 parallel jobs.
$ pip install --pre chainer
Collecting chainer
Requirement already satisfied: filelock in /home/terasaki/miniconda3/lib/python3.6/site-packages (from chainer) (3.0.9)
Requirement already satisfied: protobuf>=3.0.0 in /home/terasaki/miniconda3/lib/python3.6/site-packages (from chainer) (3.6.1)
Requirement already satisfied: numpy>=1.9.0 in /home/terasaki/miniconda3/lib/python3.6/site-packages (from chainer) (1.15.4)
Requirement already satisfied: six>=1.9.0 in /home/terasaki/miniconda3/lib/python3.6/site-packages (from chainer) (1.11.0)
Requirement already satisfied: setuptools in /home/terasaki/miniconda3/lib/python3.6/site-packages (from protobuf>=3.0.0->chainer) (40.4.3)
Installing collected packages: chainer
Successfully installed chainer-6.0.0a1
terasaki@wizzard:~/tmp$
お?楽勝かな??
--pre
は pypaのドキュメント で次のような説明があります。
Include pre-release and development versions. By default, pip only finds stable versions.
はじめてしった・・・。ちなみにバージョンはChainer6に昇格するので開発中のPCでは取り扱い注意です(普段Dockerをつかっていれば問題ないですが)
つかってみよう
ChainerXのチュートリアル
によると Pythonからは import chainerx
でモジュールをインポートしていろいろできるとのこと
>>> import chainer
>>> chainer.__version__
'6.0.0a1'
>>> import chainerx
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'chainerx'
ん???
入れてみよう
$ pip uninstall chainer
Uninstalling chainer-6.0.0a1:
Would remove:
/home/terasaki/miniconda3/lib/python3.6/site-packages/chainer-6.0.0a1.dist-info/*
/home/terasaki/miniconda3/lib/python3.6/site-packages/chainer/*
/home/terasaki/miniconda3/lib/python3.6/site-packages/chainermn/*
Proceed (y/n)? y
Successfully uninstalled chainer-6.0.0a1
$ git clone https://github.com/chainer/chainer.git
$ cd chainer
$ pip install .
Processing /home/terasaki/tmp/chainer
Requirement already satisfied: setuptools in /home/terasaki/miniconda3/lib/python3.6/site-packages (from chainer==6.0.0a1) (40.4.3)
Requirement already satisfied: filelock in /home/terasaki/miniconda3/lib/python3.6/site-packages (from chainer==6.0.0a1) (3.0.9)
Requirement already satisfied: numpy>=1.9.0 in /home/terasaki/miniconda3/lib/python3.6/site-packages (from chainer==6.0.0a1) (1.15.4)
Requirement already satisfied: protobuf>=3.0.0 in /home/terasaki/miniconda3/lib/python3.6/site-packages (from chainer==6.0.0a1) (3.6.1)
Requirement already satisfied: six>=1.9.0 in /home/terasaki/miniconda3/lib/python3.6/site-packages (from chainer==6.0.0a1) (1.11.0)
Building wheels for collected packages: chainer
Running setup.py bdist_wheel for chainer ... done
Stored in directory: /tmp/pip-ephem-wheel-cache-nolm7ktr/wheels/dc/eb/02/fad9e4ce07b707b8063e7e245d168846851a2b3cf05d432b96
Successfully built chainer
Installing collected packages: chainer
Successfully installed chainer-6.0.0a1
なにかしらのビルドは通ったっぽい。
サンプルを動かす
Ubuntu上でしています。
import chainerx as chx
x = chx.array([[0, 1, 2], [3, 4, 5]], dtype=chx.float32)
print(x.shape)
print(x.dtype)
print(x.device)
$ python3 study_x.py
(2, 3)
float32
native:0
UGOITA・HAGOITA・DEKITA(歓喜)
GPU 版も動かしたい
CuPy のインストールが時間かかります(CuPyは読み方くーぱい
らしいけれど くぴー
のほうが可愛い気がする.でもそうするとNumPyがぬむぴー
になって変か・・・)
$ export CHAINER_BUILD_CHAINERX=1
$ export CHAINERX_BUILD_CUDA=1
$ export CUDNN_ROOT_DIR=path/to/cudnn
$ export MAKEFLAGS=-j8 # Using 8 parallel jobs.
$ git clone https://github.com/cupy/cupy.git
$ cd cupy
$ pip install .
$ cd ../chainer
$ pip install .
>>> import chainerx
>>> cuda_x = chainerx.array([1,2,3],device='cuda:0')
>>> cuda_x
array([1, 2, 3], shape=(3,), dtype=int64, device='cuda:0')
>>> cuda_x. # ここでタブを連打
cuda_x.T cuda_x.fill( cuda_x.reshape(
cuda_x.argmax( cuda_x.get_grad( cuda_x.set_grad(
cuda_x.as_grad_stopped( cuda_x.grad cuda_x.shape
cuda_x.astype( cuda_x.is_backprop_required( cuda_x.size
cuda_x.backward( cuda_x.is_contiguous cuda_x.squeeze(
cuda_x.cleargrad( cuda_x.is_grad_required( cuda_x.strides
cuda_x.clip( cuda_x.itemsize cuda_x.sum(
cuda_x.copy( cuda_x.max( cuda_x.take(
cuda_x.data_ptr cuda_x.nbytes cuda_x.to_device(
cuda_x.data_size cuda_x.ndim cuda_x.transpose(
cuda_x.device cuda_x.offset cuda_x.view(
cuda_x.dot( cuda_x.ravel(
cuda_x.dtype cuda_x.require_grad(
>>> cuda_x.to_device('native:0')
array([1, 2, 3], shape=(3,), dtype=int64, device='native:0')
うっかり export CUDNN_ROOT_DIR=path/to/cudnn
抜かしてしまったんですけれど、動いています. ローカルにすでにcuDNNいれていたからかな? (ドキュメントにExampleがほしいです)。
追記 2019/06/06:
cuDNN のインストール方法によって格納場所が異なるみたいなので
の議論にあるパスを眺めてみると良いです。この後
$ pip install cupy -vvvv
をした際に出力されるログにおいてcuDNNのパスが認識されていれば大丈夫なはず。
ラズパイ3でいけるかな???
ideep の恩恵受けられないので動くとうれしみが。
pi@raspberrypi:~ $ git clone https://github.com/chainer/chainer.git
Cloning into 'chainer'...
remote: Enumerating objects: 25, done.
remote: Counting objects: 100% (25/25), done.
remote: Compressing objects: 100% (18/18), done.
remote: Total 157873 (delta 9), reused 19 (delta 7), pack-reused 157848
Receiving objects: 100% (157873/157873), 37.95 MiB | 940.00 KiB/s, done.
Resolving deltas: 100% (115947/115947), done.
pi@raspberrypi:~ $ cd chainer/
pi@raspberrypi:~/chainer $ ls
LICENSE chainer_bibtex.txt chainerx_cc setup.cfg
MANIFEST.in chainermn codecov.yml setup.py
README.md chainermn_bibtex.txt docker tests
appveyor chainerx docs
appveyor.yml chainerx.md examples
chainer chainerx_build_helper.py readthedocs.yml
pi@raspberrypi:~/chainer $ export CHAINER_BUILD_CHAINERX=1
pi@raspberrypi:~/chainer $ export MAKEFLAGS=-j4
pi@raspberrypi:~/chainer $ sudo pip3 install .
Processing /home/pi/chainer
Requirement already satisfied: filelock in /usr/local/lib/python3.5/dist-packages (from chainer==6.0.0a1)
Requirement already satisfied: numpy>=1.9.0 in /usr/local/lib/python3.5/dist-packages (from chainer==6.0.0a1)
Requirement already satisfied: protobuf>=3.0.0 in /usr/local/lib/python3.5/dist-packages (from chainer==6.0.0a1)
Requirement already satisfied: setuptools in /usr/lib/python3/dist-packages (from chainer==6.0.0a1)
Requirement already satisfied: six>=1.9.0 in /usr/lib/python3/dist-packages (from chainer==6.0.0a1)
Installing collected packages: chainer
Found existing installation: chainer 5.0.0
Uninstalling chainer-5.0.0:
Successfully uninstalled chainer-5.0.0
Running setup.py install for chainer ... done
Successfully installed chainer-6.0.0a1
pi@raspberrypi:~ $ python3
Python 3.5.3 (default, Sep 27 2018, 17:25:39)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import chainerx
>>> chainerx.__version__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'chainerx' has no attribute '__version__'
>>> import chainerx as chx
>>> x=chx.array([1,2,3,4],dtype=chx.float32)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'chainerx' has no attribute 'array'
あぁぁ・・・いぃぃ・・・うぅぅ。
Macだと?
ざんねんながらビルドでこけてしまいます。
更新:2019/06/06更新: Chainerの V6.0.0 ではビルド成功できました!!!!
$ export CHAINER_BUILD_CHAINERX=1
$ pip uninstall chainer # 古いChainerを削除
$ pip install chainer
$ python
>>> import chainerx as chx
>>> chx.array([1,2,3])
array([1, 2, 3], shape=(3,), dtype=int64, device='native:0')
>>> import chainer
>>> chainer.__version__
'6.0.0'
そんなわけで
すこし寄り道しましたが、Ubuntuでは ChainerX の導入はいけそうです。Chainer5触ったばかりの人間ですが、Chainer6を導入して背伸びすることができ、良い経験をすることができたとおもいます。以下、うごいたUbuntu16.04マシーンでMNIST学習してみます。
MNIST
https://github.com/chainer/chainer/tree/master/chainerx_cc/examples/mnist を参考にしました。
$ cd chainer/chainerx_cc/example/mnist
$ bash download.sh
$ ls
download.sh mnist README.md train_mnist.py
$ python train_mnist.py --device=cuda:0
epoch 1... loss=0.483272021484375, accuracy=0.8827, elapsed_time=0.9652724266052246
epoch 2... loss=0.3484232666015625, accuracy=0.9055, elapsed_time=1.627737283706665
epoch 3... loss=0.3021266845703125, accuracy=0.9153, elapsed_time=2.283825159072876
epoch 4... loss=0.277078173828125, accuracy=0.9199, elapsed_time=2.9371321201324463
epoch 5... loss=0.2530198974609375, accuracy=0.9293, elapsed_time=3.594005823135376
epoch 6... loss=0.2379763427734375, accuracy=0.9335, elapsed_time=4.25266695022583
epoch 7... loss=0.224865869140625, accuracy=0.9369, elapsed_time=4.911699056625366
epoch 8... loss=0.214370947265625, accuracy=0.9392, elapsed_time=5.569540739059448
epoch 9... loss=0.2032531982421875, accuracy=0.9426, elapsed_time=6.233461380004883
epoch 10... loss=0.1948798583984375, accuracy=0.9437, elapsed_time=6.891218423843384
epoch 11... loss=0.1849767578125, accuracy=0.9466, elapsed_time=7.554072856903076
epoch 12... loss=0.1776248291015625, accuracy=0.9474, elapsed_time=8.219156503677368
epoch 13... loss=0.16978060302734374, accuracy=0.95, elapsed_time=8.877105951309204
epoch 14... loss=0.16511090087890626, accuracy=0.9513, elapsed_time=9.53380298614502
epoch 15... loss=0.1575286376953125, accuracy=0.9538, elapsed_time=10.190188884735107
epoch 16... loss=0.15317554931640626, accuracy=0.9543, elapsed_time=10.849192380905151
epoch 17... loss=0.14726854248046875, accuracy=0.9571, elapsed_time=11.506675243377686
epoch 18... loss=0.1426803955078125, accuracy=0.9567, elapsed_time=12.164527416229248
epoch 19... loss=0.138498828125, accuracy=0.9592, elapsed_time=12.825119733810425
epoch 20... loss=0.1334173828125, accuracy=0.96, elapsed_time=13.483542919158936
watch nvidia-smi
を眺めながらするとGPUがむぉおおおおと言わんばかりに動いているのがわかります。
CPU だとこれぐらい
$ python train_mnist.py
epoch 1... loss=0.479378076171875, accuracy=0.8823, elapsed_time=21.332125425338745
epoch 2... loss=0.3438715087890625, accuracy=0.9064, elapsed_time=39.776408195495605
epoch 3... loss=0.2983966064453125, accuracy=0.9183, elapsed_time=54.61747431755066
epoch 4... loss=0.2714416748046875, accuracy=0.9253, elapsed_time=69.31229591369629
epoch 5... loss=0.2527154541015625, accuracy=0.9285, elapsed_time=84.05134153366089
epoch 6... loss=0.2373039306640625, accuracy=0.9346, elapsed_time=98.87632894515991
epoch 7... loss=0.223982470703125, accuracy=0.9378, elapsed_time=118.0163414478302
もっとこまかい Example ほしい?
とかが参考になりそうです。
以上初めてのアドベントカレンダーでした。