作って遊ぶ機械学習。

~基礎的な確率モデルから最新の機械学習技術まで~

実践!ベイズ学習

今回は、実問題を解くためのベイズ学習による機械学習アルゴリズムの構築方法に関してざっくり俯瞰してみたいと思います。ここで解説するフローは僕が実問題にアプローチする際に意識しているものですが、おそらくこれはベイズ学習のみならず、広く一般的な統計モデリング機械学習の問題解決にも適用できると思います。

 

 <アルゴリズムの開発フロー>

f:id:sammy-suyama:20161219140751p:plainあまりファンシーな図でなくて申し訳ないですが、これから1つ1つの項目と各々の遷移に関して説明していきます。

 

1、データ・課題の整理をする

まず、機械学習を使って解きたい問題や実現したいサービスを定義してみます。データはあるんだけど何をして良いかわからない、という場合もあるかもしれませんが、そういうときでもとりあえず何かしらの目標を仮置きしてみるのが良いかと思います。基本的に機械学習でできることは「見えない情報の予測」であると考えればアイデアが発想しやすいかもしれません。未来の株価の予測、画像や音声の判別、欠損データの補間、異常値の特定など、これらはすべて未知の事象に対する予測問題として定義することができます。*1

課題が決まれば、次第に必要なデータは明らかになってきます。例えば、明日の東京都全体の電力需要を予測したいのであれば、過去の需要データに加え、その日の天気や曜日の情報(平日or休日)なども予測に役に立つでしょうし、その日に起こる予定のイベントとかも考慮しておいた方が良いかもしれません。この辺りはデータの収集コストと相談する必要もあるかと思います。また、データそのものの収集に伴って、データに関する周辺的な知識(よく知られた法則、物理的な制約など)も色々仕入れておけば、後のモデル構築の段階に役立てられる可能性が高いです。
また、集めたデータの形式や粒度がバラバラだったりする場合はこの時点で揃えておくのが良いかもしれません。ただし、欠損値の補間や異常値の除去、データサイズの補正などのいわゆる「前処理」をここで行ってしまうと、後段のアルゴリズムに対する情報欠損に繋がる可能性があります。手間とコストを十分に考慮する必要がありますが、理想的には、これらの処理はモデルと推論(2および3)で行う方が良いです。

 

2、モデルを構築する

f:id:sammy-suyama:20161219202632p:plain

ここでは確率モデルP(X, Θ)の構築を行います(Xがデータで、Θが学習したいパラメータなどの未観測変数)。基本的なアプローチとしては、「今手元にあるデータXは一体どういうプロセスを経て生成されたのか?*2」ということを念頭に置き、基本的な確率分布を組み合わせてモデルを構築します。

持っているデータの種類によってもモデル構築の仕方が大きく変わってきます。例えばラベルデータを十分に持っているのであれば、既存の教師ありの識別モデル(線形回帰、ロジスティック回帰、ガウス過程など)をそのまま使うのでも良いかもしれません。*3

最も大事なことは、この段階でデータをよく観察し、普遍的な性質や特徴を整理することです。そのような知見をどれだけモデルに組み込むことが出来るかが、未知の値を予測するにあたって非常に重要になってきます。ちなみに、生データに対して何かしらの特徴量抽出を行うやり方も手軽ですが、このような段階を踏んだ情報処理の過程にしてしまうと、その都度情報欠損が起きてしまう可能性があることに注意してください。これを防ぐには、特徴量抽出のプロセスも確率モデルとして組み込むのが理想的です。

さらに、確率モデルを構築した後に必ずやってほしいことは、モデルP(X, Θ)から仮想的にデータXをサンプル(シミュレート)してみることです。このサンプルが、我々が実データを学習させる前に持っている「仮説」を具体的に表していることになります。例えば、データXとして成人男性の身長を仮定しているのに、モデルからサンプルしてみた値が0 cm近辺にへばりついたちっさい値しか出てこないとかいう場合は、明らかにモデル自体か事前分布の設定等が誤っています。モデルからのサンプルが実際に発生し得るデータをちゃんとカバーできそうかどうか、次の推論導出に進む前にチェックしておくのが大事です(「作ったモデルでもっと遊んでね」と僕は表現します)。

 

