今日は自分の受け持ちの科目の期末試験でした.昨日の午後に問題ができたとこ(ほんまは12月中旬には作っとくことになってるんですが…)っちうていたらくでしたが,一応無事終了.採点はまだですが.で,昨日のうちに問題用紙と解答用紙の印刷その他ほとんどの準備を済ませてて,今日は時間があったので,研究のようなそうでもないような活動をちょっとだけ.
で,こんな日記になりました.自分の頭の中では,この話もそのうち自分の研究につながることになってますが,今は時間がないのであれこれちまちま.以前の pylearn2 & theano の話との関係とか一度整理して書いときたいけど,また今度.というわけで,最近のんへのリンクだけでも.
最後にランニングの話のおまけつき (^^;
Logistic Regression してみる
多クラス識別の基本的な手法である Logistic Regression を Python + Numpy で書いて,人工データで実験しました.MNIST の実験もやってるけどまだ途中なのでその話はまたあらためて.
Logistic Regression の学習則
特徴ベクトル \( \boldsymbol{x} \in {\cal R}^D \) が与えられたときに,これを \( K \) 通りのクラス \( {\cal C}_1, {\cal C}_2, \dots , {\cal C}_{K} \) のいずれかに分類する識別問題を考えます.Logistic Regression では,クラス事後確率が次式で表されるものとします.
\begin{align} p({\cal C}_k | \boldsymbol{x}) &= \boldsymbol{z}_k(\boldsymbol{x}) = \frac{\exp(y_k)}{\sum_j \exp(y_j)} \tag{1} \\ y_k &= \boldsymbol{w}_k^\top\boldsymbol{x} + b_k \end{align}
式(1)はいわゆる softmax 関数ですね.パラメータ \( \boldsymbol{w}_k, b_k \) \( (k = 1, 2, \dots , K ) \) は,学習データ \( \{ (\boldsymbol{x}_n, \boldsymbol{t}_n ) \}_{n=1}^N \) を用いて学習させます(バイアス項 \( b_k \) については…今はとりあえずありで話を進めることにします).\( K \) 次元ベクトル \( \boldsymbol{t}_n \) は,一つの要素だけが 1 で他は 0 で,正解クラスを表します.
このとき,学習データに対する対数尤度関数を \( L \) とおくと,
\begin{align} L &= \log \prod_{n=1}^N \prod_{k=1}^{K} p({\cal C}_k | \boldsymbol{x})^{t_{n,k}} = \sum_{n=1}^N \sum_{k=1}^{K} t_{n,k} \log{z_{n,k} }\end{align}
と書けます.この \( L \) を最大化することが目的です.そのようなパラメータ \( \boldsymbol{w}_k, b_k \) を求めるために,以下では単純な勾配法をもちいることにします.つまり,適当な初期値からはじめて,
\begin{align} \boldsymbol{w}_k^{\rm new} &= \boldsymbol{w}_k^{\rm old} + \eta \frac{\partial L}{\partial \boldsymbol{w}_k} \\ b_k^{\rm new} &= b_k^{\rm old} + \eta \frac{\partial L}{\partial b_k}\end{align}
という更新規則にしたがってパラメータを逐次更新してくわけです.\( \eta \) は学習定数.ちなみに,勾配を具体的に書くと次の通り.
\begin{align} \frac{\partial L}{\partial \boldsymbol{w}_k} &= \sum_{n=1}^{N} ( t_{n,k} - z_{n,k})\boldsymbol{x}_n \\ \frac{\partial L}{\partial b_k} &= \sum_{n=1}^{N} ( t_{n,k} - z_{n,k})\end{align}
これらを上の式に代入したものが,今回用いる学習則です.
Logistic Regression のプログラム
というわけで,Python + Numpy で書いたらこんなん.あ,上の式と違って,こちらはデータ数 N で割った値で動くようになってます.
logsumexp の説明は...面倒なのでリンクだけ (^^;
3クラスの2次元データを識別する実験
適当に作ったデータで動作確認.プログラムはこんなん.
はじめて pylab というか matplotlib というかを使ってみたので,グラフのプロット回りは何か変なこと書いてる可能性大です.
上記をそのまま実行してみた時の出力はこんなん.
# N = 600 D = 2 K = 3 0 -1.09825523036 88.0 100 -0.946441545934 12.8333333333 200 -0.827675000788 4.83333333333 300 -0.732000049299 3.5 400 -0.654474636171 3.0 500 -0.59108975153 2.83333333333 600 -0.538718615823 2.83333333333 700 -0.494969194423 2.33333333333 800 -0.458024035431 2.33333333333 900 -0.426501179662 2.33333333333 1000 -0.399344224105 2.33333333333
学習データの散布図と,推定された事後確率で平面を塗り分けてみた図はこんなんなりました.
モデルの式から明らかですが,念のため…クラス間の識別境界は直線です.
上記は3つのクラスの学習データ数が同数でしたが,ためしに赤クラスのデータ数を 1/4 の50個にした実験もやってみると…
# N = 450 D = 2 K = 3 0 -1.09910292386 59.1111111111 100 -0.815654426434 16.2222222222 200 -0.70832426179 13.1111111111 300 -0.628703160812 12.6666666667 400 -0.567130509944 12.4444444444 500 -0.517949260683 12.0 600 -0.477608735641 12.0 700 -0.443805526707 12.0 800 -0.414990489951 11.7777777778 900 -0.390084348094 11.5555555556 1000 -0.368310406891 10.8888888889
こうなりました.
よだんだよん
ipython で __debug__ が False の状態で %run したい
上記のプログラムでは盛大に assert 文使ってます:
単純文 (simple statement) — Python 2.7ja1 documentation
デバッグに便利やから&コメントがわりって感じ.コマンドラインで python コマンドで実行するときは,
% python -O hoge.py
とかやれば assert 文は評価されなくなるのでええんですが,ipython から
In [1]: %run hoge.py
とかやる場合どうしたらええんかなと探してみたら,こんなんでてきました.
[IPython-dev] Sth. like "python -O" within IPython?
なるほど.早速,bash の設定ファイルで次のように alias しときました.
alias ipython="ipython --colors=Linux" alias ipythonO="python -O `which ipython` --colors=Linux"
--colors=Linux は,たかたかの「ターミナル」の設定が黒板色(濃い緑の背景に白字)で,デフォルトの ipython の色使いが見にくいのをなんとかするためです.
ランニングの記録更新
今朝,小雨の中をいつもの遠回りルートで走って登校したら,またちょこっとだけ記録更新しました( 前回の記録更新:情報処理の基礎 - まんぼう日記 ):
6.3km, 35分37秒, 5:39 min/km (10.62 km/h)
https://www.runtastic.com/ja/users/takashi-takahashi-13/sport-sessions/384134227
- 3mi最速 26:36
- 5km最速 27:38
もひとつ.日記に書かへんかったけど,21日の帰り4.5km走って,1mi最速の記録も更新.7分37秒.
https://www.runtastic.com/ja/users/takashi-takahashi-13/sport-sessions/383175436