統計コンサルの議事メモ

統計や機械学習の話題を中心に、思うがままに

「ガウス過程と機械学習」第3章のグラフ(一部)を作図する

※ 3/13 一部修正

いま「ガウス過程と機械学習」を読んでいるのですが、第3章のグラフが非常に面白かったので自分でも作図してみたところちょっと腹落ちするものがありました。せっかくなので記事にしておきます。今回グラフを作成したのは図3.7と3.8(P69、70)の2つです。

ガウス過程と機械学習 (機械学習プロフェッショナルシリーズ)

ガウス過程と機械学習 (機械学習プロフェッショナルシリーズ)

順番は前後してしまうのですが、図3.8から作図します。まずは必要な関数を定義しておきましょう。本にしたがい、共分散行列を計算するRBFカーネルガウスカーネル)のtheta1theta2はともに1にしてあります。

## 1~4までの数列を適当な刻み幅で生成する
generate_vector <- function(by, from = 1, to = 4) seq(by, from = from, to = to)

## xからRBFカーネルを使って共分散行列を作成する
get_cov_mat <- function(x, theta1 = 1, theta2 = 1) {
   vec <- x
   theta1 * exp(-(apply(as.matrix(x), 1, function(x) x-vec))^2/theta2)
} 

※ 3/13 apply中のfunctionの引数を修正しました

上記の関数を使って1から4までの数列xを生成し、その共分散行列Kから生成されるyとのプロットを描く関数を以下のように定義します。なるべく本のグラフと近づけるために、共分散行列のヒートマップはcorrplotパッケージのcorrplot関数を使い、method = "shade"を指定しました。

## xからKとyを生成し、そのプロットを描く
gen_y_plot <- function(by) {
   
   x <- generate_vector(by)
   K <- get_cov_mat(x)
   mu <- rep(0, length(x))
   y <- MASS::mvrnorm(n = 1, mu = mu, Sigma = K)
   par(mfcol = c(1, 2))
   plot(x, y, xlim = c(0, 5))
   corrplot::corrplot(K, method = "shade")
   
}

数列の刻み幅を変えながらいくつかプロットしてみます。

set.seed(123)
gen_y_plot(1)
gen_y_plot(0.5)
gen_y_plot(0.2)
gen_y_plot(0.1)

f:id:ushi-goroshi:20190312231034p:plain f:id:ushi-goroshi:20190312231050p:plain f:id:ushi-goroshi:20190312231105p:plain f:id:ushi-goroshi:20190312231120p:plain

本にある通り、刻み幅を小さくすることで順に滑らかな曲線になっていくのがよくわかります。

続いて図3.7を作成します。先ほどとほぼ同じです。

gen_x_plot <- function(by) {
   x <- generate_vector(by, -4, 4)
   K <- get_cov_mat(x)
   mu <- rep(0, length(x))
   y <- MASS::mvrnorm(n = 1, mu = mu, Sigma = K)
   plot(x, y, type = "l", ylim = c(-4, 4))
}

plotを重ねるためにpar(new = T)を使っているのですが、一回目だけは作図を0から始める必要があるので処理を分けています。もっと良い方法がある気がしていますが、ひとまず欲しいグラフは得られたので良しとします。

set.seed(123)
for (i in 1:4) {
   if(i == 1) {
      gen_x_plot(0.05) 
      next
   }
   par(new = T)
   gen_x_plot(0.05)
}

f:id:ushi-goroshi:20190312231141p:plain

自分で書いてみると理解できているかの確認になりますし、パラメータを変えたときの挙動を見ることで理解が深まりますので本当にオススメです。この後もなるべく自分で作図してみようと思います。