3、事後分布を計算する(推論を実行する)

前ステップで構築したモデルをもとに、事後分布P(Θ|X)を評価します。

伝統的な確率推論に対して、機械学習機械学習たらしめているのはおそらく取り扱う確率モデルの複雑さにあると思います。多くの問題では事後分布が解析的に得られず、推論アルゴリズムを導いてコンピュータ上で実行することになります。具体的にはMCMCや変分近似などの近似推論アルゴリズムを導出してPythonやJulia等の適当な言語で実装するほか、モデルがそれほど複雑でないのであればStanなどのツールを使って自動的に推論してもらうという手もあります。
また、多くの機械学習の課題では、ただパラメータの事後分布を計算するだけを目標とするということはあまりないでしょう。例えば未来の値X*を予測したい場合は、学習された事後分布を使って予測分布P(X*|X)=ΣP(X*, Θ|X)を評価することになると思います。あるいは、クラスタリングなどの「観測することのできない潜在的な値を推定する」問題では、潜在変数モデルP(X,Z,Θ)に対する潜在変数の事後分布P(Z|X)を計算することになります。

ところで、このステップでは多くのバグに苦しむことになります。手で導出した推論アルゴリズムがきちんと動作しているか確認する方法はいくつかあり、一番のオススメとしては、いきなり実データに挑戦せずに、学習前のモデルから仮想的にサンプルしたデータを改めて訓練データとして使って推論させてみることです。このようにすればデータに対するモデルは100%正しいことが保証されるので、推論アルゴリズムの導出式や実装のバグのチェックのみに集中することできます。また他には、例えば変分ベイズ法などの特定の方法では、変分下限と呼ばれる値を評価することにより(ある程度は)動作の正当性を確認できます。

モデル構築および近似推論に関する関連記事は例えば次のようなものがあります。

グラフィカルモデルによる確率モデル設計の基本 - 作って遊ぶ機械学習。

ベイズ混合モデルにおける近似推論① ~変分近似~ - 作って遊ぶ機械学習。 

 

4、結果の評価を行う

f:id:sammy-suyama:20161219201611p:plain

作ったアルゴリズムが所望の動作を実現しているか、あるいは改良がうまくいっているかを評価します。モデル自体を評価するような指標(周辺尤度、BICAICなど)もありますが、基本的には今解いている課題に即した評価手法を使うのが自然かと思います。例えば連続値の予測であれば二乗誤差で評価するのが(ベストかどうかはともかく)簡単ですし、低頻度のイベントを検知するような課題であればF値を使うのが良いかもしれません。ただし、結果の1%や2%を競うような数値評価至上主義*4に陥らないように注意してください。また、見落としがちではありますが、実際のところ機械学習を使ったサービスなどでは視覚的に結果の良し悪しを確認したり、自分でサービスを使ってみて感触を確かめる、というのも重要な評価手段の1つになります。

それに伴って、アルゴリズムの計算効率(メモリ量や計算速度など)も合わせて評価するのが重要です。というのも、最適化やサンプリングに基づく多くの機械学習アルゴリズムは、時間をかければかけるほど最終的な性能が高くなるものが多く、計算コストを無視した推定精度のみの評価はほとんどの場合では不十分になるためです。

また、機械学習の課題で訓練データとテストデータを分けて評価するのは必須だと思われます(クロスバリデーションなど)。これは過学習をしていないかチェックするための超基本手段なのですが、意外にちゃんとやっていない人が多くてびっくりです。ちなみに「ベイズ学習はそもそも過学習をしないので、データを分けなくても評価できる」という主張もありますが、現実的に多くの場合では近似アルゴリズムを推論に使うことになるので、オーバーフィットやアンダーフィットに近しい現象も起こり得ます。なるべく本番環境に近い状態で評価するためには、やはりテストデータに対する課題依存の評価指標を設定するのが無難かと思います。

