今日の落書き Ruby の PyCall で Keras の Mnist 画像部類

RubyでPythonっぽいコードを書くと、RubyでPythonが実行できるというPyCallというGemがあります。
このPyCallでDeep Learning用のライブラリであるKerasが動かせるということなので、やってみました。

こちらのサイトを参考にしました。
PyCallを使えばRubyでもKerasでDeep Learningができる(洋食の日記)

短いコードですが、半年ぐらいプログラミングに触れていなかったのでかなり時間がかかりました。

工夫したところ

・RubyからPython呼んでいる時点で無駄が多いことをしている。だから何も気にせずに、ライブラリを贅沢に使おうと思った。
・MnsitをRubyの配列で呼ぶためだけにruby_brainを使用した。
・255で割るためだけにNumo/NArrayを使用した。
・結果として、mnistの元ファイル ⇢ Ruby配列 ⇢ NArray配列 ⇢ テキストファイル ⇢ numpy配列 という情報の変換、受け渡しにとても時間がかかっている。
 (・しかし、これは、PCを使わない人工知能にも広く見られる現象だ)
・ハマったのは、Kerasでmnist読み込む時と、ruby_brainでnnist呼びこむ時のデータ形式の違い。

よかったところ

・うごく!
・Rubyでディープラーニングする手段がある。0と1では大違い。

不満が残るところ

・PyCallでKerasを実行している最中に Ctrl+C でターミナルを停止できない
・エラーメッセージがもっと改行してくれると嬉しい
・やはり Ruby ←→ Pyrhon の情報のやりとりに不自由を感じる
 ・Rubyで前処理して一度ファイルに保存、Pythonで処理するのが現実的かもしれない

ASUS ZenBook に Keras を入れるまで

常用していた中古のノートパソコンをMacbookに買い換えました。周囲のMac使用率が50%に近づいている現在、Macを購入する最大のメリットは、周囲とのコミュニケーションの心理的な促進作用だと思います。Macには人と人とのつながり、コミュニケーションを誘発する作用があります。そこにはスペックだけ見ているとわからない、お金にできない、大きな価値があります。それに、Macを使っていると気分がいいです。Macについて語るとき、みんな笑顔になります。洗練されたGUIとシンプルなソフトウェアに囲まれて作業していると、落ち着いた気持ちになります。そう、間違いなくMacを選択するメリットは大きいのです。そうだMacbook Proを購入しよう。2年ぶりにUbuntuからMacに戻ろう。鼓動の高なりを感じながら、僕は家を出た。


そして、ASUSとともに帰宅。


Intelのシールの右に、緑色のNVIDIAのシールが張られている。GeForce 940MX搭載である。つまりCudaが使える。それからMacは高い。そりゃあなた、お金は大事ですよ。(しかし現行MacにGeForce搭載されていたら本当にMacbookを買っていたと思う)

以下困った時のためにKeras導入までの自分用メモ。

① まず購入して真っ先に、Intel等のシールをはがす。Macでは不要な作業。

② ブートUSBの作成
UNetbootinではなくこちらを使用した。とくに不具合なし。Ubuntu 16.04
UbuntuのブートUSB作成 (usb-creator を使用)

③ 画面の解像度がおかしい
→ソフトウェアアップデートして再起動

④ Cuda8.0のインストール
第456回 Ubuntu 16.04 LTSでCUDA 8.0を使用する 2017年2月1日 柴田充也
→ こちらの情報が適確で初心者にもわかりやすいのでその通りにした
→ deb(network)を選択した
→ 自動的にnvidia-375がインストールされる。NVIDIAのサイトでsupported productにGeForce 940MXが含まれていることを確認
→ PATHの設定、LD_LIBRARY_PATHの設定
→ nvcc –version や echo $LD_LIBRARY_PATH で確認

⑤ nvidia-smiコマンドが見つからない
→ F2でBIOSの設定に入り secure boot をdisableに変更して起動

