今回は実践編、前回導出した確率的勾配降下法でのロジスティック回帰の学習を実装してみましょう。
環境はこれまでと同じくPython/numpy/matplotlibを用います。インストールなどの準備は第6回を参照してください。
パーセプトロンの実装の復習
今回のロジスティック回帰の実装は、連載第17回のパーセプトロンの実装と非常によく似たものになります。
そこでパーセプトロンの実装を再掲しておきます。パーセプトロンそのものの復習はここではしませんので、必要なら連載第15回をご覧ください。
ロジスティック回帰の実装
これをロジスティック回帰の実装に差し替えるにあたって、変更する必要があるのはラベル変数の値、予測確率の計算と、パラメータwの更新式、あとはパラメータの初期化とループの終了条件です。
順に見ていきましょう。
人工データの生成
パーセプトロンは線形分離可能な問題しか解けなかったので(連載第15回参照)、このコードでは線形分離可能なデータを生成しています。
一方、ロジスティック回帰は線形非分離な問題でも大丈夫なのですが、ここではパーセプトロンと同じ問題をきちんと(期待通りに)解けるかを確認しておきましょう。
というわけでデータ生成のコードは基本そのまま使いますが、正解ラベルの値だけはロジスティック回帰にあわせて変更する必要があります。
パーセプトロンの正解ラベルは+1と-1であるのに対し、ロジスティック回帰は1と0を使うため、その点のみ反映したコードは次のようになります。
これに関連して、出力の図を描くところも少し変更します。
パーセプトロンによって得られる予測は「正か負か」、特に+1または-1であり、描画する必要があるのは分離平面だけでした。一方、ロジスティック回帰の予測は確率、つまり0から1の間で変化する関数として得られます。
よって、なだらかに変化する予測分布を描画したいですから、そのための書き換えのついでに、今回はmatplotlibのimshow()という関数を使ってみましょう。
imshow関数は、引数cmapに描画する色マップを指定します。PiYG_rの場合は、予測分布が1に近い点はピンク(Pi)、0に近い点は緑(G)に、そしてちょうど中間は白っぽい黄色(Y)となるグラデーションで描画されます(_rは逆順を意味する)。
予測確率とパラメータの更新式
パーセプトロンにしてもロジスティック回帰にしても、「データを選んで、予測して、それを使ってパラメータを更新」という大きい流れは全く同じです。
パーセプトロンのコードでは、訓練データセットからランダムに1つ取りだした点(xn,yn)、その点での正解ラベルtnを使って予測とパラメータの更新をし、それをデータセットを一周するまで繰り返すということをしていますが、その枠組みはロジスティック回帰でもそのまま使えるということですね。
一方、予測やパラメータの更新式はモデルの要ですから、こちらは当然書き換える必要があるでしょう。
ロジスティック回帰の予測確率は次の式で表されるのでした。
ただし
これを実装するには、まずシグモイド関数σ(z)が必要ですね。このシグモイド関数やその多変数版にあたるソフトマックス関数はnumpyかscipyで標準サポートしてくれててもいいのになあとか個人的には思うのですが、無いものは仕方ありません。
せっかくですから関数として実装しておきましょう。
上の式では予測確率にyの文字が当てられていますが、その文字はすでにデータ点のy座標を表すのに使ってしまいました。ここではパーセプトロンのコードにあわせてpredict(予測)という名前の変数を使うことにしましょう。
φnもこの後またすぐ使いますから、これは変数feature(特徴、素性)に入れておきます。すると次のようなコードになります。
特徴関数phiは定数項にあたる1を付け加えただけの、元のパーセプトロンのコードと同じものを使います。
予測確率がわかると、パラメータを更新できます。
ロジスティック回帰の確率的勾配降下法では、次の式でパラメータwを更新します。
ηは「学習率」と呼ばれる適当な正の値で、一回の更新でパラメータをどれくらい動かすかを調整します。ηが大きいほど学習は速くなりますが、予測確率が安定しません。そこで初期値は0.1くらいにして、学習が進むにつれて徐々に小さくしていく、というのが一般的です。
このetaを使ってパラメータを更新します。
パラメータの初期値と学習の終了条件
後はパラメータwの初期化と学習の終了条件だけです。この2つは実は少々関連があります。
パーセプトロンの解法アルゴリズムは、0で初期化したパラメータで始めるとすべてのデータ点を完全に正しく分離する解にたどり着くことが示されています。
この時の学習ループの終了条件は明確で、「すべてのデータ点での予測が正解と一致するまで」となります。「線形分離可能な問題に限る」という強い条件が付いているだけあって、非常に強い性質を持っているわけですね。
一方の確率的勾配降下法で求まるのは、パラメータwの初期値に依存した局所解になります。そこでランダムな初期値で始めるのが一般的ですが、パラメータが大きくなりすぎるのを嫌って、あえて0から始めることもあります。
そうして求めた局所解は、一般に全データ点で正解を予測できるものにはなりませんので、学習ループの終了条件もパーセプトロンのままというわけにはいきません。
そこで確率的勾配降下法では尤度などの指標値があまり変化しなくなったら終了したり、あるいはあらかじめ学習の回数を適当に決めておきます。
今回はシンプルに学習回数を50周と決めておきましょう。
これらをすべて反映したコードは次のようになります。
さて、長々と20回続けてきた本連載ですが、次回で最終回となります。
最終回は連載の流れの中では触れられなかった落ち穂拾いをしつつ、これまでのまとめをしようと思います。