【Google Colab】Red Chainer を使ってみた

Google Colab で GPU を使用してRed chainer を動かしてみました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/144608/67bc3070-54e7-aeaf-4392-978b8ad36af5.png)![image.png](https://qiita-image-store.s3.amazonaws.com/0/144608/f62ae99b-b191-9714-2ec2-2887bf5d2c3f.png)

## [Google Colaboratory](https://colab.research.google.com) とは
Google Colaboratory はGoogleのアカウントさえあれば無料でGPUが使えるJupyter環境です。公式はPython対応をうたっていますが、実際にはカスタムでインストールすることでJupyterカーネルがあるさまざまな言語を動かすことができると思われる。少なくともRubyは動く。

## [NArray](https://github.com/ruby-numo/numo-narray) とは
RubyにおけるNumpy。Cで実装されている。高速。
（SciRubyのNMatrixはNArrayより遅い）

## [Cumo](https://github.com/sonots/cumo) とは
RubyにおけるCupy。CUDAを使用している、NArrayと互換性のあるライブラリ。

## [Red Chainer](https://github.com/red-data-tools/red-chainer) とは
ChainerのRuby版。NArrayを使用しているので、Cumoに切り替えることでGPUを使うことができる。


# 動かしてみる
ここでは誰でも無料でGPUを使えるGoogle Colabで動かす方法を説明しますが、無理をしている感じは否めません。手元のコンピュータでCUDAが動作する場合はそちらで試した方がよいでしょう。

## GPU対応のランタイムを選択する

一番最初にGPU対応のランタイムに変更します。ファイルを開き直した時など、気が付かないうちにGPU非対応に切り替わることがあるので注意してください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/144608/d305e3f9-0642-832d-4be4-41eff4e6447d.png)

## Google ColabにRubyとCumoをインストールする
* [Google Colab で Rubyを動かしてみた](https://qiita.com/kojix2/items/64f14e3487e3d957d4e5)
  の方法でRubyをインストールします。
  この時一緒にred-chainerもインストールします。（コマンド実行時間 約5分)

```bash
!gem specific_install https://github.com/red-data-tools/red-chainer
```

* [Google colab で RubyからGPU を使って行列計算する](https://qiita.com/kojix2/items/5cf18978c930df72d162)
  の方法でCumoをインストールします。（コマンド実行時間 約10分）

ランタイムがGPU Noneの場合もインストール自体は成功したりするようなので注意が必要です。

## Red Chainerを実行する
### 3層ニューラルネットワークによるMNISTの分類
以下Red chainerのサンプルを少し改変したものを実行してみます。

```ruby
require 'chainer'

include Chainer 
F = Functions
L = Links
Ext = Training::Extensions

class MLP < Chain
  Linear = L::Connection::Linear
  R = F::Activation::Relu

  def initialize(n_units, n_out)
    super()
    init_scope do
      @l1 = Linear.new nil, out_size: n_units
      @l2 = Linear.new nil, out_size: n_units
      @l3 = Linear.new nil, out_size: n_out
    end
  end

  def call(x)
    h1 = R.relu(@l1.call x )
    h2 = R.relu(@l2.call h1)
    @l3.call h2
  end
end

batchsize = 100
epoch     = 3
gpu       = 0
unit      = 1000
out       = 'result'

# Set up a neural network to train
device = Device.create gpu
Device.change_default device
lossfun = lambda { |x, t|
  F::Loss::SoftmaxCrossEntropy.new(ignore_label: nil).call(x, t)
}
model = L::Model::Classifier.new(MLP.new(unit, 10), lossfun)

# Setup an optimizer
optimizer = Optimizers::Adam.new
optimizer.setup model

# Load the MNIST dataset
train, test = Chainer::Datasets::MNIST.get_mnist
train_iter = Iterators::SerialIterator.new train, batchsize
test_iter  = Iterators::SerialIterator.new test,  batchsize,
                                           repeat: false, shuffle: false

# Set up a trainer
updater = Training::StandardUpdater.new train_iter, optimizer,
                                        device: device
trainer = Training::Trainer.new updater,
                                stop_trigger: [epoch, 'epoch'],
                                out: out

# Print selected entries of the log to stdout
items = ['epoch',
         'main/loss',
         'validation/main/loss',
         'main/accuracy',
         'validation/main/accuracy',
         'elapsed_time']

extensions = [
  Ext::Evaluator.new(test_iter, model, device: gpu),
  Ext::LogReport.new,
  Ext::PrintReport.new(items, out: $stdout)#, out: $stdout はJupyter出力に必要
  # Ext::ProgressBar.new(out: $stdout)
]
extensions.each{ |e| trainer.extend e }

trainer.run
```
無事に実行できると、下記のような画面が出力されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/144608/dfbe2e1b-32ee-47af-574e-2bb86c6ca155.png)

# VGG16によるCIFAR10の分類
次にVGGによるCIFAR10分類のExampleを試みましたが、結論から言うと2019年2月8日時点では、まだGoogle Colabで試すには時期尚早のようです。GPUを使用してもなぜかほとんど実行速度は上がらず、場合によってはエラーが発生することもあるようです。

# 付記 2019年のRubyの機械学習環境について
2019年2月現在 注目しているRubyのプロダクトは次の通りです。

| python       | Ruby        | 説明             |
|--------------|-------------|------------------|
| NumPy        | NArray      | 数値計算         |
| Cupy         | Cumo        | 数値計算(GPU)    |
| Chainer      | Red Chainer | Deep Learning    |
| IPython      | IRuby       | Jupyter Notebook |
| Pandas       | Daru        | データフレーム   |
| scikit-learn | Rumale      | 機械学習全般     |

可視化ライブラリについては定番のものはなく色々なものが開発されています。しかし、現時点でもある程度使える完成度、メンテナンスが継続的という観点で下記の２点をあげます。

| ライブラリ    | バックエンド  |
|--------------|-------------|
|[numo-gnuplot](https://github.com/ruby-numo/numo-gnuplot)|gnuplot|
|[Daru::View](https://github.com/SciRuby/daru-view)|Google Charts または Highcharts|

そのほかにも私が知らないだけでもおもしろいプロジェクトがたくさんあると思います。

この記事は以上です。