⑥ cuDNN のインストール
CUDA 8.0とcuDNN 5.1をUbuntu 16.04LTSにインストールする
→ こちらの通りにした。
→ cuDNN のバージョンは要注意

⑦ Anacondaの導入
公式サイトの通り

⑧ 新しい環境の作成:
conda create -n keras .anaconda python=3.5
→ 最新過ぎるとはまりやすいという感覚で何となく3.5に

⑧ tensorflowのインストール
公式サイトの通り(Ubuntu/Anaconda使用版)

⑨ pythonでtensorflowを読み込んだ時のエラー
ImportError: libcudnn.5: cannot open shared object file: No such file or directory
→ まずはLD_LIBRARY_PATHの設定を見直し → 改善せず
→ stackoverflowの中段の解決策が有効
→ そもそもディレクトリのなかにlibcudnn.5が存在しないので、シンボリックリンクを作成
→ ln -s libcudnn.so.6* libcudnn.so.5
→ import tensorflow as tf が動作することを確認

⑩ Keras のインストール
公式サイトの通り
pip install keras
→ 公式exampleのmnist(MLP)が動作することを確認
→ nvidia-smi で確かにCPUではなくGPUで動作していることの確認

細かい不具合あるかもしれないが、これで手元でKerasを勉強できる環境が整った。

UbuntuでRuby2.4.1にTkをインストールする

TkがRuby本体から分離されましたが、オプションは今までの通りでも大丈夫なようです。

gem install tk — –with-tcltkversion=8.6 \
–with-tcl-lib=/usr/lib/x86_64-linux-gnu \
–with-tk-lib=/usr/lib/x86_64-linux-gnu \
–with-tcl-include=/usr/include/tcl8.6 \
–with-tk-include=/usr/include/tcl8.6 \
–enable-pthread

ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装 を買った

書店をぶらついていると、真っ赤なタイトルの本が目に飛び込んできた。

ページをめくってみた。すごい。勉強になる。数式読めない人けど、なんとなくDeep Learningが理解できるかも知れないきざしのきざしの兆候を感じる。すごい。うじゃひょぇえええええ!!!!!期待にドキドキ胸が鼓動を早める。そう、これは…買っただけで勉強しない時の予感。

ふと、ページをめくる指が震える。
おかしい。何かがおかしい。かすかに感じるこの違和感はなんだろう。もしかして、この素晴らしい本には、ひょっとして一点だけ欠陥と言わざるをえないところがあるのではないか。すべて整っているのに肝心のところで、どこか画竜点睛を欠くのではないか。

その原因は、最初はぼんやりとしていたが、次第に誰の目にもわかるほど明瞭になっていった。

どういうわけか、本文中のコードに Ruby + NArray が一行も使われてないのである。 そのかわり Python + numpy という一風変わった言事とライブラリが使用されている。Python? パイソン? 聞いたことがない新鮮な響きだ。Rubyはどこへいったのだろう? 公園だと思ったら行ってみたら墓地だった。そんな衝撃を想像してほしい。

これでは作者の美的センスを疑わざるをえない状況である。それだけではない。近代文明社会への冒涜、民主主義への挑戦というものではなかろうか。久々に怒りで額に汗が流れた。グルグルと景色が回りはじめ、書棚に並ぶ本たちの笑い声がドッと湧いてこだました。

※ 本文はフィクションです。謹んで勉強させていただきます。

無知をさらす
・損失関数についてあまり意識してなかった
 ・交差エントロピー誤差というものを知らなかった
 ・なるほどsoftmaxと交差エントロピー誤差はセットなのね
・数値微分という言葉を知らなかった
・勾配によるニューラルネットワークの更新がよく理解できない
・chainerって連鎖率(chain rule)から名前がつけられたのだろうか
 ・合成関数の微分は合成関数を構成するそれぞれの関数の微分の積によって表すことができる
