Golangで多次元正規分布を生成する

前回の記事も書きましたが、 Golangrandパッケージでは、 一次元正規分布の乱数生成が可能です。 今回は、多次元正規分布から乱数を生成する方法についてまとめます。

どうやって生成するか

まずPRMLから引用します。

平均 \boldsymbol{\mu} ,共分散 \boldsymbol{\Sigma} を持つ多変量ガウス分布に従うベクトル値の変数を生成するには,  \boldsymbol{\Sigma} = \boldsymbol{LL}^{T}の形を取るコレスキー分解(Cholesky decomposition)を用いればよい(Press et al., 1992). このとき, もし \boldsymbol{z}がベクトル値の確率変数であり, その各要素が独立で, 平均0, 分散1のガウス分布に従うとすれば,  \boldsymbol{y} = \boldsymbol{\mu} + \boldsymbol{Lz}は平均  \boldsymbol{\mu}, 共分散 \boldsymbol{\Sigma}ガウス分布に従う.

rand.NormFloat64()は、まさに平均0、分散1の一次元正規分布の乱数を生成してくれるので、 与えられた \boldsymbol{\Sigma}をコレスキー分解すれば多次元正規分布からの乱数生成ができます。

gonumのmatパッケージでは、Cholesky型のFactorizeメソッドでコレスキー分解ができるので、こちらを使って多次元正規分布からの乱数を生成します。

コード

実装は以下です。MultiNorm関数として実装しています。 散布図を描くコードも含んでいるので、少し長いです。。。

gist3609a47a7f572bd8e479ef120dae3f0e

実行結果

f:id:cipepser:20171029222325p:plain

References