「データ解析のための統計モデリング入門」第3章メモ #みどりぼん

6/10 に開催された「データ解析のための統計モデリング入門」、通称「みどりぼん」の第3回読書会にのこのこ参加& LT してきた。主宰のやまかつさん、発表者&参加者の皆さん、会場を提供してくださったドワンゴさん、ありがとうございました。


LT は……正直、ネタを思いついた時は、ええやんおもしろいやん、とかなぜか思いこんでた。当日の朝くらいに「測度論とかないわー」ということにやっと気づき、一週間前の中谷の後ろ頭をしばき倒したくなったが、もはや後戻りはできず。この LT をちゃんと最後までやり通したという一点で褒めてあげて欲しい……



さて気を取り直して。
質疑応答の時にあれこれ好き勝手なことを突っ込ませていただいてたのだが、読書会終了後にそのあたりをブログとかにまとめてあると嬉しい、という声をもらったので、かんたんにメモしてみる。

3.6 説明変数が数量型+因子型の統計モデル

この節では、体サイズ x と施肥 f の両方を組み込んでポアソン回帰をしてみたら、施肥の係数 β3 が負になっちゃった! という話をする。
しかし、「みどりぼん」はこの教科書的おあつらえ向きな展開にもかかわらず、「前の節(=施肥のみを説明変数とするモデル)では肥料の効果 fT がプラスであったのに、このモデルではマイナスだと推定されています。肥料の効果についてはいよいよわからなくなってきました」とコメントしたのみで終わってしまう。
案の定、読書会ではこの点が議論の的となり、みんなでこの「直感と異なる結果」をどのように解釈するのかを熱く語り合うことになった。このように議論してもらう事を期待して、あえて説明しなかった……?


先に結論めいた事を一言でいうと「説明変数である体サイズと施肥効果の間に、いわゆる弱い相関があるから」となるだろうか。


一般化線形モデルでは説明変数間の独立性をどこか期待している部分があって(「説明変数」「目的変数」ではなく「独立変数」「従属変数」と呼ぶ流儀もあり、このことと関係している……のかな? 由来は調べてない)、そうでない場合はパラメータが「期待する値」から外れたり、精度が悪くなる、などと言われたりする。
といっても、読書会でも指摘のあったことなのだが、「期待する値」とは「説明変数にその変数だけを使って、他の変数の影響を除外した場合の係数」だと解釈することができる。すると、その変数が他の変数と独立なら「期待する値」に一致するだろうし、逆に独立でなければ、その「期待する値」に一致しないのは不思議でもなんでもない。


つまり、パラメータが「期待する値」から外れているように見えて、その「理由」を考察する必要をもし感じたなら、まずは説明変数間の相関を確認するのが一つの手。
そこで体サイズと施肥効果の関係を見てみると、

d <- read.csv("http://hosho.ees.hokudai.ac.jp/~kubo/stat/iwanamibook/fig/poisson/data3a.csv") 
plot(d$f,d$y) 
plot(d$f,d$x) 

左図が施肥の有無ごとの種子数の関係(みどりぼん図3.3)、右が施肥の有無ごとの体サイズの関係。種子数は施肥の有無と関係なさそうだが、右の体サイズはどうも関係がありそうに見える。
実際 C=0, T=1 として各変数間の相関係数を見てみると(TRUE を 1 、FALSE を 0 とするために +0 している)、

> cor(d$y,(d$f=="T")+0)
[1] 0.01914445          # 種子数 と 施肥の有無

> cor(d$x,(d$f=="T")+0)
[1] 0.2806593           # 体サイズ と 施肥の有無

> cor(d$x, d$y)
[1] 0.2276909           # 体サイズ と 種子数

となり、施肥と種子数は相関がなく、施肥と体サイズ、体サイズと種子数には弱い相関がある、と一般に言われるような相関係数が得られる。
つまり、施肥と種子数の間にも(かろうじて)正の相関があるが、体サイズとの相関で十分説明できてしまっている。したがって施肥による効果は微調整レベル、負になっても不思議はない。そういう解釈をすることもできる。


