Skip to content

【Ruby】OpenAI Gymで遊ぶためのgemをつくった

29-8月-16

 夏休みなので、取り急ぎ作ってみました。
 ソースコード:https://github.com/kojix2/openai_gym

 OpenAI Gymとはイーロン・マスクらが率いる、人工知能(AI)を研究する非営利団体「OpenAI」が開設したAIシステムに、さまざまなゲームや課題を練習させることができる「ジム」です。人工知能開発のためのベンチマークとなることを目指して地道な取り組みが続いているようです。(内容はAtariゲームなどですが、こうやって人を集めて研究のインフラ基盤を作っていこうとする姿勢は本当に見習いたいと思います。)OpenAI GymはPythonで作られていますのでユーザーもPythonが中心です。GitHubを検索すると、Juliaのwrapperはありますが、Rubyのラッパーは見つかりませんでした。黙って待っていてもなかなか誰も作ってくれないでしょうから自分で手を動してみました。

 仕組みは単純で、open3で呼び出したPythonのプロセスのパイプを通してパックされた数字をPython←→Ruby間でやりとりしています。

 はじめてgemを公開してみたわけですが、IT業界ともデータサイエンスとも無縁な人が趣味と気合だけで作っていますので、変なところ、間違ってるところ、作りかけのところが多々あるかと思います。そういうところを見つけたら Pull Request 等して教えてくれると嬉しいですね。

 Numpyを使った機械学習なら、ちょっとした気合で大半のものがNumo::NArrayに直訳できると思われます。あとはRubyでもGPUを使った高速計算ができるようになればいいなと願っています。

朝三暮四じゃなくて朝令暮改だった

23-8月-16

前のエントリーで、RMSPropのコメントの「朝三暮四」は「朝令暮改」の間違いだった。
日本語能力のなさが露呈した。ところで、朝三暮四のサルたちは、強化学習的にはとても正しい行動をしているのではないか。
そんなことを思った。

それ以前にnumpyとnarrayのfloatのやりとりに完全に失敗しているけど、それでも何となく動いてしまうから人工知能すごい。

強化学習 + ニューラルネットワークがどうやって実社会に応用されていくのか考えがまとまらない。。
Policy gradient ってすごい。

強化学習:ピクセルから『ポン』 をRubyで書いてみた – 1

21-8月-16

強化学習について調べていたところ深層強化学習:ピクセルから『ポン』という面白い記事を見つけましたので、Rubyでやってみました。

4500回ぐらい学習させたところの動画。右側の緑が学習させたAI

まだまだ弱いです。。

Andrej karpathy さんの書いた元記事のPythonのコード (何と132行)を、Ruby/NArray にほぼ直訳しています。NArrayとはRubyでは最速の行列計算ライブラリです。
OpenAI Gym の Pong はPython製なので、Rubyとはパイプで通信することにしました。最初は自作の簡易ニューラルネットワークを流用しようと試みましたが、RMSProp や報酬の正規化などやらないと思うように学習してくれないことが判明したので、諦めて直訳しました。コード量はRubyの部分だけでも270行と膨大な量(100行以上のコードは膨大だという思想)になりましたが、理解のためにごちゃごちゃとコメントを入れたりPythonとの接続で増加した分がほとんどです。エンジニアじゃない人が適当に書いてるので間違ってる部分も多数残ってるかと思いますが、何となく学習できていそうなのでよしとします。

Python側のコードです。pong.py

次にRuby側のコードです。rl.rb

何時間も実行するとだんだんとメモリの使用量が増えていくので、どこかまずい部分があると思われます。

感想

・policy gradient は実装が簡単で素晴らしい。
・強化学習はディープラーニングを用いた分類器よりも奥が深い技術のような気がする。世間の人がいう「人工知能」はこっちに近い。
・強化学習はアルゴリズムが人間の哲学的な領域にまで踏み込んでくる怖さがどこかにある。
・人工知能じゃ実現できないなと思っていたようなことも案外実現できてしまいそうな気がする。
・ボールそのものよりも相手の動きをみてボールの位置を判定しているフシがあり、敵プレーヤーが代わっても実力を発揮できるか少し疑問。
・やはりRubyでも機械学習は可能なのだ。

RubyでシンプルなQ学習

13-8月-16

rl0rl2rl1qv

せっかくなので『機械学習と深層学習』を参考に簡単なQ学習を書いてみる。
hoge

プロットにはnumo/gnuplotを使用しました。