・ハイパーパラメータという言葉はよく聞くが、なぜハイパーというのか知らなかった
・ミニバッチはランダムにサンプルを取得するものだと知らなかった(順番にサンプル取得するものだとばかり思っていた)
・加算、乗算の計算グラフによる逆伝播を理解した
・Adamが理解できないぞ?
・Xavierの初期値は、sigmoidやtanhに有効だが、ReLuには「Heの初期化」がある。へー。
・Batch Normalization 今度やってみよう
・ハイパーパラメータの最適化は結局総当り式?
・特徴マップという言葉を知らなかった
・im2colねえ…。これRubyだけで実装するとやっぱりfor(each)使わざるを得ない気がするが。

自信をもったところ
なんだかんだですでに実装したことがあるような内容も多い。①パーセプトロン、②2層ニューラルネットワーク、③計算グラフ ④バッチ処理 ⑤CNNみたいな順番で勉強してきてよかったなと。経験的に好きな事はつまみ食い的に勉強した方が、かえって効率的に勉強できる気がする。むしろこの本だけでDeep Learning勉強しようとしていたらどこまで理解出来てたか疑問だ。

この本のおかげでchain ruleと計算グラフについて少し理解した。
加算ノードの逆伝播と、乗算ノードの逆伝播理解したから。Numo::NArrayでLSTMにもう一回挑戦してみたいな。

RubyでKaggleのMnistを試してみた

はじめてのKaggle

 先のエントリーで医用画像認識ソフト開発の米EnliticがKaggleでエンジニアを集めているということを知って、技術者でもなんでもないけどKaggleをちょっと試してみたくなった。

Mnist

 チュートリアルでMnist手書き文字認識があるそうなので、以前作成したRubyでニューラルネットでMnist認識するコードを使って投稿してみた。使用したニューラルネットワークはこんな感じ。隠れ層が大きくなると実行に時間がかかるので200程度にとどめておいた。

 3層のニューラルネットワークなので、少し無理をすればディープラーニングの定義に当てはまるかも知れない…いや、やっぱり無理かな。

バックプロパゲーションだけで多層ニューラルネットワークを学習させてみる

 なぜ単純なバックプロパゲーションだけで多層ニューラルネットワークが学習できてしまうのかというと(Mnist手書き文字認識が簡単な問題だからかも知れないが)10点中10点満点で正解した場合でも「おまえはまだまだ出来るはずだ。次から100点を取らないと。まだ90点足りないよ!」いう感じ(ニューラルネットがつらそうですね)で大げさに誤差を逆伝播させる仕組みにしているからだと思う。多分。以前試した時は4層〜6層ぐらいの先細りの多層パーセプトロンなら、denoising autoencoder等の方法を使わなくても学習できていた。(softmaxがよくわかってなかった頃に思いつきで実装しただけなので、何という手法なのかは知らない。そしてこの方法で作られた重みはdenoising autoencoderで学習させた重みと比較して可視化した時にあまり綺麗とは言えない。)

結果

結果は正解率 0.97657 で1218チーム中470番ぐらいでした。(でもこれ画像の並行移動してなかったら、Mnistの出典データを参照するだけで正解率100%簡単に出せるんじゃ…)

学習時間は手元のパソコンで2時間弱かかった。

改善できそうなところ

 これまでにもParallelsによる並列計算による改良を何回か試みたけどうまくいってない。順伝播(評価時)はうまくいく。パイプで返却されるデータが少ないためかThreadの待ちがうまく動く。CPUのファンがぶんぶん回って、htopコマンドで4つのCPUの使用率100%になるのを見るのは爽快だ。しかし逆伝播では、パイプで返却される重みのデータ量が多すぎるせいか、Threadの待ち合わせがうまく動いてくれない。STDOUT.sync = true すればいいとかそういう問題でもないみたいだ。ここを上手くやって複数のCPUで動いてくれれば、もうすこし高速化できると思うけど難しい。

 あとは旧NArray + opencl_ruby_ffiを使えばGPUによる高速計算もある程度できると思う。しかしC言語も読み書きできない私のような素人さんにはちょっと敷居が高すぎるというのが正直なところだ。NarrayからGPUのメモリに移動して、GPUのメモリからNArrayに移動して、NArrayからGPUのメモリに移動して、を繰り返す時間的ロスってどのぐらいなのか気になる。OpenCLは手元のパソコンで試していてPCがフリーズしたりした時に萎えるけど、Amazon EC2 のGPUインスタンスでもopencl_ruby_ffiが動くことを確認したので今度試してみたいところ。

 ひと通りKaggle体験を楽しんだあと、日本にもKaggleのようなサイトがないか探してみた。いくつかみつかったけど、どこもKaggleほどの活気はなく、なんだか閑散としていてほんの少し寂しい気持ちになったのでした。

