ガウス過程(Gaussian Process)の性質は、カーネル関数(共分散関数)の選び方によって大きく変わります。カーネル関数は、入力空間上の2点がどれだけ「似ている」かを定量化する関数であり、ガウス過程から生成される関数の滑らかさ、周期性、振幅などの性質を決定します。
つまり、ガウス過程で良い回帰や予測を行うためには、データの構造に適したカーネル関数を選ぶことが不可欠です。本記事では、代表的なカーネル関数の数学的定義と性質を省略せずに解説し、Pythonによる可視化を通して、各カーネルの振る舞いの違いを実感していただきます。
本記事の内容
- カーネル関数の数学的定義と正定値性
- RBF(ガウス)カーネル、Maternカーネル、周期カーネル、線形カーネルの定義と性質
- カーネルの合成(和・積・定数倍)による新しいカーネルの構成
- Pythonで各カーネルからガウス過程のサンプルを描画して比較
前提知識
この記事を読む前に、以下の記事を読んでおくと理解が深まります。
カーネル関数の数学的定義
カーネル関数とは
カーネル関数 $k: \mathcal{X} \times \mathcal{X} \to \mathbb{R}$ は、入力空間 $\mathcal{X}$ 上の2点 $\bm{x}, \bm{x}’$ を受け取り、実数値を返す関数です。ガウス過程では、カーネル関数が共分散関数の役割を果たします。
$$ \text{Cov}(f(\bm{x}), f(\bm{x}’)) = k(\bm{x}, \bm{x}’) $$
直感的には、$k(\bm{x}, \bm{x}’)$ の値が大きいほど、入力 $\bm{x}$ と $\bm{x}’$ における関数値 $f(\bm{x})$ と $f(\bm{x}’)$ は互いに強く相関する、つまり似た値をとりやすいということを意味します。
ガウス過程 $f \sim \mathcal{GP}(m(\bm{x}),\, k(\bm{x}, \bm{x}’))$ は、平均関数 $m(\bm{x})$ と共分散関数 $k(\bm{x}, \bm{x}’)$ の2つで完全に特徴づけられます。平均関数は簡単のためゼロとすることが多いため、ガウス過程の挙動を事実上支配しているのはカーネル関数 $k(\bm{x}, \bm{x}’)$ です。
正定値性
カーネル関数がガウス過程の共分散関数として有効であるためには、正定値性(positive definiteness)を満たす必要があります。
関数 $k(\bm{x}, \bm{x}’)$ が正定値であるとは、任意の有限個の点 $\bm{x}_1, \bm{x}_2, \dots, \bm{x}_N \in \mathcal{X}$ と、任意の実数 $c_1, c_2, \dots, c_N \in \mathbb{R}$(ただし全てが0ではない)に対して、
$$ \sum_{i=1}^{N} \sum_{j=1}^{N} c_i c_j \, k(\bm{x}_i, \bm{x}_j) \geq 0 $$
が成り立つことをいいます。等号が $c_i = 0$ のときのみ成り立つ場合は、狭義正定値(strictly positive definite)と呼びます。
この条件は、カーネル関数から構成されるグラム行列(カーネル行列)
$$ \bm{K} = \begin{pmatrix} k(\bm{x}_1, \bm{x}_1) & k(\bm{x}_1, \bm{x}_2) & \cdots & k(\bm{x}_1, \bm{x}_N) \\ k(\bm{x}_2, \bm{x}_1) & k(\bm{x}_2, \bm{x}_2) & \cdots & k(\bm{x}_2, \bm{x}_N) \\ \vdots & \vdots & \ddots & \vdots \\ k(\bm{x}_N, \bm{x}_1) & k(\bm{x}_N, \bm{x}_2) & \cdots & k(\bm{x}_N, \bm{x}_N) \end{pmatrix} $$
が半正定値行列になることと等価です。共分散行列は半正定値でなければならないため、正定値性はカーネル関数がガウス過程で使えるための最低限の条件になります。
マーサーの定理
カーネル関数と正定値性に関する古典的な結果として、マーサーの定理(Mercer’s theorem)があります。マーサーの定理は、連続な正定値カーネル $k(\bm{x}, \bm{x}’)$ が、ある特徴空間 $\mathcal{H}$ への写像 $\bm{\phi}: \mathcal{X} \to \mathcal{H}$ を用いて、
$$ k(\bm{x}, \bm{x}’) = \langle \bm{\phi}(\bm{x}), \bm{\phi}(\bm{x}’) \rangle_{\mathcal{H}} = \sum_{i=1}^{\infty} \lambda_i \, \phi_i(\bm{x}) \, \phi_i(\bm{x}’) $$
と展開できることを保証するものです。ここで $\lambda_i \geq 0$ は固有値、$\phi_i$ は対応する固有関数です。
この定理は、ガウス過程回帰の記事で登場した「特徴ベクトルの内積としてカーネルが書ける」という性質(カーネルトリック)の理論的裏付けになっています。つまり、高次元(場合によっては無限次元)の特徴空間を明示的に構成しなくても、カーネル関数を通じてその空間での内積を計算できるということです。
RBF(ガウス)カーネル
定義
最もよく使われるカーネル関数が RBFカーネル(Radial Basis Function kernel)です。ガウスカーネル(Gaussian kernel)や二乗指数カーネル(Squared Exponential kernel, SE kernel)とも呼ばれます。
$$ k_{\text{RBF}}(\bm{x}, \bm{x}’) = \sigma_f^2 \exp\!\left( -\frac{\|\bm{x} – \bm{x}’\|^2}{2\ell^2} \right) $$
ここで、各パラメータの意味は以下のとおりです。
- $\sigma_f^2$ : 信号分散(signal variance)。関数の振幅のスケールを制御します。
- $\ell$ : 長さスケール(length scale)。入力空間における相関の届く範囲を制御します。
長さスケールの影響
長さスケール $\ell$ は、RBFカーネルの振る舞いを直感的に理解する上で最も重要なパラメータです。
- $\ell$ が小さいとき:近い点同士しか相関しないため、サンプリングされる関数は細かく変動します。
- $\ell$ が大きいとき:遠い点同士も相関するため、サンプリングされる関数は滑らかになります。
数学的には、$\|\bm{x} – \bm{x}’\| \ll \ell$ のとき $k \approx \sigma_f^2$(強い相関)、$\|\bm{x} – \bm{x}’\| \gg \ell$ のとき $k \approx 0$(ほぼ無相関)となります。
無限回微分可能
RBFカーネルの重要な性質として、このカーネルから生成される関数は無限回微分可能($C^\infty$ 級)であることが知られています。これは、指数関数 $\exp(-r^2)$ が $r = 0$ の周りで任意の次数のテイラー展開が可能であることに由来します。
現実のデータでは無限回微分可能という仮定が強すぎる場合もあり、その場合はこの後紹介する Matern カーネルがより適切な選択となります。
Matern カーネル
一般的な定義
Matern カーネルは、関数の滑らかさをパラメータ $\nu$ で明示的に制御できる柔軟なカーネルです。
$$ k_{\text{Mat\acute{e}rn}}(\bm{x}, \bm{x}’) = \sigma_f^2 \, \frac{2^{1-\nu}}{\Gamma(\nu)} \left( \frac{\sqrt{2\nu} \, \|\bm{x} – \bm{x}’\|}{\ell} \right)^\nu K_\nu\!\left( \frac{\sqrt{2\nu} \, \|\bm{x} – \bm{x}’\|}{\ell} \right) $$
ここで、各記号の意味は以下のとおりです。
- $\nu > 0$ : 滑らかさパラメータ。大きいほど滑らかな関数を生成します。
- $\ell$ : 長さスケール。RBFカーネルと同様の意味です。
- $\sigma_f^2$ : 信号分散。
- $\Gamma(\cdot)$ : ガンマ関数。
- $K_\nu(\cdot)$ : 第2種変形ベッセル関数(modified Bessel function of the second kind)。
Matern カーネルから生成される関数は $\lceil \nu \rceil – 1$ 回微分可能です。また、$\nu \to \infty$ の極限では、Matern カーネルは RBF カーネルに収束します。
$\nu = 1/2$(指数カーネル)
$\nu = 1/2$ を代入すると、
$$ k_{\text{Mat\acute{e}rn}_{1/2}}(\bm{x}, \bm{x}’) = \sigma_f^2 \exp\!\left( -\frac{\|\bm{x} – \bm{x}’\|}{\ell} \right) $$
これは指数カーネルとも呼ばれ、オルンシュタイン・ウーレンベック過程の共分散関数に対応します。生成される関数は連続ですが微分不可能で、非常にギザギザした形状になります。
$\nu = 3/2$ の導出
$\nu = 3/2$ を Matern カーネルの一般式に代入して、閉じた形を導出してみましょう。
まず、ガンマ関数について $\Gamma(3/2) = \sqrt{\pi}/2$ であり、第2種変形ベッセル関数の半整数次の公式から、
$$ K_{3/2}(z) = \sqrt{\frac{\pi}{2z}}\, e^{-z}\left(1 + \frac{1}{z}\right) $$
が得られます。$r = \|\bm{x} – \bm{x}’\|$ として $z = \sqrt{3}\,r/\ell$ を代入すると、
$$ \begin{align} k &= \sigma_f^2 \frac{2^{1-3/2}}{\Gamma(3/2)} \left(\frac{\sqrt{3}\,r}{\ell}\right)^{3/2} K_{3/2}\!\left(\frac{\sqrt{3}\,r}{\ell}\right) \\ &= \sigma_f^2 \frac{2^{-1/2}}{\sqrt{\pi}/2} \, z^{3/2} \cdot \sqrt{\frac{\pi}{2z}}\, e^{-z}\left(1 + \frac{1}{z}\right) \\ &= \sigma_f^2 \frac{\sqrt{2}}{\sqrt{\pi}} \, z^{3/2} \cdot \frac{\sqrt{\pi}}{\sqrt{2z}}\, e^{-z}\left(1 + \frac{1}{z}\right) \\ &= \sigma_f^2\, z\, e^{-z}\left(1 + \frac{1}{z}\right) \\ &= \sigma_f^2 (1 + z)\, e^{-z} \\ &= \sigma_f^2 \left(1 + \frac{\sqrt{3}\,r}{\ell}\right) \exp\!\left(-\frac{\sqrt{3}\,r}{\ell}\right) \end{align} $$
よって、Matern 3/2 カーネルは次のように書けます。
$$ k_{\text{Mat\acute{e}rn}_{3/2}}(\bm{x}, \bm{x}’) = \sigma_f^2 \left(1 + \frac{\sqrt{3} \, \|\bm{x} – \bm{x}’\|}{\ell}\right) \exp\!\left( -\frac{\sqrt{3} \, \|\bm{x} – \bm{x}’\|}{\ell} \right) $$
生成される関数は1回微分可能です。物理的な時系列データなど、ある程度滑らかだが RBF ほど滑らかではないデータのモデリングに適しています。
$\nu = 5/2$
同様の導出により、$\nu = 5/2$ のとき、
$$ k_{\text{Mat\acute{e}rn}_{5/2}}(\bm{x}, \bm{x}’) = \sigma_f^2 \left(1 + \frac{\sqrt{5} \, \|\bm{x} – \bm{x}’\|}{\ell} + \frac{5 \, \|\bm{x} – \bm{x}’\|^2}{3\ell^2}\right) \exp\!\left( -\frac{\sqrt{5} \, \|\bm{x} – \bm{x}’\|}{\ell} \right) $$
生成される関数は2回微分可能です。機械学習の実務では、RBF カーネルの代わりに Matern 5/2 がデフォルトで使われることも多いです(例: scikit-learn のガウス過程モジュール)。
滑らかさの比較
$\nu$ の値と生成される関数の性質をまとめると、次のようになります。
| $\nu$ | 微分可能性 | 関数の見た目 | 別名 |
|---|---|---|---|
| $1/2$ | 連続のみ(微分不可) | ギザギザ | 指数カーネル |
| $3/2$ | 1回微分可能 | やや滑らか | — |
| $5/2$ | 2回微分可能 | 滑らか | — |
| $\to \infty$ | 無限回微分可能 | 非常に滑らか | RBF カーネル |
$\nu \to \infty$ の極限で Matern カーネルは RBF カーネルに収束することが知られています。
$$ \lim_{\nu \to \infty} k_{\text{Mat\acute{e}rn}}(\bm{x}, \bm{x}’) = \sigma_f^2 \exp\!\left( -\frac{\|\bm{x} – \bm{x}’\|^2}{2\ell^2} \right) = k_{\text{RBF}}(\bm{x}, \bm{x}’) $$
つまり、RBF カーネルは Matern カーネルの特殊ケースと見なせます。
周期カーネル
定義
周期カーネル(Periodic kernel)は、周期的なパターンをモデリングするためのカーネル関数です。
$$ k_{\text{periodic}}(\bm{x}, \bm{x}’) = \sigma_f^2 \exp\!\left( -\frac{2 \sin^2\!\left(\pi \|\bm{x} – \bm{x}’\| / p\right)}{\ell^2} \right) $$
ここで、各パラメータの意味は以下のとおりです。
- $p$ : 周期(period)。関数が繰り返すサイクルの長さです。
- $\ell$ : 長さスケール。1周期内での関数の滑らかさを制御します。
- $\sigma_f^2$ : 信号分散。
周期的パターンのモデリング
このカーネルは $\sin^2$ の性質により、$\|\bm{x} – \bm{x}’\|$ が周期 $p$ の整数倍のとき $k = \sigma_f^2$ となります。つまり、周期 $p$ だけ離れた点同士は、隣り合う点と同じくらい強く相関します。
直感的には、「1周期前の同じフェーズの点とは、今の近傍の点と同じくらい似ている」という構造を表現しています。
季節変動のある時系列データ(気温、売上など)や、回転角に依存する物理量など、明確な周期性を持つ現象のモデリングに適しています。
線形カーネル
定義
線形カーネル(Linear kernel)は、最もシンプルなカーネル関数の一つです。
$$ k_{\text{linear}}(\bm{x}, \bm{x}’) = \sigma_b^2 + \sigma_v^2 (\bm{x} – \bm{c})^T (\bm{x}’ – \bm{c}) $$
ここで、各パラメータの意味は以下のとおりです。
- $\sigma_b^2$ : バイアス分散。
- $\sigma_v^2$ : スロープ分散。
- $\bm{c}$ : 中心点。関数が通過しやすい点を指定します。
最も簡単な場合($\sigma_b^2 = 0$, $\sigma_v^2 = 1$, $\bm{c} = \bm{0}$)では、
$$ k_{\text{linear}}(\bm{x}, \bm{x}’) = \bm{x}^T \bm{x}’ $$
となり、単純な内積に帰着します。
ベイズ線形回帰との等価性
線形カーネルを用いたガウス過程回帰は、ベイズ線形回帰と数学的に等価であることが知られています。これを確認しましょう。
ベイズ線形回帰では、重み $\bm{w}$ に事前分布 $\bm{w} \sim \mathcal{N}(\bm{0}, \sigma_v^2 \bm{I})$ を仮定して、モデル $f(\bm{x}) = \bm{w}^T \bm{x}$ を考えます。このとき、任意の2点 $\bm{x}, \bm{x}’$ における関数値の共分散は、
$$ \begin{align} \text{Cov}(f(\bm{x}), f(\bm{x}’)) &= \mathbb{E}[\bm{w}^T \bm{x} \, \bm{x}’^T \bm{w}] – \mathbb{E}[\bm{w}^T \bm{x}]\,\mathbb{E}[\bm{x}’^T \bm{w}] \\ &= \bm{x}^T \mathbb{E}[\bm{w}\bm{w}^T] \bm{x}’ – \bm{0} \quad (\because \mathbb{E}[\bm{w}] = \bm{0}) \\ &= \bm{x}^T (\sigma_v^2 \bm{I}) \bm{x}’ \\ &= \sigma_v^2 \, \bm{x}^T \bm{x}’ \end{align} $$
これはまさに線形カーネルです。したがって、線形カーネルを持つガウス過程は、重みにガウス事前分布を置いたベイズ線形回帰と同じモデルになります。
ガウス過程からサンプリングされる関数はすべて直線になります。そのため単独で使われることは少ないですが、他のカーネルとの合成で重要な役割を果たします。
カーネルの合成
正定値カーネルの重要な性質として、いくつかの演算によって新しい正定値カーネルを構成できることがあります。これにより、基本的なカーネルを組み合わせて、複雑なデータ構造をモデリングできます。
和
$k_1$ と $k_2$ が正定値カーネルならば、その和
$$ k(\bm{x}, \bm{x}’) = k_1(\bm{x}, \bm{x}’) + k_2(\bm{x}, \bm{x}’) $$
も正定値カーネルです。
和の正定値性の証明: $k_1$, $k_2$ が正定値であるとき、任意の $c_1, \dots, c_N$ と $\bm{x}_1, \dots, \bm{x}_N$ に対して、
$$ \begin{align} \sum_{i=1}^{N} \sum_{j=1}^{N} c_i c_j \, k(\bm{x}_i, \bm{x}_j) &= \sum_{i=1}^{N} \sum_{j=1}^{N} c_i c_j \left[ k_1(\bm{x}_i, \bm{x}_j) + k_2(\bm{x}_i, \bm{x}_j) \right] \\ &= \underbrace{\sum_{i=1}^{N} \sum_{j=1}^{N} c_i c_j \, k_1(\bm{x}_i, \bm{x}_j)}_{\geq\, 0} + \underbrace{\sum_{i=1}^{N} \sum_{j=1}^{N} c_i c_j \, k_2(\bm{x}_i, \bm{x}_j)}_{\geq\, 0} \geq 0 \end{align} $$
和カーネルは、それぞれのカーネルが表す構造を加法的に重ね合わせます。例えば、長期トレンド(RBFカーネル)と周期変動(周期カーネル)を同時にモデリングしたいとき、
$$ k = k_{\text{RBF}} + k_{\text{periodic}} $$
とすることで、両方の構造を捉えることができます。
積
$k_1$ と $k_2$ が正定値カーネルならば、その積
$$ k(\bm{x}, \bm{x}’) = k_1(\bm{x}, \bm{x}’) \cdot k_2(\bm{x}, \bm{x}’) $$
も正定値カーネルです。この性質は Schur の積定理(シューアの積定理)として知られています。
積のカーネルは、一方のカーネルの構造を他方で変調する効果があります。例えば、RBFカーネルと周期カーネルの積は、「局所的な周期性」を表現します。つまり、近い入力では周期的な相関を持つが、遠い入力では相関が減衰するような構造をモデリングできます。
$$ k = k_{\text{RBF}} \cdot k_{\text{periodic}} $$
定数倍
$k$ が正定値カーネルで $\alpha > 0$ ならば、
$$ k'(\bm{x}, \bm{x}’) = \alpha \, k(\bm{x}, \bm{x}’) $$
も正定値カーネルです。これは信号分散 $\sigma_f^2$ をスケーリングすることに対応します。
合成の設計例
これらの合成ルールを組み合わせると、以下のような表現力の高いカーネルを構成できます。
| 合成 | 式 | 表現する構造 |
|---|---|---|
| 和 | $k_{\text{RBF}} + k_{\text{periodic}}$ | 緩やかなトレンド + 周期変動 |
| 積 | $k_{\text{RBF}} \times k_{\text{periodic}}$ | 局所的にのみ現れる周期性 |
| 線形+周期 | $k_{\text{linear}} + k_{\text{periodic}}$ | 線形トレンド + 周期変動 |
| 線形x周期 | $k_{\text{linear}} \times k_{\text{periodic}}$ | 振幅が増大する周期関数 |
各カーネルからサンプリングした関数の比較
ここでは、各カーネルの違いを直感的に理解するために、それぞれのカーネルを共分散関数とするガウス過程からランダムに関数をサンプリングして比較します。
ガウス過程 $f \sim \mathcal{GP}(0, k)$ からのサンプリングは、次の手順で行います。
- 入力点 $\bm{x}_1, \dots, \bm{x}_N$ を決める。
- カーネル行列 $\bm{K}$ を計算する($(i,j)$ 成分が $k(\bm{x}_i, \bm{x}_j)$)。
- 数値安定性のために微小量 $\epsilon \bm{I}$ を加える。
- コレスキー分解 $\bm{K} = \bm{L}\bm{L}^T$ を行い、$\bm{f} = \bm{L}\bm{z}$($\bm{z} \sim \mathcal{N}(\bm{0}, \bm{I})$)としてサンプルを生成する。
各カーネルで期待される関数の特徴は次のとおりです。
- RBF カーネル : 非常に滑らかな関数。長さスケールが大きいほど緩やかに変動します。
- Matern 1/2 : ギザギザした関数。ブラウン運動のような見た目です。
- Matern 3/2 : 適度に滑らかな関数。RBF より粗く、Matern 1/2 より滑らかです。
- Matern 5/2 : 滑らかな関数。RBF に近いですが、やや粗い構造が残ります。
- 周期カーネル : 周期的に繰り返す関数。
- 線形カーネル : 直線。
Python実装
カーネル関数の定義
まず、代表的なカーネル関数をPythonで実装します。
import numpy as np
import matplotlib.pyplot as plt
# --- RBF(ガウス)カーネル ---
def rbf_kernel(x1, x2, sigma_f=1.0, length_scale=1.0):
"""RBF カーネル"""
dist_sq = (x1 - x2) ** 2
return sigma_f**2 * np.exp(-0.5 * dist_sq / length_scale**2)
# --- Matern 1/2(指数カーネル)---
def matern12_kernel(x1, x2, sigma_f=1.0, length_scale=1.0):
"""Matern nu=1/2 カーネル"""
dist = np.abs(x1 - x2)
return sigma_f**2 * np.exp(-dist / length_scale)
# --- Matern 3/2 ---
def matern32_kernel(x1, x2, sigma_f=1.0, length_scale=1.0):
"""Matern nu=3/2 カーネル"""
dist = np.abs(x1 - x2)
s = np.sqrt(3) * dist / length_scale
return sigma_f**2 * (1 + s) * np.exp(-s)
# --- Matern 5/2 ---
def matern52_kernel(x1, x2, sigma_f=1.0, length_scale=1.0):
"""Matern nu=5/2 カーネル"""
dist = np.abs(x1 - x2)
s = np.sqrt(5) * dist / length_scale
return sigma_f**2 * (1 + s + s**2 / 3) * np.exp(-s)
# --- 周期カーネル ---
def periodic_kernel(x1, x2, sigma_f=1.0, length_scale=1.0, period=1.0):
"""周期カーネル"""
dist = np.abs(x1 - x2)
return sigma_f**2 * np.exp(-2 * np.sin(np.pi * dist / period)**2 / length_scale**2)
# --- 線形カーネル ---
def linear_kernel(x1, x2, sigma_v=1.0, c=0.0):
"""線形カーネル"""
return sigma_v**2 * (x1 - c) * (x2 - c)
ガウス過程からのサンプリング関数
カーネル行列を共分散行列とする多変量ガウス分布からサンプリングします。数値安定性のためにコレスキー分解を使います。
def sample_gp(kernel_func, x, n_samples=5, **kwargs):
"""
ガウス過程から関数をサンプリングする
kernel_func: カーネル関数
x: 入力点の配列
n_samples: サンプル数
kwargs: カーネルのハイパーパラメータ
"""
# グラム行列(カーネル行列)の構成
x1, x2 = np.meshgrid(x, x)
K = kernel_func(x1, x2, **kwargs)
# 数値安定性のための微小量を対角に加える
K += 1e-8 * np.eye(len(x))
# コレスキー分解によるサンプリング
L = np.linalg.cholesky(K)
samples = []
for _ in range(n_samples):
z = np.random.randn(len(x))
samples.append(L @ z)
return samples
各カーネルの共分散行列の可視化
各カーネルのグラム行列(共分散行列)を可視化して、入力点間の相関構造を確認しましょう。
import numpy as np
import matplotlib.pyplot as plt
# カーネル関数の定義(上で定義した関数を使用)
x = np.linspace(-5, 5, 200)
x1, x2 = np.meshgrid(x, x)
# 各カーネルの共分散行列を計算
kernels_cov = {
"RBF ($\\ell=1.0$)": rbf_kernel(x1, x2, length_scale=1.0),
"Matern 1/2": matern12_kernel(x1, x2, length_scale=1.0),
"Matern 3/2": matern32_kernel(x1, x2, length_scale=1.0),
"Matern 5/2": matern52_kernel(x1, x2, length_scale=1.0),
"Periodic ($p=2$)": periodic_kernel(x1, x2, length_scale=1.0, period=2.0),
"Linear": linear_kernel(x1, x2),
}
fig, axes = plt.subplots(2, 3, figsize=(14, 9))
axes = axes.flatten()
for ax, (name, K) in zip(axes, kernels_cov.items()):
im = ax.imshow(K, extent=[-5, 5, -5, 5], origin="lower", cmap="viridis")
ax.set_title(name, fontsize=12)
ax.set_xlabel("$x$")
ax.set_ylabel("$x'$")
fig.colorbar(im, ax=ax, fraction=0.046, pad=0.04)
plt.suptitle("Kernel Gram Matrices", fontsize=14, y=1.02)
plt.tight_layout()
plt.show()
RBFカーネルでは対角線に沿って滑らかにグラデーションが広がる一方、Matern 1/2 では対角線付近に相関が集中していることが確認できます。周期カーネルでは、対角線と平行な帯状のパターンが繰り返し現れ、周期的な相関構造が可視化されます。
GPからのサンプリング比較
各カーネルを用いたガウス過程から関数をサンプリングし、生成される関数の形状を比較します。
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
x = np.linspace(-5, 5, 300)
n_samples = 5
# カーネルの設定(名前, 関数, パラメータ)
kernels = [
("RBF ($\\ell=1.0$)", rbf_kernel, {"sigma_f": 1.0, "length_scale": 1.0}),
("Matern 1/2 ($\\ell=1.0$)", matern12_kernel, {"sigma_f": 1.0, "length_scale": 1.0}),
("Matern 3/2 ($\\ell=1.0$)", matern32_kernel, {"sigma_f": 1.0, "length_scale": 1.0}),
("Matern 5/2 ($\\ell=1.0$)", matern52_kernel, {"sigma_f": 1.0, "length_scale": 1.0}),
("Periodic ($p=2.0$)", periodic_kernel, {"sigma_f": 1.0, "length_scale": 1.0, "period": 2.0}),
("Linear", linear_kernel, {"sigma_v": 1.0, "c": 0.0}),
]
fig, axes = plt.subplots(2, 3, figsize=(15, 8))
axes = axes.flatten()
for i, (name, kernel_func, params) in enumerate(kernels):
samples = sample_gp(kernel_func, x, n_samples=n_samples, **params)
for s in samples:
axes[i].plot(x, s, alpha=0.7)
axes[i].set_title(name, fontsize=13)
axes[i].set_xlabel("$x$")
axes[i].set_ylabel("$f(x)$")
axes[i].set_ylim(-4, 4)
axes[i].grid(True, alpha=0.3)
plt.suptitle("Samples from GP with different kernels", fontsize=15)
plt.tight_layout()
plt.show()
実行すると、6つのサブプロットに各カーネルからサンプリングした関数が描画されます。注目すべき違いは以下のとおりです。
- RBF: 非常に滑らかな曲線。折れ曲がりがなく、どこでも微分可能に見えます。
- Matern 1/2: 角張ったギザギザの曲線。微分不可能な点が至るところにあります。
- Matern 3/2: Matern 1/2 より滑らかですが、RBF ほどではありません。自然現象のモデリングに適した「程よい滑らかさ」です。
- Matern 5/2: RBF にかなり近い滑らかさ。実用上 RBF との差は小さくなります。
- Periodic: 周期的に繰り返すパターンが明確に見られます。
- Linear: すべてのサンプルが原点を通る直線になります。
RBFカーネルの長さスケールの影響
最後に、RBFカーネルの長さスケール $\ell$ がサンプリングされる関数にどう影響するかを可視化します。
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(0)
x = np.linspace(-5, 5, 300)
length_scales = [0.3, 1.0, 3.0]
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
for i, ls in enumerate(length_scales):
samples = sample_gp(rbf_kernel, x, n_samples=5, sigma_f=1.0, length_scale=ls)
for s in samples:
axes[i].plot(x, s, alpha=0.7)
axes[i].set_title(f"RBF: $\\ell$ = {ls}", fontsize=12)
axes[i].set_xlabel("$x$")
axes[i].set_ylabel("$f(x)$")
axes[i].set_ylim(-4, 4)
axes[i].grid(True, alpha=0.3)
plt.suptitle("Effect of length scale on RBF kernel", fontsize=14)
plt.tight_layout()
plt.show()
$\ell = 0.3$ では細かく振動する関数が得られ、$\ell = 3.0$ ではほぼ定数のような緩やかな関数になっていることがわかります。長さスケールはガウス過程回帰のハイパーパラメータ最適化において最も重要なパラメータの一つです。
まとめ
本記事では、ガウス過程で使われる代表的なカーネル関数について解説しました。
- カーネル関数は、ガウス過程の共分散構造を定義し、生成される関数の性質(滑らかさ、周期性、線形性など)を決定します。
- 正定値性は、カーネル関数が有効な共分散関数であるための必要条件であり、マーサーの定理がその理論的基盤を与えます。
- RBF カーネルは無限回微分可能な滑らかな関数を生成し、Matern カーネルは $\nu$ パラメータで滑らかさを制御できます。
- 周期カーネルは周期的なデータに、線形カーネルはベイズ線形回帰と等価な線形的なモデリングに適しています。
- カーネルの和・積・定数倍により、基本カーネルを組み合わせて複雑な構造をモデリングできます。
次のステップとして、ガウス過程のカーネル関数のハイパーパラメータ(長さスケール $\ell$ や信号分散 $\sigma_f^2$ など)をデータから最適化する方法(対数周辺尤度の最大化)について学ぶとよいでしょう。