十の並列した脳

何でも勉強する,毎週月木曜に投稿予定

「Pythonによるベイズ統計モデリング」まとめ #5

Pythonによるベイズ統計モデリングPyMCでのデータ分析実践ガイド― 」:

 

Pythonによるベイズ統計モデリング: PyMCでのデータ分析実践ガイド

Pythonによるベイズ統計モデリング: PyMCでのデータ分析実践ガイド

 

前回↓ 

 

ryosuke-okubo.hatenablog.com

 

 

#5では第8章を扱う。

 

 

8章 ガウス過程

ここからはノンパラメトリックモデルを扱う。

カーネル

カーネルベースの手法として,サポートベクトルマシンガウス過程がある。ここではガウス過程について扱う。

 

ガウスカーネルの定義:

 {\displaystyle K(x,x') = exp(-\frac{||\boldsymbol{x}-\boldsymbol{x'}||^2}{w})}

ここで {\displaystyle ||\boldsymbol{x}-\boldsymbol{x'}||^2}ユークリッド平方距離w帯域幅である。

 

線形回帰モデル:

{\displaystyle y = f(\boldsymbol{x}) + \epsilon}{\displaystyle \epsilon}:誤差)

{\displaystyle f(\boldsymbol{x}) =\boldsymbol{\mu} = \sum_i^N \boldsymbol{\gamma}_i \boldsymbol{x_i}}

ここで {\displaystyle \boldsymbol{\gamma}_i}は係数ベクトル,{\displaystyle \boldsymbol{x}_i}はデータを示す。

 

多項式回帰モデルは

{\displaystyle \boldsymbol{\mu} = \sum_i^N \boldsymbol{\gamma}_i \phi_i(\boldsymbol{x_i})}

と表される。関数\phi_iカーネルKで置き換えると,

{\displaystyle \boldsymbol{\mu} = \sum_i^N \boldsymbol{\gamma}_i K(\boldsymbol{x},\boldsymbol{x'})}

となる。ここでデータ{\displaystyle \boldsymbol{x}}に対して,{\displaystyle \boldsymbol{x'}}ノットと呼ばれる。

 

実装例としては重み空間モデルが扱われる。これは{\displaystyle \boldsymbol{x'}}グリッド点として\muの値を近似する曲線を得るグリッドアプローチである。

 

データの表示

import pymc3 as pm
import numpy as np
import pandas as pd
import theano.tensor as tt
import scipy.stats as stats
import matplotlib.pyplot as plt
import seaborn as sns
plt.style.use(['seaborn-colorblind', 'seaborn-darkgrid'])
np.set_printoptions(precision=2)

np.random.seed(1)
x = np.random.uniform(0, 10, size=20)
y = np.random.normal(np.sin(x), 0.2)
plt.plot(x, y, 'o')
plt.xlabel('$x$', fontsize=16)
plt.ylabel('$f(x)$', fontsize=16, rotation=0)

plt.figure()

f:id:ryosuke_okubo:20190303103027p:plain


 

モデル記述

def gauss_kernel(x, n_knots):
    knots = np.linspace(x.min(), x.max(), n_knots)    
    w = 2 
    return np.array([np.exp(-(x-k)**2/w) for k in knots])

n_knots = 5

with pm.Model() as kernel_model:
    gamma = pm.Cauchy('gamma', alpha=0, beta=1, shape=n_knots)
    sd = pm.Uniform('sd',0,  10)
    mu = pm.math.dot(gamma, gauss_kernel(x, n_knots))
    yl = pm.Normal('yl', mu=mu, sd=sd, observed=y)

    kernel_trace = pm.sample(5000, njobs=1)

pm.traceplot(kernel_trace)

plt.figure()

f:id:ryosuke_okubo:20190303103045p:plain

 

事後予測チェック

ppc = pm.sample_ppc(kernel_trace, model=kernel_model, samples=100)

plt.plot(x, ppc['yl'].T, 'ro', alpha=0.1)

plt.plot(x, y, 'bo')
plt.xlabel('$x$', fontsize=16)
plt.ylabel('$f(x)$', fontsize=16, rotation=0)

plt.figure()

f:id:ryosuke_okubo:20190303103146p:plain


 

データ適合性チェック

new_x = np.linspace(x.min(), x.max(), 100)
k = gauss_kernel(new_x, n_knots)
gamma_pred = kernel_trace['gamma']
for i in range(100):
    idx = np.random.randint(0, len(gamma_pred))
    y_pred = np.dot(gamma_pred[idx], k)
    plt.plot(new_x, y_pred, 'r-', alpha=0.1)
plt.plot(x, y, 'bo')
plt.xlabel('$x$', fontsize=16)
plt.ylabel('$f(x)$', fontsize=16, rotation=0)

plt.figure()

f:id:ryosuke_okubo:20190303103203p:plain

 

このように,カーネルを用いることで非線形データのモデリングができる。 

 

ガウス過程

ガウス過程は多変量正規分布を無限にまで拡張したものであり, 平均関数と共分散関数によってパラメータ化される。

{\displaystyle f(\boldsymbol{x}) \sim GP( \mu (\boldsymbol{x}), K(\boldsymbol{x},\boldsymbol{x'}))}

 

事前分布,尤度,事後分布は以下のようになる。

  • 事前分布:{\displaystyle f(x) \sim GP( \mu =[0...0], k(x,x'))}
  • 尤度:{\displaystyle p(y|x,f(x)) \sim N(\boldsymbol{f},\sigma^2I)}
  • 事後分布:{\displaystyle p(f(\boldsymbol{x})|\boldsymbol{x},\boldsymbol{y}) \sim GP( \mu_{post}, \Sigma_{post})}

 

データが周期的な可能性が ある場合は,周期カーネルを使うのがよい。例としてsin関数を含んだものを示す。

 {\displaystyle Kp(\boldsymbol{x},\boldsymbol{x'}) =exp \Biggl(-\frac{sin^2(\frac{\boldsymbol{x}-\boldsymbol{x'}}{2})}{w} \Biggl)}

 

(終)