また、勉強会の質疑で出ていた意見として、「同じ体サイズなら、施肥してそうなったものより、施肥をせずにそうなったもののほうがポテンシャルが高いと考えれば、施肥の係数が負になることは『直感に反しない』」という解釈が納得感が高くておもしろかった。そういう解釈をすることもできる。


一般化線型モデルに限らず統計モデルを現場で使ってみたときの「あるある」ネタとして、得られたパラメータの値、特に正負が「直感と異なる」場合に(上司などから)理由の説明を求められて困る、というのは鉄板の1つだと思うので、「みどりぼん」のような教科書でここらへんフォローしてくれててもいいのに、という気もちょっとする。
そういった時に上のような作文が求められるわけだが、逆にそういう主観的で作為的な作文術に結びついてしまうことを嫌って、この話題を深追いしたくなかったのかもしれない。


ただそういう作文は置いといたとしても、「データ解析で最も重要なのは、まず何はともあれ、そのデータをさまざまな方法で図示してみることです」(p16)とか、「統計モデリングにとりくむときに、そのデータを「いろいろな図にしてよく見る」点は何度でも強調しておきたいところです」(p44)とか、図示の重要性をたびたび強調する「みどりぼん」なら、上で描いた体サイズと施肥の関係を図示しといてほしかったかなあとは思うかな。


あと、p51 で z 値や Pr(>|z|) といった指標の説明をしておきつつ、施肥を説明変数に加えてパラメータの効果が「いよいよわからなくなってきました」というとき、なぜこのモデルでの z 値などを示さなかったのかも疑問。まあモデルの選択は次の章の AIC に全て託した、ということなのかなあ。


ちなみに z 値類を出してみるとこんな感じ。

> fit <- glm(y~x+f, data=d, family=poisson)
> summary(fit)

Call:
glm(formula = y ~ x + f, family = poisson, data = d)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-2.3977  -0.7337  -0.2023   0.6795   2.4317  

Coefficients:
            Estimate Std. Error z value Pr(>|z|)    
(Intercept)  1.26311    0.36963   3.417 0.000633 ***
x            0.08007    0.03704   2.162 0.030620 *  
fT          -0.03200    0.07438  -0.430 0.667035    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1 

(Dispersion parameter for poisson family taken to be 1)

    Null deviance: 89.507  on 99  degrees of freedom
Residual deviance: 84.808  on 97  degrees of freedom
AIC: 476.59

Number of Fisher Scoring iterations: 4

fT の z 値は -0.430 ( 0 から十分離れていれば有効なパラメータ)、Pr(>|z|) は 0.667035 ( 0 に近いほど有効なパラメータ)ということなので、fT は有効なパラメータとはなさそうだ、ということが3章の知識からだけでも推測できる、と言っていいのかな?


ちなみに AIC は、上の summary にも出てるが 476.59。
施肥を加えなかった場合の AIC は、

> fit <- glm(y~x, data=d, family=poisson)
> summary(fit)
(中略)
AIC: 474.77

なので、こちらからも施肥を加えない方がいい、という結論に。

PRML ガール 〜とある文芸部の統計女子〜

これは「PRMLガール 〜 文芸部のマネージャーが「パターン認識と機械学習」を読んだら 〜」の幕間的なお話です。
未読の方は先にそちらをどうぞ。