Amazon EC2 試してみた

 chainerでより気軽に遊ぶためにAmazon EC2を試してみた。そして思った。凄いなあと。ディープラーニング向けのレンタルサーバーはこれからの分野のようで、IDCフロンティアは、近日サービス開始となっている。アリババにはGPUクラウドがあるみたいだけど日本語の情報が少なすぎて敷居が高い。手元のパソコンでDeep Learningを試したい人は初期費用20万円ぐらい計上してGPU付きのPCを準備する必要があったけど、もうそんな時代ではないみたいだ。でも、いい事ずくめで興奮しているのに、どうしてもクラウドコンピューティング万歳という気分にはなれない。なんでだろう。それはともかく、はやくRubyでNArray使って簡単にGPU計算できる時代になりますように。

犬がかわいい

ソウル大学のgliese581ggさんのYOLO_tensorflowのtiny版をNumo::NArrayに直訳してみました。
cutedog
何が言いたいかというと、犬がとてもかわいい。

アルゴリズム:You only look once (YOLO)
言語:Ruby
ライブラリ:Numo::NArray, oily_png
重み:YOLO_tensorflow

※ Deep Learning はできていません

(この画像には本来著作権があるのかも知れないが確かめられなかった。しかしインターネット上では壁紙用画像として広く配布されているようだから許してほしい。)

データセット、データセット

 VGGによる画像分類は面白い。もしデータセットがあれば医用画像で人間の認識を超える精度を出すこともできる気がする。特にCTでは、あっという間に人間を超える高精度を出してくれそうでこわい。もしもCTの読影をDeep Learningでやらせようとすると、いくつかの課題があるように感じられる。第1に、個人情報保護の問題、第2に、完備されているデータセットを作ることが難しい問題、第3に、自動運転のような安全性に関する問題がある。
 このうちで最も問題になるのは、データセットを作るところだと思う。もちろんまず個人情報保護をきちんと解消しないとデータセットは作れなが、安全性に対する不安は、一旦高品質な分類器が作られ始めると、世間の反応は変わっていくのではないかと思う。今現在でも、レポート文章とレポート添付画像を使ってCNNとLSTM組み合わせて学習させれば相当なところまでやれるのかも知れない。国内でこういう事をこっそり研究してそうなところは富士フィルムさんかな。放射線科医はこの問題についてどう考えているのだろう。

 雑多な資料をながめていて思ったのは、ImageNetという団体が主催するコンテストによって画像認識がどんどん進化していったということ。そのようなコンテストが色々な領域で生まれて、やがて医療をとりまく環境も少しずつ変わっていくのでしょう。あるいは、オープンなデータセットが作られないまま謎の方向へ進化していく道も薄っすらと想像されるが、そちらの方向はあまり望ましくないと個人的には思います。

Ruby で畳み込みニューラルネットワーク(VGG-16)

RubyでVGG16による画像分類を書いてみました。

行列計算はいつも通りNumo::NArrayを使いました。
学習済みの重みとバイアスは、こちらのchainerモデル(元々はCaffe)から取り出しました。

convの部分は、Rubyのループと、NArrayの行列計算が同居しています。遅いですがメモリをあまり食いません。
まだまだ改良の余地はありそうです。しかし、Pythonを使って計算したモデルを使っていますので「Ruby で Deep Learning」はできていませんね。