概要
今回はガウス過程の導出と、線形回帰における出力の事前分布はカーネル関数を使って表すことができるということの確認です。計算自体は難しくないのですが、ガウス過程という名称から確率過程のように時間軸を意識してしまうと戸惑ってしまいます。
線形回帰における出力の事前分布
まずは線形回帰で何度もやってきた通り、回帰式のモデルを
と設定します。線形回帰をMAP推定で解くで計算したのと同じく、係数の事前分布を
とします。平均が0で、各パラメータには相関がなく、全て等しい分散であるということです。線形回帰をMAP推定で解くの式(5)で、とすれば同じことです。
ここで最小二乗法の解の導出の式(4)と同じように計画行列を用いて
とします。は訓練データに対する値をまとめたベクトルになっています。冒頭で書いた通り、今回はこのの分布を求めることが目標です。
さて、正規分布に従う独立な確率変数の和は、やはり正規分布に従うという性質があります。正規分布に従うと仮定した係数と入力の線形和がですから、この性質よりは正規分布に従うことがわかります。*1
今回の目的はの分布を求めることでしたから、正規分布に従うということは平均と共分散がわかれば良いということになります。まずは平均を求めますと、
です。は式(2)で平均としていますから式(5)はと計算できます。
次にの共分散を求めます。多変量正規分布の式(2)の通り、
です。ここで式(6)よりでしたから、
です。共分散行列は多変量正規分布の式(4)ですので、
と計算できます。式(9)から式(10)は転置行列の定理を使っています。また、]は前提条件よりです。ここでカーネル法による正則化最小二乗法(1)の式(10)より、
でした。以上をまとめると、求めたい分布は
となることがわかります。カーネル関数さえ定まればいきなりの事前分布が求まってしまうっていうことなんですが、なんか驚きです。係数の事前分布を設定し、計算の過程での前提条件からを式からなくしてしまい、の事前分布になるという。
ガウス過程
さて、ここでようやくタイトルのガウス過程の話です。ガウス過程とは、任意の個数の入力を選んだとき、それに対する出力が常に多次元正規分布に従うことをいいます。ちょっと説明が正確でないかもしれません、、、Wikiを参考にしました:ガウス過程 - Wikipedia
は式(15)の通り多次元正規分布ですから、これを満たしています。つまりガウス過程となっています。確率過程のように時間軸が関係しそうな名前ですが、とにかく多数個入力の出力が多次元正規分布に従っていればガウス過程と呼べます。
式(15)を使って、を出力してみた実験結果です。いくつかサンプリングしてみました。
上のグラフは、5次の多項式モデルを考え、を計算しています。下のグラフはガウスカーネルでを計算しました。ガウスという名前がたくさん出てきてややこしいですが、ガウスカーネルを使っていない上の図もガウス過程です。
これらの結果はなめらかな曲線になっていますが、これはが実際どのような値になっているかを見れば明らかです。例えば-1~1の範囲で均等に5点を取り、このに対してガウスカーネルでを計算すれば、以下のようになります。(としました。)
の値が近いほうが共分散が高い、つまり同じような値を取る確率が高いことがわかります。また、逆にの値が遠ければ共分散は0に近く無相関に近くなります。この共分散行列によってが生成されるのですから、なめらかな曲線が得られることがわかります。
入力は多次元になっても同じようにサンプリングすることができます。こちらもガウスカーネルを用いました。
ガウス過程を回帰や分類で使う
このガウス過程を回帰や分類問題に使っていきます。
ガウス過程による回帰の記事1つ目:
回帰の最終的な実験結果はこちらです。
ガウス過程による分類の記事1つ目
分類の最終的な実験結果はこちらです。
今回のコードです。
# ガウス過程からのサンプリング import matplotlib.pyplot as plt import numpy as np # カーネル def kernel(x1, x2): # 5次の多項式モデルを考えたときのカーネル関数(内積) ret = 0 for i in range(5): ret += x1**i * x2**i return ret # ガウスカーネル # sigma = 0.3 # return np.exp(-(x1 - x2) ** 2 / (2 * sigma ** 2)) # グラム行列 def gram_matrix(x): gram = np.empty([N, N]) for i in range(N): for j in range(N): gram[i, j] = kernel(x[i], x[j]) return gram # x N = 100 x = np.linspace(-1, 1, N) # α ALPHA = 1.0 # グラム行列K K = gram_matrix(x) / ALPHA for i in range(5): y = np.random.multivariate_normal(np.zeros(N), K) plt.plot(x, y) # 結果の表示 plt.xlim(-1, 1) plt.show()