読者です 読者をやめる 読者になる 読者になる

影の薄いカーネル密度推定にもっと注目してあげてほしい!

おはようございます。

ここ最近研究発表と論文読み会と課題に追われて、研究のアイデアはたまってきたのに実験に移る時間がないりとささんです。

いやもうさあ、再来週も発表あるし今週も発表だったし論文読み会のために自分の研究分野とは無関係の論文読まなきゃだし研究させる気があるのかいって感じです(笑)

 

最近ハマっていて、そんな研究のイライラを癒してくれるものがファミマのピザまんです。←

あれ本当に食べた瞬間チーズがびよーんってなるくらいトロトロに溶けていて本当においしいんですね(*´ω`)

なんか今100円セールやってるみたいなので食べたことない方はぜひ食べてみてください。

 

 

さてさて、機械学習には機械学習の大支柱とも言うべき強力なアルゴリズムがいくつかあります。

SVMしかり、CNNしかり、k-meansしかり、MCMCしかり...

でもそんなド派手で表立って活躍するアルゴリズムの陰に隠れて、ちゃっかり有用で、データを運用するうえで、つまり人間がデータを解釈しそれをどのように実社会の抱える問題に適用させていくかを決めるうえで、非常に重要なアルゴリズムも存在します。

 

今回はそんなアルゴリズムの一つ(だと僕が勝手に思っている)でもっともっと日の目を見てもいいんじゃあないか?と思っている、カーネル密度推定についてメモ書きしていこうと思います。

 

カーネル密度推定ってなんですのん?

そういえば最近8.6秒バズーカ見ない...(笑)

それはさておき、カーネル密度推定とは一言で言ってしまえばヒストグラムの連続バージョンです。

ヒストグラムとは、ある変数が各区間内であるサンプルの数を数え、その数を棒グラフにしたやつでしたね。

カーネル密度推定では、そのサンプルの分布を連続な関数として表現することができます。

カーネル密度推定により得られる分布曲線は次のように表されます。

http://www.fukudat.com/texcrop/render.php/texcrop.png?tex=%5Cbegin%7Balign*%7D%0Ap%28x%29%3D%5Cfrac%7B1%7D%7Bnh%5E%7Bd%7D%7D%5Csum_%7Bi%3D1%7D%5E%7Bn%7DK%28%5Cfrac%7Bx-x_%7Bi%7D%7D%7Bh%7D%29%0A%5Cend%7Balign*%7D&resolution=150&font=times&jfont=hiragino&opaque=off&bold=off

ただし、nはサンプル数、x_iは各サンプルの座標、dは入力xやx_iの次元数、hはバンド幅、Kはカーネル関数と呼ばれるものになっています。

Kは全入力空間で積分した結果が1であるという正規化条件を満たさなければなりません。

一般的にはKにはガウスカーネルを用いられることが多く、それを考えるとバンド幅というものは、標準偏差のようなものだとわかります。

ようは一点が周囲の領域の関数に及ぼす範囲の大きさを示しています。

 

非常にシンプルな形で書けるカーネル密度推定!
実際にこれを使ってみましょう。

この程度なら自分で実装するのも簡単そうですが、scipy大先生の力を借りると一撃なので、素直にscipy大先生に頼ります。
まずは必要なライブラリをインポートします。

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde

次に、推定する分布をサンプルしてみましょう!
普通のガウス分布でもいいのですがそれだけだとつまらないので、2つばかりガウス分布を混ぜてみます。
よく使われるフツ―のヒストグラムではこのような分布になります。

random_seed=np.random.randint(2,size=10000)
samples=random_seed*np.random.normal(loc=40.0,scale=20.0,size=10000)+(1-random_seed)*np.random.normal(loc=120.0,scale=30.0,size=10000)
plt.hist(samples,bins=30)
plt.show()

f:id:phyquar:20170115072406p:plain

うーん...
これを見るとなんかヒストグラムで全然いい感じがしますね!←

でもでも、ヒストグラムだとビン幅(棒グラフ1個の横幅)の調整をいい感じに調整してあげないといけません(カーネル密度推定もバンド幅の調整が必要だということには目をつむります笑)。
要するにこの棒グラフが細かすぎるとちょいちょい棒の間に一つもサンプルが入らない謎な分布ができたり、一つの区間内に入るサンプルが少なくなるためその区間内のサンプル数に意味が見出しづらくなりますし、逆にビン幅が太すぎると、真の分布がなかなかみえてこなかったりします。こんな感じで↓

f:id:phyquar:20170115073251p:plain

f:id:phyquar:20170115073414p:plain

取りうる変数の値が連続で、かつサンプル数が非常に多い場合、その分布の全容を知るには、ヒストグラムを使うよりもむしろカーネル密度推定を使うことをおすすめします。
視覚的にも見やすいですし、多分これで確率分布を求めておけばMCMCとかを使って、この分布にしたがったサンプルを自分で生成できるんじゃないかなあと思います。
早速使ってみましょう(*^-^*)

search_range=np.linspace(np.min(samples),np.max(samples),num=10000)
kde_model=gaussian_kde(samples)
plt.plot(search_range,kde_model(search_range))
plt.show()

f:id:phyquar:20170115074622p:plain

うん。連続な分布が描写できました!(笑)
ちなみにさっきMCMCを使えばリサンプリングできるんじゃなかろうかといいましたが、このscipy.stats.kde_gaussian()には.resampleメソッドがあり、推定した確率密度関数に従うサンプルを生成してくれるそうです。
ヒストグラムを使っているのではこんなことはできません。
これらの作業がたったの数行で終わってしまうなんてやっぱりカーネル密度推定ってすごい!!(ライブラリがすごいだけかもですけど笑)
研究でサンプルがいくつも取れて、その値が連続値なときはヒストグラムもいいですけどぜひぜひカーネル密度推定君をつかってあげてください。
僕はこのカーネル密度推定、知っている方は知っていますけど、もっともっとメジャーな手法になってもいいんじゃないかなあと思ってます。
ヒストグラムの単純かつ明瞭さの陰に隠れてしまっていますが(笑)
プレゼンの資料とかにも使いやすいと思います。


今日は靴底に穴が空いたのでこれから靴を買いに行きます!
ではまた!