「先輩、先輩。我らが PRML ガールの評判聞きました?」
「聞いてない」
「やっぱり気になりますよねえ。ねえ?」
「僕は別に」
「……」
「……わかったわかった。どんな評判なの?」
「評判というか苦情ですかね。『 PRML ガール言うくせに PRML 関係ないやん!』みたいな」
「まあ、情報量とエントロピーの話しかしてないし」
「『あとがきがわりの AC ガール』(暗黒通信団刊行の書籍『PRML ガール』に収録)に至っては選択公理ですからねえ。そんな評判を跳ね返すためには、紛れもなく PRML ってテーマをここらで一発取り扱っておくべきなんじゃないか! と愚考するわけですよ。このあたくし」
「そういうことを言い出すと、黒幕がウォーミングアップを始めるからやめて欲しいのだけれど……それで本音は?」
「あの〜、PRML 8 章のグラフィカルモデルでどーしてもスッキリしないとこがあって〜」
「はいはい。余計な前振りいらないから。普通に聞けばいいのに」
「矢印のある方のグラフィカルモデルなんですけど」
ベイジアンネットワークだね」
「はい。あれの矢印の向きに、本質的な意味なんか無いような気がしてきちゃってて……なんのためにあるのかなあ、と」
「なるほど。どうしてそう思ったか……の前に、ベイジアンネットワークの矢印の定義は?」
「むー、さすがにそれくらいはわかってますよー」
「わかっているなら答えられるよね」
「はうっ。……えーとぉ、改めて聞かれると自信なくなるんですが、変数 a から変数 b に矢印が引かれているのは、b が a に依存している、みたいな……」
「依存とは?」
「待って待って、依存、うーん、条件付き分布 p(b|a) がある?」
「……今のところはそれでいいか。後でもう一度確認しよう」
「つまりなんか間違えてるんですね……」
「間違いというほどではないけどね。とりあえずその定義で考えても、a→b なら p(b|a) が、b→a なら p(a|b) があるということだから、矢印の向きに意味はある。どう?」
「あれれ? いや、そうじゃなくて、生成モデルって言うんですか、つまり同時分布 p(a, b) があるときに、これを乗法定理で p(a)p(b|a) と分解するとグラフは a→b になるけど、p(b)p(a|b) と分解すると b→a になるわけですよね。まあ p(a|b) と p(b|a) のどちらを考えるのが自然かとかはあるんでしょうけど、それに目をつむれば分解の選択は恣意的なので、矢印の向きに本質的な意味はないのかなあと」
「そうだね。その例なら」
「やっぱり! ……って、その例なら?」
「変数2個で例を作るのは無理があるから3個にして、設定も具体的にしようか。変数 a と b を『サイコロを振って出る目』、c を『その和の偶奇』とする。いい?」
「鉄板例ですね……んーでもそれってグラフは元からこの形に決まってるんじゃないですか?」

「自分から『分解の選択は恣意的』と言っておきながら、都合でそれを忘れるのはさすがにどうかと」
ぐぬぬ
「……というわけで、同時分布の分解を『恣意的に選んで』このモデルを解釈してみて」
「はーい……ではまず p(a, b, c)=p(a)p(b|a)p(c|a, b) と分解してみます。グラフはこんな形。



んで……それから……?」
「今、各変数は具体的にわかっている」
「え? ああ、p(b|a) とかが書けるってことですね。えと、a はサイコロの目そのままだから p(a) は毎度おなじみ 1/6 ずつ。p(b|a) は……もう一つのサイコロの目に影響受けないから、やっぱり 1/6 ずつ。p(c|a, b) は…… a と b が与えられたら c は確定だから、a+b が偶数なら p(c=偶|a, b)=1、以下省略」
「気づくことは?」
「気づく、というか、最初からわかってたことですが a と b は独立ですよね」
「独立とは?」
「独立…… b は a によらない……?」
「今何を求めていたの?」
「えっ? あ、そうか、p(b|a) は a によらない、p(b|a)=p(b) だ」
「そう。独立の定義そのまま。『b は a によらない』とかあいまいなことを言う必要はない」
「ぐはっ……もうあたしの HP はゼロです……」
「……このときグラフィカルモデルは?」
「ん〜、p(b|a)=p(b) だから a から b への矢印が消えてこの形に。なるほどな〜。



要領わかってきましたよ。次は p(a, b, c)=p(c)p(b|c)p(a|b, c) でやってみますね。まずグラフ描いといて。



c は偶数奇数だから p(c=偶)=p(c=奇)=1/2 ですね。p(b|c) は……ビミョウにややこしい……」
「表を書いたら?」
「そっか。a と b とで表にすると、

a\b 1 2 3 4 5 6
1
2
3
4
5
6


ふむふむ、これなら簡単ですね。c が偶数の時、b のそれぞれの確率は

p(b=1|c=偶) = 3/18 = 1/6
p(b=2|c=偶) = 3/18 = 1/6

あ、あれ? 変だな〜」
「どうかした?」
「全部 1/6 になります」
「そうだね」
「p(b|c)=p(b) になっちゃいます」
「なるね」
「ダメでしょう!?」
「なぜ?」
「だって、c から b への矢印が消えて