〜早熟なタイプ〜

rl0
早熟なタイプが一番多いけど、あまりグラフが凡例に被らないようにコイツにしました。

〜途中でぐんぐん成長するタイプ〜

rl2
見ていて気持ちがいいです。

〜彼の実力はまだ目覚めていないタイプ〜

rl1
俺達の戦いはこれからだ。

200000回ぐらい試行するとQ値もだいたいいい感じに収束するみたいですね。
qv

強化学習が哲学的すぎる

13-8月-16

教化学習の薄くて簡単な本を読んでいる。

イラストで学ぶ 人工知能概論 (KS情報科学専門書)機械学習と深層学習 ―C言語によるシミュレーション―

『イラストで学ぶ人工知能概論』は、サポートベクトルマシンとか、ニューラルネットワークのような流行の分類器には割と背を向けている本。人工知能を学ぶ一番のモチベーションは、老いも若きも分類器作ってデータかダウンロードしてきた学習済みモデル入れてイェイ……っていうことを考えると、一見するとフレンドリーに見えて、そうでもない本。

『機械学習と深層学習』は簡単なCNNのコードが載ってるというので買ってみたけれど、肝心の畳み込み層の重みはランダムで、重みの更新も実装されていない様子でがっかり。でも蟻コロニー最適化や、Q学習の書き方が載っていて興味深い。

それで、Q学習を眺めていると、なんだか哲学的な思考力のなさをずばずば追及されている気持ちになる。

というのは、Q学習の説明を読んでいるとすごく不完全な仕組みに不安と憤りを感じるけど、その気持ちをうまく説明できない。

「本当にやりたいことは別にあるけど、それを簡単なモデルに置き換えましたよ、どうよ?」
って、言われているような気持ち。

強化学習、こいつは、現実の世界と比較してはるかに不完全だ。

たとえば日本人が昔から大好きな文章に

 ゆく河の流れは絶えずして、しかももとの水にあらず。淀みに浮かぶうたかたは、かつ消えかつ結びて、久しくとどまりたるためしなし。世の中にある人とすみかと、またかくのごとし。

という平家物語の一節がある。日本人が考える世界が、この一文のなかに凝縮されている。もちろん現実の世界が本当にこういう風かわからない。でも神様が人間社会を眺めたら、きっとこんな風に見えるだろうと昔の日本人は考えた。世界を単純化しようとした。

ところが、Q学習は、この日本の伝統的な世界観と哲学を、何重もの意味で、バッサリと否定しているように感じる。
現実の世界をモデルに近似する段階で、「そこんところ別に大事じゃないから…」といって、切り捨ててしまう。

 ひとつは離散的なマルコフ連鎖に対する違和感だと思う。それから、同じ局面に何回も出会うというのは理想的な状況だが、現実の世界では再現性がなくて今まで一度も出会ったことがない状況でもある程度正しく対処しなければならない事が少なくない。ある状況を「同じ」だと認識することそのものが恣意的だ。。
 それから、Q値が高い方法を選ぶという単純化にも何か気に食わないものがある。Q値が高い選択肢が目前にあっても、突然トイレに行きたくなることもあるだろう。自分のいる場所は確率的にしかわからないとか、自分以外にもエージェントがいてとか、そういう事を考えていくと、どんどん複雑になっていく。

またQ学習のように物事を単純化することが、妥当で典型的な単純化と言えるのかどうか、直感的にはわからない。
でもそれは突き詰めると哲学的な問題につながっていく気がする。自由意志の問題とか。

もちろんQ学習の作者や利用者に言わせれば、Q学習は現実の世界を近似した哲学じゃないし、目的を達成するための一つの方法にすぎないということになるのでしょうが。

ずぶの素人が珍説で素直に偉大なアルゴリズムにケチをつけるというコンテンツは案外希少なので、つまらないことでも思ったことを正直に書いておく。

文系的な思考なら数式よりは簡単だと思っていたけど、哲学的なこともやっぱり難しい。難しいことだらけだ。


方策勾配

深層強化学習:ピクセルから『ポン』 – 前編

 この記事が面白かった。Q学習じゃなくて、方策学習(policy gradients)という手法が人気なんだって。ソースコードを読んでいないので詳しいことはわからないけれど、本文を読む限りは、
