Updating multivariate priors

First of all, many thanks for the prompt replies. I really appreciate. It makes sense to me to use an approximation. Ultimately, I’ll be interested in non-negativity constrained parameters, and thus in something like a Dirichlet distribution approximation (as I read that the Wishart distribution is not recommended within PyMC).

As a first step, I have tried to implement a receding horizon estimator based on a Multivariate Normal-distribution, as suggested by @junpenglao. Based on other examples that I’ve found across the web, I think I got the overall structure right. But I’m not sure exactly how to update the parameters that characterize the distribution of the covariance matrix.

Below is a MWE, in which two lines are tagged with a FIXME note (the same lines appear a bit later again). Any help with correctly specifiying these update statements would be highly appreciated.

import numpy as np
import pymc3 as pm
import theano
import warnings
warnings.simplefilter(action='ignore', category=FutureWarning)

μ_actual = np.array([1, -2])
Σ_actual = np.array([[0.5, -0.3],
                     [-0.3, 1.]])

def getNewObservations(N=100):
    return np.random.multivariate_normal(μ_actual, Σ_actual, size=N)

def printResults(trace):
    #mean
    print("deviation in μ: ", np.mean(trace["μ"],0) / μ_actual - 1)

    #covariance
    L = np.mean(trace["L"],0)
    print('deviation in Σ: ', L.dot(L.T) / Σ_actual - 1)

initialObservations = getNewObservations(1000)

with pm.Model() as model:
    packed_L = pm.LKJCholeskyCov('packed_L', n=2, eta=2., sd_dist=pm.HalfCauchy.dist(2.5))
    L = pm.Deterministic("L", pm.expand_packed_triangular(2, packed_L))

    μ = pm.Normal('μ', mu=0., sd=10., shape=2, testval=initialObservations.mean(axis=0))
    obs = pm.MvNormal('obs', μ, chol=L, observed=initialObservations)

    stepNUTS = pm.NUTS(vars=[packed_L, μ])
    trace = pm.sample(cores=1, step=[stepNUTS])

printResults(trace) #DEBUG

#### rolling-horizon model
traces = [trace]

#FIXME
eta_cov = theano.shared(???, name="eta_cov")
#FIXME
sd_dist_cov_beta = theano.shared(???, name="sd_dist_cov_beta")

mu_mean = theano.shared(trace['μ'].mean(axis=0), name="mu_mean")
sd_mean = theano.shared(trace['μ'].std(axis=0), name="sd_mean")

new_observations = getNewObservations()
observations_shared = theano.shared(new_observations)

#iteration 0
with pm.Model() as update_model:
    packed_L = pm.LKJCholeskyCov('packed_L', n=2, eta=eta_cov, sd_dist=pm.HalfCauchy.dist(sd_dist_cov_beta))
    L = pm.Deterministic("L", pm.expand_packed_triangular(2, packed_L))
    μ = pm.Normal('μ', mu=mu_mean, sd=sd_mean, shape=2, testval=observations_shared.mean(axis=0))

    obs = pm.MvNormal('obs', μ, chol=L, observed=observations_shared)

    stepNUTS = pm.NUTS(vars=[packed_L, μ])
    trace = pm.sample(cores=1, step=[stepNUTS])

    traces.append(trace)

    printResults(trace) #DEBUG

#iterations 1,2,...
for _ in range(1,3):
    #retrieve new observations
    observations_shared.set_value(getNewObservations())

    #FIXME
    eta_cov.set_value(?)
    sd_dist_cov_beta.set_value(?)

    mu_mean.set_value(trace['μ'].mean(axis=0))
    sd_mean.set_value(trace['μ'].std(axis=0))

    with update_model:
        stepNUTS = pm.NUTS(vars=[packed_L, μ])
        trace = pm.sample(cores=1, step=[stepNUTS])
        traces.append(trace)

    printResults(trace) #DEBUG

If there’s anything else wrong, I’d equally appreciate any comments. Many thanks in advance.