ってグラフになっちゃいます。同じモデルが2種類の全く違うグラフを持つとか、どう見てもまずいじゃないですか」
「つまりどこかが間違っている?」
「それがさっきから見直しているんですが、どこも間違えてなくて……」
「間違ってないからねえ」
「えーっ! いやでも。え〜……。そんなんアリなんですか?」
「そもそも、モデルの情報をわずかな丸と線でどれくらい表せると思う?」
「そりゃまあ全部ってことはないでしょうけど」
「一部しか表せないなら、『どの一部を表すか』という選択が生じる。つまり、グラフィカルモデルによる表現は一意ではない」
「はぁ〜なるほど。分解に恣意性があるようにグラフにも恣意性があるわけですね」
「普通は構成から自然に決まるグラフしか見ないから意識しないけれどね。これがまず一つわかること」
「もう一つあるんですか?」
「最初のあなたの疑問の答え。今得た2つのグラフィカルモデルを見比べてみて」
「最初の疑問って矢印の向きの話ですよね。でも、向き以前にグラフの形というか、切れているところがぜんぜん違いますよ」
「いいね。それが答え」
「む〜〜〜。禅問答じゃないんですから、もうちょっとわかりやすくプリーズ」
「では、切る前と切った後を並べてみよう」



「これ見せられてもやっぱりわかりませんよう。これ見てわかることなんて、向きが違うと切れるところが違うってことくらい……あ」
「気づいた?」
「左は a→b, b→c, a→c 『だから』 a→b が切れる。右は c→b, b→a, c→a 『だから』 c→b が切れる。向きが逆なら切れる場所が変わる!」
「そう。つまり、ベイジアンネットワークがこの構造を採るためには、各辺はこの向きである必要がある」
「この向きがあって初めてこの形のグラフになるんですね……ん? ちょっと待ってください」
「何?」
「こっちの後から描いた方のグラフでも、a と b って独立じゃあないですか。だからもともとそこは切れるんじゃないですか?」
「そして先ほど b と c が独立とわかったのと同様に a と c も独立と示せるので、すべての辺が切れる、と」
「あれれ?」
「ちょうどいい。矢印の定義の話に戻ろう」
「あたしのが間違えてたやつですね」
「だから間違っていたわけではないよ。矢印が条件付き分布に対応するのはいい。ただ、親の変数は複数を許す。つまり、p(x|y_1, …, y_n) があることをグラフを用いて次のように表す」



「そうか! 指している先が同じ矢印は全部セットなんですね」
「だから a と b が独立であっても、p(a|b, c) で引いた辺の片方を勝手に消すことは出来ない」
「a と b、a と c が両方とも独立でも、 a と b, c の組が独立とは限らないですもんねー」
「どう? 疑問はかなり解消されたと思うけど」
「はい、ストンときました! でも考えたんですけど、『この構造のためにこの向き』ということは、もちろん一つ一つの矢印の向きも大事なんでしょうけど、『どこが切れているか』のほうがもっと重要なのかなあ、なんて思えてきました」
「そうだね。PRML にもそう書いてあるし」
「うんうん……えっ!? 書いてあるんですか?」
「確かこのあたり……あった、下巻 73 ページ」
「『グラフはリンクが存在しないことをもって分布のクラスの性質に関する情報を表現する』うわーほんとだ、まんま書いてある……なんかもっと目立つように書いて、大事なんですよ! って主張してくれないと見逃しちゃいますよう」
「一応太字で記されてはいるのだけれどね。四倍角で書いてあってもいいくらいではあるだろうね」
「よんばいかく?」
「知らないの? 文芸部なのに。ほら、ワープロで文字を縦横二倍の大きさに……」
「わーぷろ?」
「……文章を打つときに。会誌用に原稿を清書とか」
「ああ、ワードのことですか」
「ワードはパソコンでしょう。そうじゃあなくて、専用の。インクリボンで印刷する……」
「いんくりぼん?」
「……」
「……そういえば先輩の原稿って、文字がギザギザしてムラがあって、なんかちょっと昔風で味があるなあと思ってたんですが、あれはわざとではなく?」
「おとうさ……父が貸してくれて……最新の機械だって……まだ普及していないからインクリボンも手に入りにくいので、大事に使うようにと……」
「ひょっとしてですけど、その機械、印刷うるさかったりしません?」
「……する……」
「あの〜、大っ変申し上げにくいんですが、それ、たぶん絶対からかわれてますね。きっと」
「……また、だまされ……いや、なんでもない」
「……許せませんね」
「いや、別にあなたが怒ることじゃあ……」
PRML では鋭い切れ味を見せる才媛ながら、普段は迂闊なお人好しキャラとか、ずるいです!」
「え……えええー! ぼ、僕!?」
「あたしの立ち位置のことも考えてください!! 読者が許してもあたしが許しません!!!」
「そんなこと言われても……いえ、ごめんなさい……」
「今度から気をつけてくださいね!」


