作者別: 毬坂 百舌鳥

最も簡単な最尤推定とMAP推定

最も簡単な最尤推定とMAP推定

最近「パターン認識と機械学習」という本を読んでいて、「最尤推定」と「MAP推定」という言葉が出てきたんだけど、本を読んだだけでは今ひとつ理解できなかった。ので、自分の中での整理のために簡単な例を使って説明してみる。間違ってたら教えてください。

1. 最尤推定

今簡略化のために、世の中には4割バッターと1割バッターしかいないとする。そして、ある人が1打席目はヒット、2打席目は三振だったとする。その人は4割バッターだったのか、それとも1割バッターだったのかを推定したい。

まず打率が4割か1割かわからないので、それを仮に「θ」としておく。θは4割バッターだったら0.4だし、1割バッターだったら0.1になる。

で、1打席目はヒット、2打席目が三振となる確率は、(2打席目の確率が1打席目の結果に影響されないとすると)

θ × (1 – θ)

になる。これがいわゆる「尤度関数」というもの。尤度っていう言葉は聞き慣れない言葉だけど、「今起こった事象がどれぐらい有り得そうか」を数字で表すものだと考えたらいい。

で、これを4割バッターの場合と1割バッターの場合でそれぞれ計算する。

4割バッター:0.4 × (1 – 0.4) = 0.24

1割バッター:0.1 × (1 – 0.1) = 0.09

つまり、0.24と0.09なので、どちらかと言えば4割バッターの方が有り得そうだということになる。これが最尤推定。

まとめると、

  1. 求めたいパラメータを変数とする(今回で言えば、打率θ)
  2. それを使って今起きた事象の尤度関数を定義する(今回で言えば、θ × (1 – θ))
  3. 尤度関数が最大になるような変数が求めたいパラメータ

2. MAP推定

上の例の場合、「4割バッターってそんなにそうそういるのか?」という事が考慮されていない。なので、ここでは仮に4割バッターは世の中に2割いて、1割バッターが8割だということにしよう。

つまり、打率θというものはどれか一つに固定化されるようなものではなく、確率的に決まるものだと考える。具体的に言うと、どこかから知らない人を連れてきたら、その人が4割バッターである確率は 0.2 だ、ということだ。これを「事前確率」という。

で、今1打席目ヒット・2打席目三振という事象をヒントと考えたら、その0.2という確率はどうなるだろう?これを「事後確率」といい、ベイズの定理を使うと

「事後確率」は、「尤度関数」×「事前確率」に比例する

という事がわかっている。これを4割バッターと1割バッターでそれぞれ計算する。

4割バッター:0.24 × 0.2 = 0.048

1割バッター:0.09 × 0.8 = 0.072

という事で、0.048 と 0.072 なので、1打席目ヒット・2打席目三振という事象を踏まえた事後確率は1割バッターのほうが高い、なので、1割バッターだろうということになる。これがMAP推定(最大事後確率推定、MAP は Maximum a posteriori の略)。

ちなみに、本当の事後確率は 0.048 + 0.072 = 0.12 で上の数字を割ったものになる。(4割バッターだったら、0.048 ÷ 0.12 = 0.4)MAP推定では事後確率が最大になるパラメータを求めたいだけなので、事後確率そのものを計算する必要はない。

まとめると、

  1. 求めたいパラメータを変数とする(今回で言えば、打率θ)
  2. パラメータを確率的に決まるものと考え、事前確率を定義する(今回で言えば、4割バッターが2割の確率で存在する事)
  3. 今起きた事象の尤度関数を定義する(今回で言えば、θ × (1 – θ))
  4. 尤度関数 × 事前確率が最大となる変数が求めたいパラメータ

MAP推定を使うと、今回のように「4割バッターはこれぐらいしかいなさそう」というような経験に基づく主観を盛り込むことができるようになるのがメリット。しかし、逆にそれが嫌というケースもあるだろう。

Photo by Mike Szczepanski on Unsplash

広告
【レビュー】Python機械学習プログラミング ―達人データサイエンティストによる理論と実践

【レビュー】Python機械学習プログラミング ―達人データサイエンティストによる理論と実践

★★★★☆

やっと読み終わりました。数式を読み解くのに苦労して何度か挫折しましたが、今回は最後まで読み終えることができました。

事前に「Pythonではじめる機械学習」を読んでいたということと巣籠先生の講義を受けていたというのが大きかったように思います。この本は結構数式が出てくるのですが、分かりやすく書かれていないので、理解するのが大変です。数式をちゃんと自分で読み解ける人でなければ挫折してしまう人が多いんじゃないでしょうか。

