0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ポアソン混合モデル その4:ポアソン混合モデルによる学習、EMアルゴリズムの適用<実装編-1:データの生成>

Posted at

ポアソン混合モデル その4:ポアソン混合モデルによる学習、EMアルゴリズムの適用<実装編-1:データの生成>

今回は、EMアルゴリズムを使ってポアソン混合モデルによる学習を行うことにする。実装編です。

理論編はこちら。

ポアソン混合モデル その3:ポアソン混合モデルによる学習・推論、EMアルゴリズムの適用<理論編>
今回は、ポアソン混合モデルからデータを生成することにしてみよう。

次回は、この記事で作成したデータに基づいて、ポアソン混合モデルによる推論を行う。

生成モデルとしてのポアソン混合モデル

ポアソン混合モデルからデータが生成する過程(簡略ver)は以下。

1.パラメータのてきとうな初期化

クラスタの混合割合 $ \textbf{π} $ と $ λ_k (k = 1, 2, .. , K) $ をてきとうに初期化する。

2.クラスタの割り振り

クラスタ番号を表すベクトル $ \textbf{s}_n (n = 1, 2, .., N) $ が、$ Cat(\textbf{s}_n|\textbf{π}) = \prod_{k=1}^{K} {\pi_k}^{s_{n,k}} $ からサンプルされる。

3.ポアソン分布からのサンプリング

$ x_n (n = 1, 2, .., N) $ が、$ \prod_{k=1}^{K} Poi(x_n|λ_k)^{s_{n,k}} $から サンプルされる ($ s_n $ に対応する一つのポアソン分布からの値が採用される)。

1.パラメータのてきとうな初期化

クラスタの混合割合 $ \textbf{π} $ と $ λ_k (k = 1, 2, .. , K) $ を適当に初期化する

てきとうに、$ K=3 $ 、 $ π = (\frac{3}{6}, \frac{2}{6}, \frac{1}{6}) $ 、 $ \textbf{λ} = (5, 10, 20) $ としよう。

はい完了。

import numpy as np

K = 3
pi_vec = np.array([3/6, 2/6, 1/6])
lam_vec = np.array([5,10,20])

2.クラスタの割り振り

クラスタ番号を表すベクトル $ \textbf{s}_n (n = 1, 2, .., N) $ が、$ Cat(\textbf{s}_n|\textbf{π}) = \prod_{k=1}^{K} {\pi_k}^{s_{n,k}} $ からサンプルされる。

今回は、お手軽にnumpyの numpy.random.choice メソッドを活用させてもらおう。

N = 100

# (0,1,2)から確率(3/6,2/6,1/6)でN個のデータをサンプリング
S = np.random.choice(a=range(K), size=N, p=pi_vec)

上コードでは、$ s_n \in {0,1,2} $ であり、1 of K なベクトルでなく、クラスタ番号を表すスカラー値としている。

実装上こちらの方が便利そうなのでこのまま進めるが、1 of K なベクトルの作り方を一応紹介しておく。

# クラスタの数と同じ次元の単位行列を作る
I = np.eye(K)

one_hot_S = I[S]

3.ポアソン分布からのサンプリング

$ x_n (n = 1, 2, .., N) $ が、$ \prod_{k=1}^{K} Poi(x_n|λ_k)^{s_{n,k}} $ ($ s_n $ に対応する一つのポアソン分布)から サンプルされる。

これの簡単な実装方法としては、例えば以下があげられる。

・$S_k = \sum_{n=1}^{N} s_{n,k}$ として、各クラスタごとに $ S_K $ 回の試行を行う。

・各 $ s_{n,k} $ に対応するクラスタを選択し、該当するポアソン分布からのサンプリングを実行する。

前者だと秒で済むが、今回は後者を実装してみよう。

from scipy import stats
# 各nについて、3つのポアソン分布のそれぞれからのサンプリングを行っちゃう
mixed_poisson = [stats.poisson.rvs(mu=lam_vec[k], size=N) for k in range(K)]

現時点で、サンプルされたすべてのデータを可視化するとこんな感じ。

plt.hist(mixed_poisson[0], alpha=0.7)
plt.hist(mixed_poisson[1], alpha=0.7)
plt.hist(mixed_poisson[2], alpha=0.7)

1_ポアソン混合分布.png

ここから、$ s_n $ に基づいて採用する値を絞っていく。

'''気持ちはこれ。内法表記を連チャンで使ってる。
samples = []
for i in range(N):
  for s_n in S:
    data = mixed_poisson[s_n][i]
    samples.append(data)
'''
data = np.array([mixed_poisson[s][i] for i in range(N) for s in S])

まとめて表示するとこんな感じ

plt.hist(data)

2_ヒストグラム_まとめて.png

まとめて表示してもわかりづらいので、クラスタ別にヒストグラムを描いてみよう。

plt.hist(mixed_poisson[0][np.where(S == 0)], alpha=0.7)
plt.hist(mixed_poisson[1][np.where(S == 1)], alpha=0.7)
plt.hist(mixed_poisson[2][np.where(S == 2)], alpha=0.7)

3_ヒストグラム_クラスタ.png

はい、クラスタによって値の採用率が異なっている感じがわかる。

このデータを使って次の記事ではポアソン混合モデルのパラメータ推定をしたいが、データとして保存したりするのがめんどくさいので、データ生成用コードをまとめておこう。

'''1.パラメータのてきとうな初期化'''
import numpy as np

K = 3
pi_vec = np.array([3/6, 2/6, 1/6])
lam_vec = np.array([5,10,20])

'''2.クラスタの割り振り'''
N = 3000

# (0,1,2)から確率(3/6,2/6,1/6)でN個のデータをサンプリング
S = np.random.choice(a=range(K), size=N, p=pi_vec)

'''3.ポアソン分布からのサンプリング'''
from scipy import stats
# 各nについて、3つのポアソン分布のそれぞれからのサンプリングを行っちゃう
mixed_poisson = [stats.poisson.rvs(mu=lam_vec[k], size=N) for k in range(K)]

data = np.array([mixed_poisson[s][i] for i in range(N) for s in S])

まとめるとあんまり難しい内容もなく簡単な感じ。ライブラリって便利ですね。

今日はここまで。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?