(おしまい)




新春お年玉駄文……のはずが、仕上げに時間がかかりすぎて危うく2月になるところだった。ふう。

今までの分:

「機械学習 はじめよう」最終回

gihyo.jp で続けていた連載「機械学習 はじめよう」がとうとう最終回を迎えることができた。


初回の 2010年 7月から 3年以上にわたる連載がなんとか完結できたのも、読んで下さった方々、担当編集者の高橋さんのおかげ。大感謝。
後半は2〜4ヶ月に1回のスローペースで全21回、年内にすっきり終わりたいね、12月25日公開ならクリスマスプレゼントって言えるねw と、難産ながらそれなりにまとまったかと。


言いたいことはだいたい連載の中に置いてきたので、付け加える事はそんなにないのだけど。
PRML機械学習を勉強していたときに、機械学習の国ではいろんなことが「あたりまえ」になっていて、特に説明もなしに使われるということに非常に戸惑った(まあどんな分野でも多かれ少なかれあることだけど)。
そういう「あたりまえ」は中の人になってしまうと「あたりまえ」すぎてわざわざ説明しないといけないということに気づきにくくなっていくので、その気持ちが新しいうちに後に続く人たちのためになんとか残しておきたい、という意識で書き続けてきた。


機械学習」でぐぐったら Wikipedia の次にこの連載が並ぶので、今では初学者の入り口の一つとなっている、と言ってしまったら自意識過剰だろうか。
そういうものを書いて、終わらせることができたのはかけねなしに嬉しい。


内容への指摘・お叱りは今後も随時受け付けているので、何かお気づきの事があればブログのコメントや twitter (@) などへ。

WebDB Forum 2013 で「どの言語でつぶやかれたのか、機械が知る方法」について発表しました。

11/27-28 に京都で開催された WebDB Forum 2013(第6回 Webとデータベースに関するフォーラム) の、サイボウズの技術報告セッションにて「どの言語でつぶやかれたのか、機械が知る方法」という題で発表させてもらいました。聞いて下さった方(ustream 中継含む)、関係各位、ありがとうございました。


発表資料はこちら。



テーマは過去に発表済みの「∞-gram ロジスティック回帰を使った短文言語判定」なので、技術的に目新しいことは特にない。実装が新しくなったり、細かい工夫はちらほらなくもないんだけど、そのあたりは基本端折ってしまったし。20分ちょっとの発表時間でモデルの話をすると大火傷を負うことは身にしみてわかっちゃったんだ……。
というわけで、「twitter やチャットといったネット上の informal な場で、諸言語が正書法からはみ出しまくっている様子」を中心にお話しした。それでも20分だとやっぱりショートバージョンになってしまうんだけどね。なんなら一時間でも二時間でも話せてしまうんだけど、モデルの話と違って途中で打ち切られても問題ないw
twitterfacebook などにあふれるテキストを使って、日本語なり英語なり、特定の言語だけを対象としたサービスや研究だけではなく、多言語をターゲットとしたものを考えるなら、今回のような話は知っておいて損はないと思う。


もともとの言語判定器は ldig という名前で公開しているのだが、こちらは扱いとしてはプロトタイプ版であり、API 的なものは整備していない。
実装も Python で、学習にまる1日かかるていたらく。


そこでぼちぼちと C++ 版を実装していたのだが、今回の発表に合わせてとりあえず最低限の体裁を整えてリポジトリにコミットしておいた。しかしドキュメントもまだないし、学習済みモデルも x64 ビルド用しか付いていない(size_t をそのまま吐いているので、プラットフォームによってフォーマットが違ってしまっている)。

