Skip to content

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

20-10月-16

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

ページをめくってみた。すごい。勉強になる。数式読めない人けど、なんとなく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を試してみた

16-10月-16

はじめての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ほどの活気はなく、なんだか閑散としていてほんの少し寂しい気持ちになったのでした。

サンフランシスコにEnliticという医療画像認識スタートアップがあるらしい

16-10月-16

 レントゲン、CTといった医療画像の読影で、近い将来ディープラーニングが一般臨床医の診断精度を超えるのはもはや動かしようのない事実だと思う。

 日本だときっと富士フィルムや横河電機、元東芝メディカル、オリンパスなどがどこかで開発しているのだろう。(このなかで富士フィルムは本気を感じるが、個人的には富士フィルムの作る個別のソフトにそこまで好印象を持っているわけではない。)ではこれをビジネスにしている組織はあるのだろうかと思ったら、アメリカにはすでにあった。サンフランシスコのEnliticという会社だ。

 このエントリーは下記日経BPムックの「ディープラーニングの検出率は人間よりう上、スタートアップの米Enlitic」という記事をベースに書かれました。

以下引用。

 レントゲン写真やCTスキャンから悪性腫瘍を見つけ出す画像認識ソフトはディープラーニングの手法の一つである「Convolutional Neural Network」を採用して開発した。人間の放射線医師が悪性腫瘍の有無や場所などをチェックした大量の医療画像データをConvNetが機械学習し、悪性腫瘍の形状などを表す「特徴」や、どの特徴を重視すれば悪性腫瘍の有無が判断できるかといった「パターン」を自動的に見つけ出す。

 やっぱりCNNを使って画像を読影しているようだ。

 Enliticによれば同社が開発した悪性腫瘍の検出システムは、放射線医師を上回る精度だという。Enliticが肺がんに関する画像データベース「LIDC(Lung Image Database Consortium)」や「NLST(National Lung Screening Trial)」を用いて検証したところ、同社のシステムの肺がんの検出の精度は、放射線医師が1人だけで肺がんを検出する精度を5割以上も上回ったとする。

 すでに公開されている医療データセットがいくつかあるらしい。どのようなものがあるか今度調べてみよう。誰かリストアップしてくれてないかな。

 同社は悪性腫瘍の検出システムを放射線医師向けに提供する。米国では医療画像診断サービス会社や医療機関が放射線医師を雇用しているので、そうした起業や機関が顧客となる。

 顧客は医療機関ではなく「医療画像診断サービス会社」になっているようだ。これは地味に重要なポイントだと思う。日本では小規模の診療所を除いて、医療画像診断サービス会社を利用するのは一般的ではないと思う。しかし血液検査や病理診断などではSRLなど外部の会社に委託することは広く行われている。このような民間企業に医療情報が蓄積されて、そこでは比較的自由にディープラーニングの開発などが進められているということなのだろう。
 そういったサービスが普及しても、放射線科医の仕事はなくならないだろうが、その業務内容は大きく変貌していくと予想される。

 なぜKaggleなのか。実はEnliticの創業者であるJeremy Howard CEO(最高経営責任者)は、KaggleのPresident兼Chief Scientistでもあった。つまりEnliticはKaggleによって優れたデータサイエンティストを見つけられることがわかったHoward氏が、データサイエンティストを活用して新しいビジネスを始めるために設立した会社でもあったのだ。

 EnliticはKaggleでデータサイエンティストを採用しており、医療経験があるメンバーはほとんどいないという。そしてEnliticの創業者はKaggleのPresidentで、Kaggleで優れたデータサイエンティストを集めて起業したということらしい。記事にはデータサイエンティストのことだけ書いてあるが、おそらく優れた医療データを供給してくれる有力企業もKaggleで見つけたのだろう。

 個人的に思ったことはたくさんありますが、頭の整理がついていかないし、私が考えていることも本当に正しいかどうかわからないから、あまり書きすぎないようにします。

Amazon EC2 試してみた

13-10月-16

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

犬がかわいい

04-10月-16

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

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

※ Deep Learning はできていません

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

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

25-9月-16

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

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

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

23-9月-16

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

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

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

落書き Neural network visualization with Ruby

12-9月-16

よくある重みの途中経過とか見せるやつ。Numo::NArray + dRuby + Ruby/Tk
作り途中もいいところだけど、それなりに動いってるっぽい。
nn_visalization

人間と社会環境の相互作用としての病気

