ガウス過程からサンプリングを行う最小のPythonプログラム
モチベーション
ガウス過程は勉強したことあったけど,理論と実装がイマイチ頭の中で結びつかなかったので色々調べていた. いきなり回帰とか実装するのは重たいので,手始めにガウス過程からの関数のサンプリングを実装してみた.
実装
ガウス過程は連続関数を生成する確率分布だけどプログラムに落とすときは生成される関数を離散な関数として扱うみたい. データ長も有限になるので,ガウス過程と言いつつ実装上は めっちゃ高次元のガウス関数からめっちゃ高次元のベクトルをサンプリングしている形になる. それにカーネル法を組み合わせている感じ.
フーリエ変換を実装するときに離散フーリエ変換使うけど信号の長さが有限になるので 実質的にフーリエ級数展開になってる感覚に近い?
以下は平均関数 $m(x) = 0$,カーネル関数 $k(x, x') = \exp\left(-|x - x'|^2/σ^2\right)$の ガウス過程$\mathcal{GP}\left(m(x), k(x, x')\right)$からサンプル$y(x)$を10個サンプリングするPythonコード.
import numpy as np from matplotlib import pyplot as plt def mean_function(x): return np.zeros_like(x) def covariance_function(x1, x2, s): return np.exp(-(x1 - x2) ** 2 / s ** 2) x = np.linspace(-10, 10, 100) x1, x2 = np.meshgrid(x, x) sigma = 1.0 m = mean_function(x) gram_matrix = covariance_function(x1, x2, sigma) plt.figure(figsize=(12, 8), facecolor='w') # 関数を10個サンプリングしつつプロット for k in range(10): sample = np.random.multivariate_normal(m, gram_matrix) plt.plot(x, sample, label=f'Sample {k}') plt.legend(loc='upper right')
実行結果 ($σ = 1.0$)
実行結果 ($σ = 0.25$)