ビルドは今のところ Windows のみで、 Visual C++ 2010 用のプロジェクトファイルが付いている(C++11 をちょいちょい使ってるので、それより前の VC ではビルドできない)。gcc on Linux でも微調整で通ると思うが、手を付けてない。ごめん。


なおビルドには cybozulib が必要なので、以下のリポジトリから ldigcpp のディレクトリ下にチェックアウトする必要がある。

岡野原さんの esaxx も必要だが、こちらは ldigcpp のリポジトリに同梱させていただいている。


というわけで、現状では余程の物好きでなければ手を出す気にもならないと思うが、ゆるゆると整備していく、かもしれない。
元の python 版 ldig と比較しての第一の変化はやはり速度だろうか。まる1日かかっていた学習が、20分で完了する。この速度ならパラメータを色々変えて実験してみたり、アホみたいに cross validation 回しまくったりできるので、やはり速いは正義と実感。


もう一つの変化は、ラテン・アルファベット以外の言語にも対応したこと。リポジトリにある学習済みモデルは、以下の50言語に対応したものとなっている。

特に Arabizi(とは何かについては発表資料参照) やモンゴル語(キリル文字表記)は Google 翻訳や Choromium の言語判定器も対応していないので、超ごくごく一部の人には値打あるのでは。精度はまだちょっと低いのだけどね。
本当はバスク語ガリシア語やスロバキア語やスロベニア語やネパール語マラヤーラム語や……なども用意していたのだが、さすがにツイート100件にも満たないのは除外した。


必要な 50言語コーパスは以前の ldig で作った 50万件は一部のみ再利用したが、40万件(訓練)、7.6万件(テスト)を基本新しく作りなおした。なぜそのまま再利用しなかったのかというと、旧コーパスの大部分は twitter のステータス ID を捨ててしまっていたので、配布できる形式ではなかったからだ。
今回の新コーパスは全部ステータス ID が付いているので、(ステータス ID, 言語ラベル) の組で配布できる。
が、ステータス ID から実際のツイートを取得するにはそういうスクリプトを書かないといけないんだけど、自分にはそれ必要ないので、用意する動機がない。スクリプト無しでデータだけ配布してもいいんだろうけど、そしたら「開いたら数字しか書いてないんだけど、どうしたらいいの?」というメールとツイートと issues への書き込みが確実にやってくる(苦笑)。
というわけで、こちらもそのうちおいおい。
ちなみに、twitter には API 呼び出し回数のキャップ(15分180回)があるので、40万件を取得するには約23日かかる。まあこういうのを必要としている人はそれでも全然いいから欲しいと言うだろうけど。

第4回 #DSIRNLP で Active Learning 入門について話しました

@overlast さん主宰の データ構造と情報検索と言語処理勉強会(DSIRNLP) の第4回にのこのこ参加して、Active Learning 入門なるものを発表してきました。お疲れ様でした&ありがとうございました>各位


こちらが発表資料。



入門とか偉そうに歌ったけど勉強し始めてまだ1月半もないので、実は入門しているのは中谷本人である。
動機は資料にも書いたとおり、ドメイン適応をドメイン知識のある人が低コストで行うのに Active Learning の技術が使えるのでは、というあたり。
ここまで実験した範囲でそれなりの手応えはあるものの、非常に単純なテキスト分類問題で試しただけなので、もう少し難しくて現実的なタスクでもいろいろ試してみたいと思っている。


発表資料に間に合わなくて20数回の試行で Query-By-Committee の箱ひげ図を描いてしまっていたが、50回の試行も終わったのでそちらの図をここに載せておこう。大幅に違うものにならなくてよかった。



ああ、そう言えばうっかりチャートを縦に見る話ばかりしてしまったが、本当は横にも見ないといけなかったんだった。大失敗。
つまり「 active learning を適応して得た精度を得るために、random sampling だと何倍の訓練データが必要か」。
必要なグラフは資料に載っているので、興味のある向きは是非自分で確かめてほしい。active learning の有用性が実感できるだろう。


