ディープラーニングの大流行の中、様々なフレームワークが登場し、気軽にプログラミングができるようになりました。しかし、そんな中どのフレームワークを選べば良いかわからないという人も多いと思います。そんな人に少しでも参考になればと思い記事を書きます。
はじめに
この記事に来る方が結構多いみたいなので、あれこれ分けずに情報を集約しておきます。
もともとはChainerとKeras、TensorFlowの記事でしたがPyTorchも追加しておきました。
Chainer
特徴
柔軟な計算グラフの構築が可能
Define by Runによって柔軟な計算グラフの構築が可能であることが、最も大きな特徴です。Chainerを皮切りに、この方式に則ったフレームワークも登場してきています(dynetやpytorch)。
実際、Define by Runでなければ上手く扱うことのできないような計算グラフも存在し、特に入力に応じて計算グラフの変更が必要であることの多い自然言語処理の分野では重宝されている印象です。
Pythonによる実装
ChainerのコードはPythonによって実装されている点も特徴的です。従って、計算グラフの構築にしても、学習のコードにしても、Pythonでの処理を好きなように用いることができる点が魅力的です。Pythonを使い慣れている人にとっては最も扱いやすいように思いますし、逆にPythonの勉強にもなるという印象です。
Pythonはインタプリタによって動作する言語であるため、C言語のようなコンパイラを通す言語に比べて低速になります(一方で気軽にテストが行えたりするメリットもある)。
Chainer自体はPythonの実装といえど、ニューラルネットの大部分を占める行列計算の処理はnumpy(C言語での実装)によって行われるため、全体としては高速な動作を可能にしています。
GPUを用いる場合は、numpyのように扱うことのできるcupyを使うことになります。現在、完璧ではないにしても、基本的な計算処理はnumpyをcupyに置き換えるだけで実装できます。また、cupyが独立したこともあり、Chainerとは別でcupyが使われるケースも出てきています。
ともかく計算処理は高速化されているため、TensorFlowに比べてやけに遅いなどということはありません。
直感的な計算グラフの構築が可能
ChainerはPythonによって実装されているフレームワークです。クラスとメソッドを使うオブジェクト指向という考え方は、プログラミングを良くするために考案された手法であり、実際、かなりプログラミングを容易にします。
Chainerでの計算グラフの構築は、Chainerで実装されているクラスを継承することで簡単かつ直感的に記述することができます。プログラムの中身を完全に理解しなくとも、どのようなクラスがどのようなメソッドを持ち、どのような働きをするのかを把握しておきさえすれば良いという感じです。
既存のクラスを継承してオリジナルな層を作ることも可能ですので、そういう必要が出た時に更に詳しく勉強するという形でも大丈夫だと思います(とにかく試してみる!という分にはほとんど苦労しないはず)。
メリット・デメリット
メリット
上記の特徴から、Chainerのメリット羅列します。
- 直感的な計算グラフの構築
- デバッグが比較的行い易い
- Pythonの勉強にもなる
- (なんとなく日本の活躍を応援できる気がする)
端的に言えば、プロトタイプの設計をサッと行い、サッと実験したい場合有効だと思われます。簡単な計算グラフから複雑なものまで、幅広く扱うことができるにも関わらず、実装の負担は少なめである印象です。
デメリット
- 計算速度が遅くなりがち
- アップデートについていけるか不安
- 利用人口が少ない
やはりPythonをインタプリタで動かすことになるので、コードによっては速度は落ちるかと思います。以下にPythonでの処理を少なくするかという点になります。
また後方互換性が無くなるようなアップデートも見られるため、注意が必要です。アップデートの頻度も高いため、必要性に駆られない限りは、やたらめったら最新のものにする必要は無いかもしれません。利用人口は質問に回答できる人間に関わってきます。。
まとめ
軽く使ってみたい初心者にとっても優しいフレームワークです。また、複雑な計算グラフにも対応できる点で、新規のネットワークを構築したい研究者にとっても有用だと考えられます。
ただし、実業務に使うという点においては、アップデートの状況や利用人口を考えると不利かもしれません。1つのコードの利用期間が短い場合は良いのですが、長期間使う場合には問題が多いでしょう。コードの規模が膨れ上がり、アップデートに対応できず、更に利用人口の問題で改修も難しいということが起こるかもしれません。
Keras
特徴
とんでもなく簡単に計算グラフを記述可能
層をただただ積み重ねていくだけという、とんでもなく簡単な実装が可能です。Kerasの登場により、ディープラーニング入門は誰にでもできるという状況が訪れました。
高速計算ライブラリのディープラーニング用ラッパー
Kerasは「Theano」や「TensorFlow」のようなテンソルを高速計算するライブラリのラッパーとして登場しました。記述を簡便化するのが役割であるため、簡単に計算グラフを構築できるという点は当たり前と言えば当たり前です。
計算グラフの構築が簡単なだけでなく、学習のコードも、学習回数などの条件を引数にたった一行で実装できてしまいます。
もはやプログラミングの経験すら不要
ディープラーニングを始めようというときにはプログラミングの壁が大きく立ちはだかります。しかし、Kerasの場合はプログラミングが未経験でも、(恐らく)すぐに簡単なネットワークの学習は可能になるでしょう。
それほどまでに計算処理のプログラムが隠蔽されています。「どのような層を配置して、どれくらいの数どのように学習をするか」くらい意識しておけば十分といった具合です。
メリット・デメリット
メリット
- コードを書くのがとっても簡単
- プログラミング未経験でも恐らく大丈夫
- 利用者も多い
最も初心者に優しいのはKerasで間違いないです。
デメリット
- 処理の中身はコードからは全く分からない
- オリジナルの処理をさせるのが面倒
- 計算グラフ構築後、変更不可能
コードの簡便さと表裏一体ではありますが、コードだけからは処理の中身を知ることはできません。従って、Kerasを使っていても、ディープラーニングそれ自体の理解には繋がりにくいように思います。無論、理解をしたければ一度、numpyなどで自身で簡単なものを書いてみるのが一番です。
また、オリジナルの処理をさせたい場合には、それを可能にする関数なども用意されてはいるものの、最初からTheanoやTensorFlowで書くのが早いと感じるでしょう。
まとめ
初心者には一番おすすめです。
また、研究では、まだネットワークの基本的な構造すら決まっていないようなときに、細かいチューニングはせずに数打って試したい場合に有効です。ある程度使うネットワークの構造が決まってきたならば、細かいチューニングや処理の追加、評価の方法の変更に備えて、TensorFlowに移行するというのが良いかもしれません。
一言で言えば、簡単なネットワークを試す場合に有効だということでしょう。
完全に独自のネットワークをKerasで書こうと思うと、かえって面倒が増えることになります。 とはいっても、完全に独自のものを考えなければいけないケースって、そんなに多くないと思います。実用上Kerasで多くのことが済むでしょう。次に説明するTensorFlowをバックエンドに使う方法が最も人気だと思われます。
TensorFlow
特徴
圧倒的な利用者数
Googleが実際にプロダクトを生む際に利用しているということで、爆発的に利用者が増えました。間違いなく世界一利用者の多いディープラーニングのフレームワークでしょう。
テンソル計算を行うライブラリ
もともとはディープラーニングに限らず、テンソル計算を行うためのライブラリとして生まれてきています。従って、基本的な計算処理の記述も可能であり、ディープラーニングのフレームワークとして考えるならば、最も細かい調整ができると言えるでしょう。
実装はC++で行われており、計算も高速に行われます。とは言っても、numpyもCで実装されており、高速処理が可能です。TensorFlowはnumpyのような高速計算処理を可能にしつつ、ニューラルネットを取り扱うことを意識した計算ライブラリだと考えるのがいいかもしれません。恐らく、このソフトウェアとしての設計はGoogleが抱えるハード技術であるTPUに最適化されているものと思われます(単なる想像だけども)。
Define and Run
計算処理を計算グラフとして一度構築し、その後、まとめて計算処理をさせるのがDefine and Runです。TensorFlowは基本的に全ての計算処理を、計算グラフによって記述します。どんな簡単な計算でもです(例えば単なる足し算でも)。
何か普通の処理をさせたいという場合にも、必ず計算グラフで考える必要があり、ある種の慣れが必要であるとも言えるでしょう。
TensorFlowの能力を最大限引き出すためには、以下にPythonの世界に戻ってこないかです。出来ることならば、すべてをTensorFlowの計算グラフにしてしまい、あとは計算グラフを実行するだけというのが理想です(学習をfor文でfeed_dictに渡すような処理もしない方が良い)。
追加のライブラリが豊富
高速計算を可能にするライブラリというのが、TensorFlowの基本的な姿ですが、やはりニューラルネットに特化した関数が多数準備されています。
また利用者数が多いため、TensorFlowのラッパーや、TensorFlowと同時に使えることを意識したライブラリも存在しており、多方面での支援が得られるという印象です。例えば今回紹介しているKerasも、TensorFlowのラッパーというポジションです。最近ではDeepmind(Googleの子会社)から、Sonnetというライブラリも登場しています。
他にも確率的プログラミングとして期待されるEdwardや、音声認識システムkaldiを統合するなど、機械学習を代表とした数値計算ライブラリとしての代表的OSSになったと言っていいでしょう。
メリット・デメリット
メリット
- 利用者数が多く、コミュニティが大きい
- 低レベルの処理も可能
- GPUの利用も簡単
ITの分野はスタンダードが多数決で決まることが多いです。利用者が多いと、それを支援する人が増え、雪だるま式に発展していきます。そのような観点からすればTensorFlowは最も発展の可能性が高いと言えるでしょう。実質、ほぼ機械学習ライブラリとしてのデファクトスタンダードになっていると考えて良いと思われます。
特にプロダクトという領域をここまでサポートしているフレームワークはTensorFlowほぼ一択になると思われます(最近、いろいろライブラリ間を埋める中間フォーマットも出てきたが)。
また、高速計算のためのライブラリであるため低階層の処理も、計算グラフを構築しさえすれば何でも行わせることができます(バッチを取り出して流すという計算グラフをTensorFlow内に作っても良いんです)。GPUの利用に関しても、データ構造として直接的にユーザーが操作しなければならないシーンは基本的にはありません。
デメリット
- 計算グラフ構築後の変更が不可能
- 今回紹介した中で一番とっつきづらい。(慣れが必要)
やはり計算グラフの構築後、変更ができない点はデメリットです。一旦構築したものを変更しないため、コンパイルをすることで計算を高速に動作させられることが期待できますが、なんか速度面は他のフレームワークもかなり頑張っているせいで、デメリットが大きく目立っています。
実際、ニューラルネットを学習させる際に、ニューラルネットの外であれこれ処理をやる必要がある場合には、単にPythonで動作するChainerやPytorchの方が便利ですし、その処理結果次第でニューラルネットの構造を変更する必要がある場合は、事実上TensorFlowではそれが不可能です。
これに対しては対応作としてライブラリが追加開発されていますが、利用の話はあまり聞きません。
また、全ての計算を計算グラフで表現することは、初心者にとっては取っ付きづらさの元になっています。高レベルAPIではかなり直感的にニューラルネットワークを構築できますが、TensorFlowをマニュアルに使いこなそうとすると、おそらく一番勉強コストが掛かるのではないかと感じます(そもそもニューラルネットだけでなく、機械学習や数値計算全てをカバーしているのだから当たり前だが)。
まとめ
計算グラフの変更が学習の途中で必要ない場合には、最も有利なのはTensorFlowでしょう。TensorFlowの世界で細かい計算の調整も可能ですし、コミュニティが大きいため、疑問の解決も比較的早く済ませることができます。最新の研究がTensorFlowで実装されることも多く、新しい物をすぐに試したい場合には嬉しいことでしょう。
tf.layers
tf.keras (1.4から正式追加かな?)
などの高レベルAPIを使えば、全く小難しいことせずともニューラルネットのワークの設計ができます。Googleという巨大企業が支えているため、クラウドサービスであったり、ラズベリーパイを支援したりなど、実務への転用も今後行いやすいように整備されていくかと思われます(実際、かなり実用レベルまで意識されるようになりましたね)。
PyTorch
特徴
Define by Run
chainer.VariableをフォークしたDefine by Runを採用しています。コードの書き方もチュートリアルレベルではChainerに酷似しており、ChainerからPyTorchあるいはその逆の移動はかなり容易と思われます。
コミュニティが拡大中
Define by Runのフレームワークとしては最も広く知れ渡る結果となりました。もはやディープラーニングフレームワークはPyTorchかTensorFlowか!?というくらいの盛り上がりを見せています(実際のところ、圧倒的にTensorFlowの方が人口多いと思われますが)。
とりあえず、いろいろ場面で比較や検証が出てくるくらいに盛り上がっているフレームワークであるということです。
結果として、最新の論文の実装であったりTensorFlowで実装されていたネットワークであったりが、迅速にPyTorchでも出てくるようになりました。
こちらは巨大企業であるFaceBookが本腰になっているフレームワークであります(きっと2大インターネット広告企業であるG社とF社が使うフレームワークだからこその盛り上がりでしょう)。
ドキュメントがしっかりしているだけでなく、3rdPartyによるTutorialも非常に豊富。
メリット・デメリット
メリット
- Define by Runである
- 利用者のコミュニティも拡大傾向
- 研究での利用例も増えてきている
- Chainerのメリットのほとんどを有する
結局コードはいろいろ読んで書いて勉強していくことになると思われますが、コミュニティが大きければそのチャンスは沢山あるというわけです。探せばいろいろなコードを好きなだけ探すことができます。また、Pythonで出来る処理をネットワークの途中に入れられるというのは、PyTorchもChainerと同様になります。
デメリット
- 日本語での文献は極めて少ない(blogやqiita)
- まだまだプリミティブなコードも書く必要がある(chainerでのTrainerみたいなのはまだ)
- 研究用途であると宣言されている
最後はデメリットというか分かりませんが、PyTorchのコードで直接何かがすぐに動くようになるということはサポートされないかもしれません。FaceBookではPyTorchを研究用途に、Caffe2を製品開発用途に使うと宣言がされていました。
ただしFaceBookとMicrosoftがディープラーニングのフレームワーク間の中間フォーマットを協力して作成し、pytorch、caffe2、CNTK間でモデルを変換できるようにしているようです。
googleのTensorFlowに対抗して研究から実用まで一貫したサポートが(クラウドを通じて)できるように整備しているというところでしょう。
まとめ
Define by Runの中で最も勢いのあるフレームワークです。Define by Runでなければ動かないようなニューラルネットの学習を行うという場合以外でも、デバッグの容易さに直接繋がってくるわけなので、オリジナルなことをやりたいと思えば思うほど、PyTorchは使いやすいと感じるのではないでしょうか。
積極的にニューラルネットのことを学びつつ、最新のコードにも触れていきたいという場合は一番おすすめできるフレームワークだと感じます。
全体のまとめ
結論
結局あれこれ書きましたが、やりたいこと達成できればどのフレームワークでも良いです。
しかし、誰かとコードを書くことになれば統一性は合ったほうが良いでしょう。そうなった場合、言語やフレームワークというのは外的要因で決定されることも出てくると思われます。一言で言えば職場の都合上とか、研究室の都合上とか、そういうことは起こるわけですね。
そうなった場合にはTensorFlowとPyTorchあるいはTensorFlowとChainerくらいな感じでDefine and RunとDefine by Run1個ずつくらい読めて書ければ十分なんじゃないかなと思います(それぞれ1つずつ書ければ、それぞれ移行もそんなに難しくないはず)。
今後の進展
結局気になるのは、どのフレームワークが生き残るんだ!?ということだと思います。一生懸命勉強して、やっとこさ使いこなせるようになった矢先Theanoのように終了されたら辛いわけです(Theano選んでたような連中は、他もすんなりやるだろうけど)。
ただどのフレームワークが生き残るか、こればかりは分からんのです。
ただ、TensorFlowの動向はこの業界を牽引しているのは間違いないので、見張っておいていいと思います。
2018年5月15日に以下の記事を書きました。
基本的な知識はそのままに、ディープラーニングフレームワークの体制が少し変わってきましたので一読ください。