しかし、最初の2章・3章さえ乗り越えられれば、あとはそれほど難しいことは出てきません。

気になったのはあまり体系的に記載されていないように感じたこと。重要な概念がいろいろな章に散らばって書かれているので、その点は「Pythonではじめる機械学習」の方がよいと感じました。ただ、あっちは数学理論の解説がほとんどないので読んでいて物足りなさを感じます。その点、この本はしっかり数学理論についても記載されていますし、Webアプリケーションへの実装についても触れられているので、そこはよいところです。

私のようにこの本で挫折した人はまず「Pythonではじめる機械学習」を読んで、それからこの本に戻るというのが良いかもしれません。ただ、内容はかなりかぶっています。

また、私が読んだのは第1版でしたが、第2版はディープラーニングについて大幅に加筆されており、TensorFlowによる実装についても解説されているようです。今から購入される方はぜひ第2版を購入しましょう。

KaggleでTitanicに挑戦

KaggleでTitanicに挑戦

こちらのサイトを参考にさせていただいた。

使用したのはランダムフォレストでスコアは0.77511。6236位でした。

上記のサイトを参考にさせていただきつつ、多少工夫した点は以下の通り。

  • Pclass を One-hot でエンコード
  • Embarked も One-hot でエンコード
  • いろいろモデルを構築する前に、 describe() とか corr() とか scatter_matrix() とかで訓練データを分析
    • 意外とAgeは相関がない
    • 意外とEmbarkedは相関がある
    • 分類問題で scatter_matrix() はあんまり面白くない
  • LogisticRegression と RandomForestClassifier でグリッドサーチ

Azure Notebooksで公開しています。

上位のスコア1.0000とかっていったいどうなっているんだろう。どう考えても無理そうなんだけど。

Pandasコード備忘録

Pandasコード備忘録

1.pandasでCSVを読み込む時に日付インデックス

parse_datesとindex_colパラメータを使えばOK。日付データと時間データが別の列に入っていてもOK。

2.ある時刻からある時刻までの1分おきの配列を作る

Pythonで2つのdatetimeオブジェクトの期間の1日ごとに処理をする – Misc Notesを参考にさせていただいた。分単位の配列がほしかったのと、endを含めたかったので一部修正。

これで作った配列を元にDataFrameを作ってmerge(外部結合)すればデータが存在しない時間帯のデータを追加できる。

3.時刻順にならんでいるDataFrameで次の時刻のデータとの差分を取る

ある時刻の株価、その次の時刻の株価・・・というDataFrameで、時刻間の株価の差がいくらかを求める方法。日経平均株価の予測をした際にはfor文を回したが、非常に遅かったので高速化する方法を考えた。

  1. 元のDataFrameから2番目以降のDataFrameを作成
  2. インデックスを振り直し
  3. 元のDataFrameと2番目以降のDataFrameを横にconcat
  4. それぞれの行で差分を計算して列追加

これでかなり速くなった。

 

 

Keras(LSTM)による株価予測モデルはイマイチ

Keras(LSTM)による株価予測モデルはイマイチ

昨日日経平均株価の予測をやってみたので、今度は同じ手法で為替(ドル円)を予測できるかチャレンジしてみた。

こちらのサイトから1分足のデータがダウンロードできるので、これを使用。昨日と同じように、対数を取って、差分を取って、CLOSEの標準偏差が1になるように調整した。

データ量があまりに多く、MemoryErrorが多発するので、学習・テストデータを直近の10万件に絞った。(Azure Notebooksは4GBしかメモリがない)また、今回は前回と違って、CLOSEだけではなくHIGHとLOWも使った。

で、24時間分の1分足データを入力として、1分後のHIGHが0.5(標準偏差の半分)よりも高くなるかどうかを予測するモデルを作成した。

結果は失敗。なぜか常に高くなると予測するモデルになってしまった。

入力データの時間量を増やしたり、LSTMの次元を変えたり、データ量を増やしたりしたが、結果は変わらず。正解ラベルの数は低くなる方が多いので、常に低くなると予測するのであればまだわかるのだが・・・。どこかバグっているのかもしれない。

で、ふと昨日の結果もあやしいなと思って混合行列を作ってみたのが上の画像。予想通りおかしなことが起こっていることがよく分かる。モデルはほぼ常に「+1」を予測しているが、真実の値は他のクラスにも散らばっている。

どうもこのモデルは、わからない場合は「+1」を返すようになっていて、たまたま正解に「+1」が多かっただけのようだ。

世の中そう簡単に儲けられる話がある訳がない。