あと、こちらは発表時間その他から断念したのだが、oracle sampling(笑) や Expected Error Reduction の指標と相関性が高くて軽量な指標があったりしないかな、と探してみたりしていた。
それ用の図も蔵出しておこう。



これは横軸が MCMI[min] (Guo+ 2007)、青/赤/黄緑がそれぞれ対応するデータの least confident / margin sampling / entropy-based の指標を縦軸に取った散布図。こうしてみると、少なくとも線形な相関は全く無さそうだな〜……とわかってしまう。難しいのう。
資料作成の寝不足がまだ解消されてないのでこのくらいで。

夏のプログラミングシンポジウムで「数式を綺麗にプログラミングするコツ」を発表してきました

8/25 に開催された夏のプログラミングシンポジウム 2013 にて、「数式を綺麗にプログラミングするコツ」というお話をさせてもらいました。運営、発表に携わった&参加者のみなさん、会場のドリコムさん、お疲れ様でした&ありがとうございました。お水おいしかったです。

こちらが発表資料。

www.slideshare.net

この発表、実は一昨年に Tokyo.SciPy #2 でやらせてもらった「数式を numpy に落としこむコツ」のブラッシュアップ版である。

変更点は R のサンプルコードの追加と、表現をよりわかりやすくリライトしたという2点であり、紹介されているサンプルも含め本質的にはほぼ同じ内容である。手抜きっぽくてごめん。
本当は他の例を追加したかったのだけど、なにぶん観測範囲が狭くて、紹介にちょうどいい例(難しすぎず、易しすぎず)を機械学習ネタ以外で見つけることが出来ず。これ以上 PRML からネタを引っ張ってくると、「ふーん、これって機械学習限定なのね」みたいな空気になってしまうんじゃあないかと。
まあ発表時間的に3例は難しいというのも。


他の例も見てみたいという方には、こちらの記事で同じく PRML 13章の隠れマルコフモデルの推論に出てくる Baum-Welch の更新式を、「コツ」にしたがって誰でも実装できる形に書き直す手順を追っかけているのでよろしければ。


言いたいことは「紙と鉛筆が最強」なので、最悪それだけでも。
こういうプログラミングがすご〜く得意な人は、ロジスティック回帰の更新式だろうが Baum-Welch だろうが、式を10秒ぐらいじーっと見つめたら、ぴらっとコードを書けてしまったりするんだけど、そんなのは誰にでもできることではないので真似しちゃあダメ。




他の方の発表もいろいろ楽しませていただいたが、中でも JFEスチール 茂森氏の発表がおもしろかった。
でもこれってプロシンっぽくないんでは〜とちょっと心配したが、twitterドメイン知識の大切さがよくわかったといったような感想が続出しているところを見て、ああなるほど、プロシンでやる意味があったんだなあと実感。


実務でデータ解析をしようと思ったら、ドメイン知識バリバリの人でないとモデルもルールも書けない&超絶泥臭い努力の積み重ねの固まりというのは、テキストマイニングシンポジウムとかに行って、企業の方の発表とか聞くとめちゃめちゃ実感させられるので、今回のプロシンで蒙を啓かれてしまった! もっとそういう話を聞きたい! という人は行ってみると幸せになれるかも。
え? ちょうど再来週に第3回のテキストマイニングシンポジウムがあるんだ。へー(ステマ……じゃあないよ、別に)

Active Learning を試す(Uncertainly Sampling 編)

教師あり学習の教師データの作成はとても大変。例えば、twitter 言語判定のために、訓練・テストデータあわせて70万件のツイートに言語ラベルを振った人もいたりいなかったり。


Active Learning(能動学習) はそんな教師データ作成のコストを抑えながらモデルの性能向上を測るアプローチの1つ。
具体的には、正解なしデータの中から「こいつの正解がわかれば、モデルが改善する(はず)」というデータを選び、Oracle と呼ばれる「問い合わせれば正解を教えてくれる何か(ヒント:人間)」にそのデータを推薦、得られた正解付きデータを訓練データに追加して、以下繰り返し。


