# 1. 均值和方差未知的多元正态分布的后验（Multivariate normal with unknown mean and variance）

$\quad$假设有N个观测值 {xi|i=1,2,...,N} $\{x_{i}|i=1,2,...,N\}$，且服从均值为 μ $\mu$方差为 Σ $\Sigma$的多元正态分布，即:

xiN(μ,Σ)

(μ,Σ)Σμ|ΣNIW(μ0,κ0;ν0,Λ0)InvWishart(ν0,Λ0)N(μ0,Σ/κ0)

p(Σ|Λ0,ν0)=|Λ0|ν0/2|Σ|(ν0+k+1)/2exp(tr(Λ0Σ1)/2)2ν0k/2Γk(ν0/2)

Γk() $\Gamma_{k}(\cdot)$是多变量Gamma分布， ν0 $\nu_{0}$ Λ0 $\Lambda_{0}$分别是逆威沙特分布的自由度和尺度矩阵， k $k$是数据的维度。

(μ,Σ)NIW(μ,κ;ν,Λ)

μκνΛ=κ0κ0+nμ0+Nκ0+Nx¯=κ0+Nν0+N=Λ0+n=1N(xix¯)(xix¯)T+κ0Nκ0+N(x¯μ0)(x¯μ0)T

# 2. 从后验分布中采样均值 μ $\mu$和方差 Σ $\Sigma$

biibij=Vi+r=1i1N2ri,1ik=NijVi+r=1i1NriNrj,i<jk

import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.math3.linear.Array2DRowRealMatrix;
import org.apache.commons.math3.linear.CholeskyDecomposition;
import org.apache.commons.math3.linear.LUDecomposition;
import org.apache.commons.math3.linear.RealMatrix;
import org.apache.commons.math3.linear.SingularMatrixException;
import org.apache.commons.math3.random.RandomGenerator;
import org.apache.commons.math3.random.Well19937c;

