はじめに
プログラムへの理解度
プログラムは複製が可能です。だれか一人がプログラムを完成させればそれを共有財産として使うことができます。それがいわゆる「ライブラリ」です。
果たして、ライブラリを作った人と使っている人の、そのプログラムへの理解度は同じだと言えるでしょうか。当然言えません。もしも同等の理解度を得たければ、ライブラリの中身まで覗く必要があるでしょう。
機械学習への理解度
同様にして、ある機械学習手法を考案した人(アルゴリズムを考案した人)と、その機械学習手法を使っている人の、その手法への理解度も同じだとは言えません。同等の理解度を得るためにはアルゴリズムが得られた手続きを追う必要があるでしょう。
そして機械学習というのはプログラムによって実現されます。
これにより、アルゴリズムとしての理解と、その実装としての理解が二重に必要となってきます。
何が重要か
そこで果たしてどちらが重要でしょうか。
どちらも重要ですが、選ぶならばアルゴリズムとしての理解の方が私は重要だと感じます。
例えば深層学習のライブラリはたくさんありますが、プログラムとしての実装形態は異なったものになっているでしょう。ライブラリを使っていく上で、プログラムがどのような設計思想になっているのかを理解するのは重要なことです。しかしそれはあくまでアプリケーションの話です。
用いているデータ構造によって速度は変わるかもしれません。実用上の差はあるかもしれません。でもそれは機械学習手法としての本質ではありません。
これらが重要でないと言っているのではありません。効率的に機械学習を利用しようと思うのならばいずれ理解しなければならないところです。
しかし機械学習手法そのものを理解しようと思うときの焦点はそこではありません。
おそらくライブラリを使い倒したところで、機械学習手法への真の理解は得られないでしょう。
この手法を使ったら○○という結果が得られた。
別の手法を使ったら☓☓という結果が得られた。
このような事実が山積みになり、その中から良さそうな物を選択する。その場しのぎにはなっても、今後の知識・知恵として蓄積できるかはかなり怪しいものです。
確固たる意思を持って、「この手法を使うことには、このような意義がある」と説明できるようになるためには、やはりアルゴリズムとしての理解が大切になります。
アルゴリズムとしての理解
アルゴリズムとプログラム
アルゴリズムとは簡単に言えば「何らかの有限の手続き」であって、抽象的なものです。必ずしもそれがプログラムで実現されるとは限りません。からくり人形の動作もアルゴリズムの産物だと言えます。
プログラムはアルゴリズムを実現する一手段です。そして非常に汎用性の高いものです。コンピュータを生み出したのは人類史上でもかなり偉大な成果でしょう。偉大であるがあまり、現在はアルゴリズムといえばコンピュータ・プログラムによって動作するのが当然であるように思ってしまいます。
コンピュータ・プログラムによってアルゴリズムの動作を実現する場合には、データ構造を与える必要があります。それに対し適切な処理手順を記述することで、望みの働きをさせることができます。(偉い誰かが「プログラム=データ構造+アルゴリズム」だと言っていました)
プログラムの理解
プログラムの理解をするというのは、どのようなデータ構造にどのような処理を施すことで、どのような動作をするのかを把握することです。高度に抽象化された言語では、プログラムの全体像を理解することは一層困難になります。明確にプログラムを知りたいならばC言語のような型宣言を明確に行うタイプの方が良いかもしれません。
更にライブラリでは動作の中身は隠蔽され、使うときにはブラックボックスとして取り扱うことになります。しかし、それで全く構わないという場面も多いでしょう。
なぜなら、少なくとも機械学習においては、何かしてほしい動作があって、それを実現する手段としてプログラムを書いているからです。もしも一行でしてほしい動作を記述できるなら、そんなに嬉しいことはありません。
問題なのは「してほしい動作」を、的確に決められるかということです。
この部分がまさに機械学習アルゴリズムへの理解力が試される場所でしょう。
アルゴリズムとしての理解
機械学習のアルゴリズムとしての理解をするというのはどういうことでしょうか。
アルゴリズムにされた時点では、何だか繰り返し構文の中に値の更新式が入っているというような状況です。「これを読めるようになることがアルゴリズムの理解だ」とは言えません。これは既に擬似言語として、言わばプログラムの形となっており、これを読んで動作を理解するのはプログラムの理解です。
アルゴリズムを理解するというのは、なぜその処理手順なのかを説明できるということです。なぜこの順番で、そのような更新を行い、その繰り返しを行うのか。そしてなぜ更新の式がそのような形なのか。これらの疑問に答えられるようになることです。
機械学習手法を理解する方法
現存するすべての手法を完全に理解するのは途方もないことです。
しかし、せめて自分が利用を検討するものや、代表的な手法くらいは理解しておきたいものです。
真の理解をするためには、その手法を考案した人の追体験をするしかありません。
すなわち、アルゴリズム導出の過程を、紙とペンで追うことです。
世の中に出回っている教科書は、代表的な手法を取り扱っており、しかもアルゴリズム導出の過程(つまり数式)を丁寧に書いてくれています。ですから基本これらを学べば良いです。
それが随分大変なことであるというのは、やったことがある人ならば全員頷くところでしょう。
機械学習を抑えるためのポイント
機械学習で繰り返しの構文が出て、何らの更新式があれば、大抵はパラメータを逐次最適化しているということです。いろいろなアルゴリズムを見てください。機械学習の手法のほとんどがこの形態をしています。というより、その部分を「学習」と呼びます。
更新式を理解すること
そして更新式というのは、「学習」とやらが進むように設計されたはずです。
では「学習が進む」とは一体どういうことでしょうか。何をもって学習が進んだと言うのでしょうか。その基準があるからこそ、更新式を導出できたはずです。その基準を理解することが、おそらく学習の狙いを掴むことに繋がります。
それはつまり、学習手法の損失関数(あるいは評価関数)を理解することです。
損失関数があったとすれば、学習が
で進むというのは
となるということです。損失関数を小さくしていくことが学習の目的です。
ならば損失関数がどのような形をしているのかを見れば、その手法の理解に繋がるはずです。
これを理解するだけでも、随分各手法の狙いの違いが分かってくるのではないでしょうか。
当然、損失関数の数式の意味がよくわからないのであれば、「その損失関数の導出を見る」という形で遡って行くことになります。
判別も回帰も大雑把には何らかの関数
データを入れたら、データ
を返す入出力装置を関数
と記述します。
判別にしても回帰にしても、この関数を適切に定めることが学習の目的です。
を闇雲に探しても見つかりません。従って、
には何らかの形を予め仮定しておき、想定された形の中で、最もまともなものを見つけるという方法を取ることができます。こういうのをパラメトリックな手法と言いますが、(とりあえずは)大抵パラメトリックな手法です。(ノンパラメトリックな方法は、それを学ぼうと思わない限り出くわさない)
みたいなのがいわゆる線形回帰であって、がパラメータです。こう決めた以上、関数はぐにゃぐにゃ曲がった形は取れません。取ることのできる形の中で一番まともなものを、パラメータを色々変えてみることで見つけようというのが学習です。パラメータを色々変えるための指針に損失関数を使うという形になります。
つまり損失関数の中には必ず、判別や回帰のために仮定した関数自身やパラメータ
などが含まれていることになります。
従って、機械学習手法のもう1つのポイントは仮定する関数の形(モデル)ということになります。
大枠はこれで殆ど掴める
モデルを仮定して、損失関数(あるいは評価関数)に従って修正を施していくのが学習です。
従って、この2つを抑えると、その手法の大枠をかなり理解することができます。
せめて使おうと思う手法のこの部分は是非とも把握しておきたいところです。
確率的なモデルを考える場合でも入出力関係だけで言えばやはり関数(データを与えたら、確率(0〜1の値)を返すような)です。
次のステップ
モデルについて詳しく知る
仮定したモデルについて理解を深めることも大切です。
なぜそのようなモデルを仮定しようと思ったのですか?という問に答えられなければいけません。損失関数を二乗誤差関数にしたり、交差エントロピーにしたり、ヒンジ損失にしたり、いろいろ考えることはできますが、どれかに決めたとして、損失関数は結局中身にモデルの形を含みます。
つまり損失関数を決めても、その詳細はモデルに依存するということです。
深層学習では、このモデルに相当する部分を非常に膨大な複雑な関数にしておくことで、どんな関数にでも姿を変えられるというのが強みになっています。
それに加え最適化の手法を工夫し高速化をはかり、問題に応じてモデルの形を適したものに調整することで高い性能を発揮します。言い換えれば、複雑すぎるあまり、問題に適していないモデルを仮定した場合には、深層学習は資源を食うだけのゴミに成り下がります。
従ってモデルについて深く知るのは、深層学習では特に大切なことでしょう。
もちろん他の手法でもそれぞれ差異が出てくる場所です。
最適化を知る
そしてコレらに加え、最適化に関する計算が加わってくれば、更新式の導出ができます(大抵は偏微分していくという操作になります)。
ココらへんが計算的にはかなりしんどい部分でしょう。
普通の勾配法なら偏微分を計算するだけです。しかしEMアルゴリズムや誤差逆伝搬法に触れて、数式の嵐に呆然とした経験がある方は多いのではないでしょうか。
ところでEMアルゴリズムや誤差逆伝搬法というのは、実は一般的な解法です。
誤差逆伝搬法といえばニューラルネットの勾配を求める手法に感じるかもしれませんが、「それに使える」というだけで、他のことも色々できます。EMアルゴリズムも非常に汎用性の高いものです。
故に、なにか簡単なモデルに対してこれらを実際に使ってみるということをするだけでも十分です。
なぜなら、モデルが複雑になったとしても、それは計算がめんどうなだけでやっていることは同じだからです。EMアルゴリズムも誤差逆伝搬法も、汎用性の高いものであってモデルが変わったからと言って大きく変更を受けるものではありません。
深層学習でも最適化はいろいろ工夫されています。
誤差逆伝搬法をベースに、更新式を更に改良する試みが行われています。
まとめ
私は基本的には今書いた手順で理解に努めています。
つまずくポイント
教科書を見ていきなり躓くのは、大抵学習の部分が最も大事だと考え、最適化の部分に飛びついてしまうからだと思われます。そして、述べたように最適化の式は損失関数を減少させるように決定され、損失関数はモデルの形状に依存します。したがって最適化から見ていくと、あたかも各手法がそれぞれ完全にバラバラに見え、こんなにむずかしい計算を途方もなく繰り返さなければならないと感じてしまいます。
そうではなく、モデルや評価関数で手法の大枠を掴んでおき、それを学習させるための具体的な計算が最適化の部分なのだと理解しておきましょう。モデルが同じでも評価関数が変われば最適化の計算も変わります。しかし、どのような思想の変更を受けたかは評価関数の変更を見るだけである程度分かるはずです。
それを理解してから、じゃあ更新式を導こうということで最適化の部分に取り組めばいいのです。
「機械学習」といえど「学習」の部分は、手法の理解においてかなり後の工程で良いと思われます。
記事
数学の勉強をする上での手順
評価関数を知る
モデルのことを知る