・勝利した場合は、ニューラルネットワークの重みをすべて足す(勝利したゲームの行動が強化される)
・失敗した場合は、ニューラルネットワークの重みを全て引く(敗北したゲームの行動が回避される)
というとてもシンプルな方法らしい。

 ということは多分 Ruby + NArray でも作れる。ニューラルネットに関する部分は。

 記事に添付されているソースコードを実行してみたら、CPU4コア使って日単位の時間がかかりそう。ということはRuby/NArrayではさらに時間がかかる。収束を早めるための何らかの工夫が必要か。球を取りこぼしたタイミングで敗北しているだろうから、敗北の10フェーズぐらい前までの行動を厳しめに減点するとかそういう方法が有効そう。

 Pongゲームについては、OpenAI Gymというツールキットを使っているようで、これもPython製。うーん。PythonとRubyをなんかの方法で接続すれば不可能ではない気がするけど。。

【Ruby】救急外来で使えそうな診断ツールを作ってみた記録

07-8月-16

救急外来で使えそうな疾患診断支援ツールを作ってみた

bayes0diagnosisbayes1graph1graph2


 医療 × Ruby × Tk × 人工知能(単純ベイズ分類器)ネタです。数年前に臨床研修をしていた時の話です。臨床研修の記憶が残っているうちに書き残していこうと思います。(実際にはそれほど使えるわけではない)

病気の診断のプロセスを考えてみる

 単純化して考えます。

① 主訴をとる

② 鑑別疾患と頻度を考える

③ 診察・検査をする

⑤ 各疾患の可能性を検討する

⑥ 最も可能性が高いものを選ぶ

上記のようなプロセスを部分的にでも模倣すれば、診断支援ツールが作れるものとします。

ツールを作ろうと思ったきっかけ

 『UCSFに学ぶできる内科医への近道』という本の第2版に、夜間当直の研修医が、腹痛の患者さんを診察する小話が載っています。

 私は現在この本を持ってないので記憶を頼りに書くしかないのですが、主人公の研修医は、腹痛の患者が虫垂炎であるかどうか悩み、所見から虫垂炎である確率を計算していきます。オッズに陽性尤度比を掛けあわせていき、夜間に虫垂炎の可能性が50%を超えため、「虫垂炎である」と判断して外科の先生をコールします。
 何が起こるか予測できない緊張感のある当直中に、資料に当たりながら悠長に確率計算をするというエピソードは、すこし現場の光景からかけ離れているように感じます。しかし研修医が外科の先生を呼ぶかどうか迷うことは、しばしば経験するケースではないでしょうか。

UCSFに学ぶ できる内科医への近道
3版

 このエピソードを読んで、私は次のように思いました。「所見ごとに尤度比を掛けあわせれば疾患の確率が計算できるんだ。」「それならば、検査所見ごとに、事前確率、陽性尤度比・陰性尤度比をあらかじめ登録すれば、疾患を自動診断できるソフトが作れるんじゃないか?」「どうしてこんな簡単なことを誰もやらないのだろう?」

その時は良い思いつきだと思いました。

 実はこのエピソードは、『UCSFに学ぶ出来る内科医への近道』第3版から丸ごと削除されています。確率の掛け算には落とし穴があります。確率を掛け合わせることができるのは、それそれの検査項目が互いに独立な場合のみです。ほとんどのケースではそうでないので、確率を掛け合わせることはできません。(有名なレジデントマニュアルでもこのように怪しい記述があるのですから、個人のブログに間違いが沢山書いてあっても許容されるべきだと思っています。)

感度・特異度の資料

 次に、感度・特異度・陽性尤度比・陰性尤度比の情報が掲載されている資料を探しました。下記の本に、いくつかの疾患について情報が載っていましたのでこれを採用しました。

JAMA版 論理的診察の技術

bayes0

 この本に、「互いに独立ではない検査項目を掛けあわせてはならない」と注意書きがしてあったので、ようやく私は作ろうとしているツールの限界に気が付きました。
kakeawase

 しかし、擬似確率であっても、このようなツールを作ることには意義がある気がしたので作業を続けました。

プログラミング言語、GUIツールキット

 iPhone用のアプリを作りたかったのでobjective-Cを勉強していましたが、結局は初心者でも書きやすいと感じたプログラミング言語Rubyに入門しました。今だったらPythonに入門していたかも知れません。
 GUIツールは、Ruby/Tk を選びました。グラフ表示はRuby/Tkの拡張ライブラリであるPlotchartを試用しました。ナイーブベイズのアルゴリズムは自分で書きました。