/**
* Inverse Wishart distribution implementation, to sample random covariances matrices for
* multivariate gaussian distributions.
* <p/>
* The sampling method follows the procedure described by Odell & Feiveson, 1966 to get samples
* from a Wishart distribution, and then computes the inverse of the obtained samples.
*
* @author Marc Pujol <mpujol@iiia.csic.es>
*/
public class InverseWishartDistribution {
private static final Logger LOG = Logger.getLogger(InverseWishartDistribution.class.getName());

private double df;
private RealMatrix scaleMatrix;
private CholeskyDecomposition cholesky;
private RandomGenerator random;

/**
* Builds a new Inverse Wishart distribution with the given scale and degrees of freedom.
*
* @param scaleMatrix scale matrix(Λ)
* @param df degrees of freedom.
*/
public InverseWishartDistribution(RealMatrix scaleMatrix, double df) {
if (!scaleMatrix.isSquare()) {
throw new RuntimeException("scaleMatrix must be square.");
}

this.scaleMatrix = scaleMatrix;
this.df = df;
this.random = new Well19937c();
initialize();
}

private void initialize() {
final int dim = scaleMatrix.getColumnDimension();

// Build gamma distributions for the diagonal
for (int i = 0; i < dim; i++) {

}

// Build the cholesky decomposition
cholesky = new CholeskyDecomposition(inverseMatrix(scaleMatrix));
}

/**
* Reseeds the random generator.
*
* @param seed new random seed.
*/
public void reseedRandomGenerator(long seed) {
random.setSeed(seed);
for (int i = 0, len = scaleMatrix.getColumnDimension(); i < len; i++) {
gammas[i].reseedRandomGenerator(seed+i);
}
}

/**
* Returns the inverse matrix.
* @return inverted matrix.
*/
public RealMatrix inverseMatrix(RealMatrix A) {
RealMatrix result = new LUDecomposition(A).getSolver().getInverse();
return result;
}

/**
* Returns a sample matrix from this distribution.
* @return sampled matrix.
*/
public RealMatrix sample() {

for (int i=0; i<100; i++) {
try {
RealMatrix A = sampleWishart();
RealMatrix result = inverseMatrix(A);
LOG.log(Level.FINE, "Cov = {0}", result);
return result;
} catch (SingularMatrixException ex) {
LOG.finer("Discarding singular matrix generated by the wishart distribution.");
}
}
throw new RuntimeException("Unable to generate inverse wishart samples!");
}

private RealMatrix sampleWishart() {
final int dim = scaleMatrix.getColumnDimension();

// Build N_{ij}
double[][] N = new double[dim][dim];
for (int j = 0; j < dim; j++) {
for (int i = 0; i < j; i++) {
N[i][j] = random.nextGaussian();
}
}
if (LOG.isLoggable(Level.FINEST)) {
LOG.log(Level.FINEST, "N = {0}", Arrays.deepToString(N));
}

// Build V_j
double[] V = new double[dim];
for (int i = 0; i < dim; i++) {
V[i] = gammas[i].sample();
}
if (LOG.isLoggable(Level.FINEST)) {
LOG.log(Level.FINEST, "V = {0}", Arrays.toString(V));
}

// Build B
double[][] B = new double[dim][dim];

// b_{11} = V_1 (first j, where sum = 0 because i == j and the inner
//               loop is never entered).
// b_{jj} = V_j + \sum_{i=1}^{j-1} N_{ij}^2, j = 2, 3, ..., p
for (int j = 0; j < dim; j++) {
double sum = 0;
for (int i = 0; i < j; i++) {
sum += Math.pow(N[i][j], 2);
}
B[j][j] = V[j] + sum;
}
if (LOG.isLoggable(Level.FINEST)) {
LOG.log(Level.FINEST, "B*_jj : = {0}", Arrays.deepToString(B));
}

// b_{1j} = N_{1j} * \sqrt V_1
for (int j = 1; j < dim; j++) {
B[0][j] = N[0][j] * Math.sqrt(V[0]);
B[j][0] = B[0][j];
}
if (LOG.isLoggable(Level.FINEST)) {
LOG.log(Level.FINEST, "B*_1j = {0}", Arrays.deepToString(B));
}

// b_{ij} = N_{ij} * \sqrt V_1 + \sum_{k=1}^{i-1} N_{ki}*N_{kj}
for (int j = 1; j < dim; j++) {
for (int i = 1; i < j; i++) {
double sum = 0;
for (int k = 0; k < i; k++) {
sum += N[k][i] * N[k][j];
}
B[i][j] = N[i][j] * Math.sqrt(V[i]) + sum;
B[j][i] = B[i][j];
}
}
if (LOG.isLoggable(Level.FINEST)) {
LOG.log(Level.FINEST, "B* = {0}", Arrays.deepToString(B));
}

RealMatrix BMat = new Array2DRowRealMatrix(B);
RealMatrix A = cholesky.getL().multiply(BMat).multiply(cholesky.getLT());
if (LOG.isLoggable(Level.FINER)) {
LOG.log(Level.FINER, "A* = {0}", Arrays.deepToString(N));
}
return A;
}

}

Java代码：链接其介绍文档链接其介绍文档
c#代码：链接其对应的介绍
Matlab：其中有一个iwishrnd方法，其介绍在这里

[1] Gelman, A., Carlin et al., Bayesian data analysis. London: Chapman & Hall
[2] Stanley Sawyer, Wishart Distributions and Inverse-Wishart Sampling
[3] Odell, P.L., and A.H. Feiveson (1966) A numerical procedure to generate a sample covariance matrix

08-13

09-19 2344
12-27 1万+
10-30 704
02-25 7617
12-19 9114
11-08 8185
08-09 3637
09-28 5333
06-04 1万+
06-03 1万+
05-31
06-21 1万+
09-07 7063