しかし「こいつの正解がわかれば、モデルが改善」を選び出す基準なんて素人考えでも何通りも思いつくわけで、実際 Active Learning のやり口は幾通りもある。
Active Learning Literature Survey (Settle 2009) ではその戦略を大きく6つに分類している。

  • 1. Uncertainly Sampling
  • 2. Query-By-Committee
  • 3. Expected Model Change
  • 4. Expected Error Reduction
  • 5. Variance Reduction
  • 6. Density-Weighted Methods


この記事では、まず 1. Uncertainly Sampling を試す。
これは「現時点のモデルで『最も不確かなデータ』を選ぶ」、柔らかく言うと「分類予測に最も自信がないものを選ぶ」ということ。
代表的な Uncertainly Sampling として、(Settle 2009) では 3 つの方法が紹介されている。ああ、ここでは教師あり学習一般ではなく、分類問題をターゲットに説明していく。

Least Confident
「最も確率の低いラベル」の確率が最も高いデータを選ぶ
Margin Sampling
(「1番目に確率の高いラベル」−「2番目に確率の高いラベル」)が最も小さいデータを選ぶ
Entropy-based Approach
予測分布のエントロピーが最も大きいデータを選ぶ


いずれも、どれか1つのラベルの確率が 1.0 であるデータは最も選ばれにくいし、全てのラベルの確率が等しいデータは最も選ばれやすい。まあ、いずれも至極妥当な印象がある。
線形分類器でこれらの戦略を取ると、選ばれるデータ点は分類平面周辺にもっぱら集中することになる。


Active Learning は理論的な評価も一部行われてはいるが、基本はヒューリスティックなアプローチということもあり、やっぱり実際に試さないことにはよくわからない。そこでまずは簡単な例としてロジスティック回帰に適用してみる。
ちなみに、2値分類ではこの3つの手法は同じデータを選択することになる(ことに気づかず、しばらく2値分類で頑張っていたのはナイショ)ので、多クラス分類をターゲットとする。


以下の様な設定で Uncertainly Sampling に分類される3手法 Least Confident, Margin Sampling, Entropy-based Approach と、baseline としてランダムにデータを選択する Random を比較した。
まずデータは再現実験しやすいよう NLTK の Reuters コーパスにて、crude, money-fx, trade, interest, ship, wheat, corn の 7 カテゴリを選び、この中の 2 つ以上のカテゴリに同時に属する文書を除外した 2256 文書を使った。
学習器は自分で実装してもいいが、何十回も学習することを考えると高速なものがいいので scikit-learn を使う。特徴量は単語(小文字化 & lemmatized)の出現数とした。 tf-idf の結果も一応見てみたが、精度に誤差程度の差しかなかったのでシンプルな方を採用した。


ここからそれぞれの戦略に従って選んだデータを訓練データに加えていくわけだが、最初に各カテゴリに1つ以上のデータがないと scikit-learn の分類器が学習してくれないので、初期データとしてランダムに1つずつ選ぶ。ちなみに、baseline(ランダム) 以外の3手法は初期値から後の選択は決定的である(評価値が同じ場合、numpy の arg 系はインデックスの一番若いものを取る)。
選択するデータは訓練データ数が 300 になるまでとし、残りのデータの正解率を毎回算出していった。


と、設定話はこれくらいにして、いよいよお楽しみの結果。
実装したスクリプトと、1回実行した時の正解率の推移グラフを挙げておく。


初期値依存なので細かい結果は毎回違うわけだが、このグラフから読み取れる通り、

  • Margin Sampling は精度が最も高く、かつほぼ安定している
  • Least Confident は最終的に Margin Sampling に近い精度に達するが、若干不安定
  • Entropy-based Approach はかなり不安定で、その精度は他の2つどころか Random を下回ることも珍しくない


という傾向は何回実行しても同じだった。
実行する前は Entropy-based に期待していたので、この結果は正直ショック。
Margin Sampling は実は ldig で訓練データを作る際にラベル付けするデータの選択(手動)にまさにこの指標を使っていたので、この指標が一番成績がいいのは少し嬉しくはある。


データやモデルにも強く依存するので、この傾向が常に成り立つとかそんなことは言えない。なんてわざわざ釘を刺す必要もないくらいだろうが、念のため。
次は Query-By-Committee を試す予定。


追記
ちょっとわかりにくいかなーと思ったので、訓練データ 100個までの推移を拡大した図を追加。

【/追記

参考文献