鑑別疾患を表示する

 鑑別疾患とは、症状から推測される病気のリストのことです。現場ではリストそのものよりも、「正しい主訴を選択する」ことが大切であると言われています。
diagnosis

レジデント初期研修用資料 内科診療ヒントブック 改訂2版
鑑別疾患リストは、実用性に優れたmedtoolz先生のマニュアル本から使用させて頂きました。

単純ベイズ分類器で確率を計算する

 このように、項目事の独立性を仮定して、ベイズの定理を適応する分類アルゴリズムを「ナイーブベイズ分類器」と呼びますが、このことは、あとから知りました。順序が逆だと思われるかも知れませんが、「感度・特異度」は国家試験の必須項目なのでみな学びますが、「単純ベイズ分類器」というものはどちらかと言えばプログラミングの世界の言葉なので、そういう概念を知っている人は少ないのです。
bayes1
↑虫垂炎について、ナイーブベイズで確率計算させているところ。

多クラス分類

 このソフトを友人に見せたところ、「すべての疾患について確率を計算して、最も確率が高いものを選べば、自動診断ソフトが作れるのではないか」という意見をいただきました。なるほど、これは凄いアイディアだ。と思いましたが、実際には使える資料が少なすぎて全く実現しませんでした。

実際に使ってみてわかったこと

 鑑別診断の表示、疾患の感度・特異度・陽性尤度比・陰性尤度比のブラウザは、研修医レベルなら現場でも十分に実用性があるということがわかりました。

graph2graph1


心不全の、陽性尤度比・陰性尤度比を表示したところ

 一方で、計算機能は、現場ではほとんど役に立たないことがわかりました。その最大の原因は、機械に一つ一つデータをインプットすることが煩雑で実用性に欠けることです。少なくとも計算機能を使用することで、新たに救える人命はないと思います。

 そのほか単純なケースではありますが、非IT分野に身を置く素人でも、Rubyのような(少なくとも入門は)簡単なプログラミング言語を用いることで今よりも少し深くITを活用できる可能性があるということを認識するきっかけになりました。(もちろんIT導入にともなう様々なリスクもあります。)

このツールと臨床現場の思考には大きな溝がある

 言うまでもないことですが、医師に限らず実際のスタッフの思考回路は、この種のソフトとは、さまざまな面で全く異なる動きをしていると感じられます。これについては、多岐にわたることであり、まったく勉強・経験が足らず、頭の整理が追いついていないと感じています。
医者は現場でどう考えるか

ツールについて

 このツールは、「もしもこのようなツールがあったら、何を考えるか」を調べる個人的な目的で作られました。正常に動作しているところもありますが、少なくない機能がヴェーパーウェアの段階です。ソースコードは素人が書いてるものにしても雑な部類に入るので公開するつもりはありません。
 気づいた方もいらっしゃるかも知れませんが、GUIはMacの作業自動化ソフトautomatorをそっくり参考にしました。

automator_2x

最後に

 IBMワトソンが診断を行ったというニュースを読んで、このエントリーを書いてみました。もちろん、このようなポンコツ診断ツールと、IBMの看板である最新鋭の診断支援システムは1から100まで異なるものです。しかし、これから技術がどのような劇的な進歩を遂げようとも、医療の本質はあまり変化しないのではないかという気がします。
 けれども、私達は面白い時代に生きているようですから、無理のない範囲で時代の波を追いかけてみたいと願っています。

AIと医用画像と死

03-8月-16

 世間もそろそろ、AIによる医用画像の診断で、医師以上の性能をあげるのは簡単だということに気づいてきたようだ。

 ところが、医療従事者に対する月給は必ずしも医療”技術”に対して生じているわけではない、という事はあまり気づかれていない。AIなどに携わる理系の技術者ほど、そういうことに気が付きにくいのではないか。医療”技術”はペイしない、とまで言ったら言い過ぎかも知れないが、それに近いものがある。

 このことについて理屈でアレコレ説明することで頭で理解することもできるけど、結局、医療のさまざまな問題を理解するには「死」についてのある程度の心の修練が必要なので難しいのではないかという気がする。

 例えば、現在の医療であろうと、200年前の江戸時代の医療であろうと、2000年前のエジプトの医療であろうと、死に注目にすればほとんど違いがないことがわかる。医療技術の進歩とは関係ない世界がそこにある。しかし、このことを頭で理解するのと、実際に死に触れながら理解するのは異なる。なぜなら現実の死は思考を拒否させるからである。

 人間は放っておけば死について考えないように心がプログラムされているようだ。死が近づくまで、そういった問題を考えることなく一生過ごす人も少なくない。だからこそ、宗教や伝統行事など、普段は死から縁遠い人たちにも死について考えさせる社会的な仕組みがあるのだろうと思う。

 日常的に死の気配を嗅ぎ、死と触れあうことで、死についての思考を余儀なくさせられるということ。死は家族や医療従事者の苦痛でもあるが天佑でもあるように思う。

 でも、心の修練が必要なのは医療に限らずどの分野でも同じで、領域ごとの特殊な心のあり方、心の鍛錬というものがあって、シンプルであっても、他の領域の人には見えそうで見えない世界というのが無数に広がっているのだろう。そう考えると、少しやさしい気持ちになれる気がする。

