多次元ガウス分布 : ガウス-ウィシャート分布 (ベイズ推定)


# 記事の目的
多次元ガウス分布の平均と分散共分散行列が未知のときの共役事前分布であるガウス-ウィシャート分布を使用し、Rを使ってベイズ推定します。
商品Aの購買個数と、商品Bの購買個数の平均と分散共分散行列を事後分布で推定します。
参考：[ベイズ推論による機械学習入門](https://www.amazon.co.jp/%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%88%E3%82%A2%E3%83%83%E3%83%97%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E3%83%99%E3%82%A4%E3%82%BA%E6%8E%A8%E8%AB%96%E3%81%AB%E3%82%88%E3%82%8B%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E5%85%A5%E9%96%80-KS%E6%83%85%E5%A0%B1%E7%A7%91%E5%AD%A6%E5%B0%82%E9%96%80%E6%9B%B8-%E9%A0%88%E5%B1%B1-%E6%95%A6%E5%BF%97/dp/4061538322)

# 目次
[0. モデルの説明](#0-モデルの説明)
[1. ライブラリ](#1-ライブラリ)
[2. 推定する分布](#2-推定する分布)
[3. 事前分布](#3-事前分布)
[4. 事後分布](#4-事後分布)
[5. 予測分布](#5-予測分布)

#0. モデルの説明
![IMG_0188.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/775500/442c1456-ece5-ab2d-d83b-4e243c2d280a.jpeg)



#1. ライブラリ
```R:
library(dplyr)
library(mvtnorm)
library(MCMCpack)
library(ellipse)
set.seed(100)
```

#2. 推定する分布
商品Aの購買個数と、商品Bの購買個数は、それぞれ平均が50, 170で、標準偏差が10, 相関係数が0.7の多次元ガウス分布に従います(適当)。
この真の分布の平均と共分散行列を事後分布で推定します。

```R:
#真の共分散行列
sigma.true <- matrix(c(10^2, 0.7*10^2, 0.7*10^2, 10^2), ncol=2)
#真の平均、共分散行列からサンプル
X.true <- rmvnorm(1000, mean = c(50, 170), sigma=sigma.true)
#可視化
plot(X.true[,1],X.true[,2], xlim = c(0, 100), ylim = c(120, 220), xlab="商品Aの購買個数", ylab="商品Bの購買個数")
ell <-  ellipse(sigma.true) + matrix(rep(c(50,170), each=100), nrow=100) 
lines(ell, lw=2)

```
>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/775500/7b43f6f7-c11b-c4a9-a4aa-4dfe484bda44.png)



#3. 事前分布
事前分布として、多次元ガウス分布の平均と分散共分散行列が未知のときの共役事前分布であるガウス-ウィシャート分布を指定します。

```R:
#ハイパーパラメータ
m0 <- c(0, 0)
beta0 <- 1/100^2
n0 <- 3
w.inv0 <- diag(2)*100
#パラメータ
lambda0 <- diag(2)
#事前分布u
u.pre <- rmvnorm(1000, mean = m0, sigma=solve(lambda0*beta0))
par(mfrow=c(1,2))
plot(u.pre[,1],u.pre[,2], xlim = c(-200, 200), ylim = c(-200, 200), xlab="商品Aの平均購買個数", ylab="商品Bの平均購買個数")
#事前分布lambda
plot(50,170, xlim = c(0, 100), ylim = c(120, 220), xlab="商品Aの購買個数", ylab="商品Bの購買個数")
par(new=T)
for(i in 1:100){
  w.pre <- riwish(n0, w.inv0)
  ell <-  ellipse(w.pre) + matrix(rep(c(50,170), each=100), nrow=100) 
  lines(ell, lw=2)
}
```
>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/775500/0f192c51-f21f-1ff6-5864-f170d900a9c2.png)



#4. 事後分布
真の分布から100個サンプルを取って事後分布を推定します。
下図から、平均も分散共分散行列もうまく推定できていることが分かります。

```R:
X <- rmvnorm(100, mean = c(50, 170), sigma=sigma.true)
#事後分布u
beta <- nrow(X)+beta0
m <- (apply(X, 2, sum)+(beta0*m0))/beta
X.sample <- rmvnorm(1000, mean = m, sigma=solve(beta*lambda0))
plot(X.sample[,1], X.sample[,2], xlim = c(0, 100), ylim = c(120, 220), col="green",
     xlab="商品Aの平均購買個数", ylab="商品Bの平均購買個数")
#事後分布lambda
n <- nrow(X)+n0
sum.tmp <- 0
for(i in 1:nrow(X)){
  sum.tmp <- sum.tmp + (X[i,]) %*% t(X[i,])
}
w.inv <- sum.tmp + (beta0*m0%*%t(m0)) - (beta*m%*%t(m)) + w.inv0
plot(50,170, xlim = c(0, 100), ylim = c(120, 220),
     xlab="商品Aの購買個数", ylab="商品Bの購買個数")
par(new=T)
for(i in 1:100){
  w.post <- riwish(n, w.inv)
  ell <-  ellipse(w.post) + matrix(rep(c(50,170), each=100), nrow=100) 
  lines(ell, col="green", lw=2)
}
```
>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/775500/5ab963e0-6ec7-4666-d0a5-bb0684c772e3.png)



#5. 予測分布
予測分布から1000個サンプルを取って可視化しました。
下図から、うまく推定できていることが分かります。

```R:
u.predict <- m
lambda.predict <- (1-2+n)*beta*solve(w.inv)/(1+beta)
n.predict <- 1-2+n
X.predict <- rmvt(1000, delta = u.predict, sigma = solve(lambda.predict), df = n.predict, type="shifted")
par(mfrow=c(1,1))
plot(X.predict[,1],X.predict[,2], xlim = c(0, 100), ylim = c(120, 220),
     xlab="商品Aの平均購買個数", ylab="商品Bの平均購買個数")
ell <-  ellipse(sigma.true) + matrix(rep(c(50,170), each=100), nrow=100) 
lines(ell, col="blue", lw=2)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/775500/ad8443ef-6c41-cb3b-8d54-b6174320478b.png)