確率モデルを使った機械学習アルゴリズムでは、得られた事後分布から仮想的にデータをサンプルしてみるのも学習がうまくいったか直観的にチェックするポイントになります。例えば、顔画像Xを学習する問題を考えてみましょう。事前分布P(Θ)をもとにP(X|Θ)からデータをサンプルしてみると初めはぐちゃぐちゃなノイズしか出てこなかったのが、学習された事後分布P(Θ|X)をもとにサンプルした場合は「顔っぽい」データがちゃんと生成できるようになっているはずです。これがうまくいかない場合は、モデルの表現能力に問題があるか、訓練データ数が少ないか、あるいは推論アルゴリズムの性能が十分でない可能性があります。

 

よく起こる遷移

・推論導出からモデルの構築(3→2)

2で構築したモデルが奇怪すぎて推論アルゴリズムがうまく導けない場合があります。
それでも無理やり追加の近似などを仮定してアルゴリズムをひねり出すこともできますが、多くの場合は性能がよくなりません。モデルの構築と推論の導出は分けられたプロセスとして認識すべきですが、実際は相互に行き来しながら一番良い組み合わせを探していくことになります。

・性能評価から推論の再導出(4→3)

アルゴリズムの導出はうまくいっているはずなのに、実データに対して思うような性能が出ない場合は、推論アルゴリズムを再検討してみる必要があります。具体的には、必要メモリ数があまりにも多すぎた場合などは、学習アルゴリズムをオンライン化(Stochastic Gradient Descentなど)してデータを小分けに出来るようにするなどが考えられます。他にも、例えばMCMCが遅すぎる場合は変分近似を使ってみる方が良いかもしれません。

・性能評価からモデルの構築(4→2)
実験結果を眺めることにより、「うまくモデル化できていない特徴」というのが見えてくる場合があります。この場合は2に戻って、新しい特徴をモデルに組み込むことが必要になってきます。例えば、データに明らかに時間的依存性があることがわかった場合は、モデルをマルコフモデルにするなどの手段が考えられます。

逆に、作ったモデルが複雑すぎるために推論アルゴリズムの性能が出ていない可能性もあります。こういう場合は、ちょっと悔しいですが、モデルから余計な要素を切り落としてシンプル化するのもアリなんじゃないかと思います。

・性能評価から課題の設定(4→1)
評価結果が思わしくない場合は、データの量や質に関する問題に着目するか、あるいは課題自体を検討しなおしてみるのが良いかもしれません。実際、4の段階にまで入ると、データに関する知識やアルゴリズムの計算コストなども最初の頃よりだいぶ頭に入ってきているはずなので、実運用に基づいた課題の再設定などは積極的に検討すべきなのではないかと思います。

 

- - -

以上、思いつくままにバァーッと書いてしまいましたが、少しでもベイズ学習あるいは確率モデルによる機械学習構築を検討される際に参考になればと思います。

 

今回の記事がよくわからん!という方には,次のような入門書もあります.

books.rakuten.co.jp

*1:他にもデータの圧縮、ノイズの除去なども確率モデルの得意とするところです。

*2:いやいや、深層学習とか認識系の課題であれば「データがどういうプロセスを経て認識されたのか」の方が正しいでしょ、とおっしゃる方もいるかもしれません。その場合は、人間が与えるラベルデータが「どのような認識的な処理過程を経て生成されたのか」をモデル化する、と考えれば、文中の言い方でも悪くない気がします。

*3:ところで「教師あり」というのはつまり、「予測したい値と同質と思われるデータを学習用に持っている」とした場合の機械学習の実装方法だと解釈できます。つまり、解きたい実課題自体が教師ありだとか教師なしだとか言うのはナンセンスで、アルゴリズムを開発する人間がその課題をどう捉えるかに依る、というのが正しいと思います。

*4:定量評価というものは、実現したい目標を理解しやすく数値に要約したもの、あるいは仮置きしたものに過ぎません。よっぽど単純な問題でない限り、絶対的な数値評価指標などというものは存在しないと思った方が良いです。