06-9月-16

 以下、与太話が延々と続くので真面目な人はあまり真に受けないでほしいです。

 強化学習をやっていてふと考えた。病気とは何だろう。

 病気とは何か。そこにはいろいろな視点がある。例えば「正常であるものと正常でないものの境界は人間が決めるから、健康と病気も人間が決める」という考え方がある。なるほど、そう思う時もある。

 「未だかつて存在せず、これからも決して存在しないが、成立してもおかしくなかった病気。」というのがある。これは何かというと、人類には潜在的にそのような病気にかかるのに十分な構造があるけれども、その病気は頻度として極めて稀であるため、結果的に人類の誕生から滅亡まで、誰1人その病気に罹患しなかった(だからこの病気は存在しない)。というものである。この「存在しない病気」を私ちが知ることはないけれども、きっと存在する。ではこの存在しない状態は「病気」と言えるのだろうか?
 そこまで抽象的じゃなくて、ある病気と別の病気、あるいは健康と病気の境界のグレーゾーンについて考えてみる。病態をいくつに分割するかは、虹の色をいくつに分割するかと同じで恣意的なものだ。時代が新しくなるとともに、それまで一つの症候群としてまとまっていた病態が、複数の病気へと分類されていく。私は病気の分類の複雑さは、その病気が本来持つ性質ではなく、人間が今まで経験した症例数と比例しているのではないかと疑っている。人間分類器は似たような状態を一定数経験すると、それを新たに分類したがる性質を持っているからだ。けれども、あまりそういう話は聞いたことがない。やっぱり病気は病気で、最初から存在する、という考え方の方が人気がある。

 「果たしてチンパンジーは病気なのか?」という疑問を考えたことはあるだろうか。これは結構難しい問題で、チンパンジーを人間の病院で検査すれば多くの異常が発見されるだろう。健康診断なら間違いなく赤点だ。しかし、人間の標準からかけ離れているからといって、チンパンジーを「先天的な遺伝子疾患」であると見なすのは、あまりにも可哀想じゃないですか? チンパンジーが人間の病院でいくら病気の診断をもらっても、森林では元気に生活することができる。チンパンジーという状態は森林という環境によく適合しているのである。とすると環境に適合していることを「健康」と言ってよいのだろうか? それも、少し違う気がする。

 ここで、最初の話題に立ち返えろう。病気とは何だろうか。

 結論からいうと、現代社会で問題となっている「病気」は、病気が単独で存在しているのではなく、環境の変化に起因するものが少なくないのではないかと感じる。もう少し丁寧に書くと、太古の時代の環境に最適化されている人間の身体が、現在の環境に対応できていない状態のことを私たちは「病気」として認識しているのではないだろうか。(もちろん全ての病気が…というわけではなくて、現代社会でメジャーな病気が…という意味です。私達は何万世代とチューニングされているのですから、現代においてなお残っている「病気」の意味を考える必要があります。)

 例えば「糖尿病」は飢餓と低血糖に苦しんでいた人類が、飽食の時代に対応できずにいる状態とみることができるかもしれない。長い年月を慢性的な飢餓と低血糖に悩まされていた人類は、高血糖に対応して血糖値を下げるホルモンを1種類しか用意していなかった。そこで現在のような飽食の時代になって高血糖の状態が当たり前になると、簡単に不具合が発生してしまう。人類はインスリンを注射で補充するようになった。食欲も適度に抑えられ、結果的に肥満にならない人が健康的だと見なされるようになった。しかし、これは「飢餓はもう問題ではない」という社会環境が前提にあってはじめて成立する疾患ではないだろうか。

 誤解を恐れずに書くと、やはり糖尿病であることは生存に不利である。だから長い年月の後には糖尿病の人は少しずつ減少していくだろう。それは見方を変えれば、人々の飢餓に対する適応力が失われていくことにもつながるのではないだろうか。そうすると、一体どちらの状態が「健康」なのだろうか。飢饉に強い性質か? それとも飽食に強い性質か? その答えは人間だけ見ていても決まらず、社会環境によって左右される。つまり病気が独立して存在しているのではなく、社会との相互関係のなかで病気の範囲が定義されいる、ということにならないだろうか。

 心筋梗塞や脳梗塞など、動脈硬化と血栓に起因する病気には、血液をサラサラにする抗凝固療法が行われている。血液をサラサラにする薬を飲むことで血液が固まって血管が詰まることを防いでいる。ところが、血液がサラサラにして血を止まりにくいということは、怪我などで出血した際にも血が止まりにくくなるということを意味する。狩猟採集の時代には、恐らく現代とは比較にならないほど怪我が多かっただろう。そのような環境では出血が止まりにくいということは、それだけで生存に不利になると推測される。つまり「怪我による出血はもはや問題ではない」という社会環境のあって、はじめて血液ドロドロという性質が是正されるべき「不健康」な状態として立ちはだかるようになったと考えられるかも知れない。

 人は不老不死を求めてきたけれども、老化に介入する有効な手段は未だにみつからない。そういう意味では、現在行われている治療は、乱暴にまとめればすべて「延命治療」と言えなくもない。そこで私達は何をしているかと言えば、太古の時代に最適化され、新しい環境についていけない生体の性質を、薬剤を投与することで、より生存に有利な方向、あるいは勾配に傾けているのである。そうすることで生体をより現代環境に適した状態に変えて、結果として寿命を伸ばしているのである。そしてその生存に有利な方向・性質というものは、必ずしも人間の身体単体だけで決まる独立した定数ではなく、身体をとりまく社会環境によって大きく変化しうるものらしい。つまり、病気や疾患とは、私達が思っている以上に社会環境に依存する存在であり、環境と人間との相互作用の中に立ち現れてくるものだということになる。おまけに現代社会では社会保障制度が発達して、どの程度まで生体の性質を変化させられるかは、投入できる社会的な医療資源の量にも大きく左右されるようになった。

だとすると病気を治療するとは本当はどういうことなのだろう?

 強化学習を眺めていて、ふと、そんなことを考えた。なんだかもう予想以上に風呂敷を広げすぎたようで、頭が痛くなってきたのでこのへんで。

落書き Ruby/Tkでリアルタイムプロット

05-9月-16

使うもの
・Ruby/Tk + Plotchart
・dRuby

Ruby/Tk はThreadとの相性が非常に悪く、非同期処理やメインループを2つ回すような作業をやろうとすると上手くいかないことが多いです。
そこで真ん中にdRubyサーバーを挟みます。これで大抵の処理はRuby/Tkでリアルタイムに表示することができます。

drb.rb

env.rb

plot.rb

あとはdrb.rb、env.rb、plot.rbの順番に実行します。
終了するときはゾンビプロセスを残さないように気をつけます。

学習中や、順伝播中のニューラルネットワークの重みを表示するみたいなよくあるネタをやってみようかしらん。でもそれだけじゃあまりにも面白くないからもうひと工夫したいところ。。