落書き IRuby Notebook で任天堂の株価のグラフを描く

28-7月-16

nintendo描いてみる。

↓の処理が結構時間がかかるので注意です

Daru::DataFrame:70234904795780 rows: 10 cols: 6
opening high low finish turnover date
0 16035 16070 15335 15395 772400 2016-04-01
1 15260 15730 15180 15370 531500 2016-04-04
2 15300 15455 14990 15020 569700 2016-04-05
3 15010 15240 14825 15095 535500 2016-04-06
4 14990 15540 14955 15530 673800 2016-04-07
5 15250 16000 15205 15795 935400 2016-04-08
6 15790 15890 15450 15855 490300 2016-04-11
7 15925 16350 15870 16325 575000 2016-04-12
8 16500 16595 16170 16215 618400 2016-04-13
9 16780 17150 16685 16875 1123900 2016-04-14

時系列グラフの作成は、チュートリアルに忠実にGnuplotrbを使うことにします。

nintendo

落書き IRuby Notebook で都道府県の人口を棒グラフで表示する

28-7月-16

fig1IRuby Notebook + Daru + Nyaplot を使いこなすための練習です。
人口上位20都道府県の人口を表示します。データのソースはWikipedia:都道府県の人口一覧

Daru::DataFrame:69874443099120 rows: 21 cols: 7
順位 都道府県 団体コード 法定人口 推計人口 増減率 年月日
0 1 東京都 13000-1 13159388 13613660 3.45 2016-6-1
1 2 神奈川県 14000-7 9048331 9146101 1.08 2016-6-1
2 3 大阪府 27000-8 8865245 8838988 -0.3 2016-6-1
3 4 愛知県 23000-6 7410719 7501909 1.23 2016-6-1
4 5 埼玉県 11000-1 7194556 7277247 1.15 2016-6-1
5 6 千葉県 12000-6 6216289 6238589 0.36 2016-6-1
6 7 兵庫県 28000-3 5588133 5526538 -1.1 2016-6-1
7 8 北海道 01000-6 5506419 5381711 -2.26 2016-6-30
8 9 福岡県 40000-9 5071968 5104919 0.65 2016-6-1
9 10 静岡県 22000-1 3765007 3689418 -2.01 2016-7-1
10 11 茨城県 08000-4 2969770 2909196 -2.04 2016-6-1
11 12 広島県 34000-6 2860750 2822448 -1.34 2016-6-1
12 13 京都府 26000-2 2636092 2607108 -1.1 2016-6-1
13 14 宮城県 04000-2 2348165 2330528 -0.75 2016-6-1
14 15 新潟県 15000-2 2374450 2290569 -3.53 2016-6-1
15 16 長野県 20000-0 2152449 2088105 -2.99 2016-6-1
16 17 岐阜県 21000-5 2080773 2024859 -2.69 2016-6-1
17 18 栃木県 09000-0 2007683 1969056 -1.92 2016-6-1
18 19 群馬県 10000-5 2008068 1967635 -2.01 2016-6-1
19 20 福島県 07000-9 2029064 1903174 -6.2 2016-6-1
20 21 岡山県 33000-1 1945276 1917299 -1.44 2016-6-1

fig1

東京の人口がそれほどでもない気がするけど、昼間は他県から集まってきてる。

IRuby Notebook でクラスや関数のドキュメントを表示する

28-7月-16

IRuby Notebook でコマンドの内容を調べたい時は、ri を使うことができる。
例えば Daru::DataFrame.from_csv を調べたい時は

と記入すればいい。便利。なぜか手元の環境だと1回目は動かず、2回目から表示される。

ri