示例#1
0
    def _draw_W11_Wishart(self, S, W, p, q, n, lambda_, T=1):
        """Draw from W11 Posterior scaled by the Temperature T: P(W11|W21,T_inv,...)^(T)

        DEPRECATED

        Arguments:
            S {[type]} -- [description]
            W {[type]} -- [description]
            p {[type]} -- [description]
            q {[type]} -- [description]
            n {[type]} -- [description]
            lambda_ {[type]} -- [description]

        Keyword Arguments:
            T {int} -- [description] (default: {1})
        """
        s11 = S[0:p, 0:p]
        s12 = S[0:p, p:(p + q)]
        s22 = S[p:(p + q), p:(p + q)]
        s22_lambda_inv = util.cholesky_invert(s22 + np.eye(N=q, M=q) * lambda_)

        n_ = (3 * n - 2 * q - 1) / 3
        Sigma = s11 - s12 @ s22_lambda_inv @ s12.T + np.eye(p)
        # updated df due to SA cooling
        scale = T * Sigma
        df = (n_ - scale.shape[0] - 1) / T + scale.shape[0] + 1

        W11 = stats.wishart.rvs(df=df, scale=scale)
        return (W11)
示例#2
0
 def draw_W22(self, S, W, p, q, n, lambda_):
     # W22 = Wishart(n, (S22+lambda*I)^-1) + W21*(W11)^-1 * W12
     if (n < q):
         a = q - n + 1
     else:
         a = 0
     s22_lambda_inv = util.cholesky_invert(S[p:(p + q), p:(p + q)] +
                                           np.eye(N=q, M=q) * lambda_)
     tmp = stats.wishart.rvs(df=n + a, scale=s22_lambda_inv)
     W22 = tmp + \
         W[0:p, p:(p+q)].T @ np.linalg.solve(W[0:p, 0:p], W[0:p, p:(p+q)])
     return (W22)
示例#3
0
    def _draw_MGIG_inv(n_, A, B, num_its=10):
        """Returns the inverse of a MGIG draw via a continued fraction of Wishart draws.
        (X~MGIG(n'=0.5(n+n0+2p-2), W12*(S22+I)W21, S11+I) and W11 = X^-1)

        Arguments:
            n_ {int} -- [Degrees of Freedom]
            A {ndarray} -- []
            B {ndarray} -- []

        Keyword Arguments:
            num_its {int} -- Number of iterations (default: {20})
        """
        p = A.shape[0]
        B_inv = util.cholesky_invert(B)
        eigvals = np.linalg.eigvalsh(A)
        if (np.sum(eigvals > 1e-5) < p):
            A = A + (np.min(np.abs(eigvals)) + 0.01) * np.identity(p)
        A_inv = util.cholesky_invert(A)
        # draw from W(df = n + n_0 + 3p - 3, (W_12(S_22 + I)W_21)^-1
        # As we are only given n' of the MGIG for W_11^-1, we need to express it in terms of this with
        # df = 2*n' + p - 1
        df = 2 * n_ + p - 1
        # MGIG dfs my version
        # df = 2*n_
        X = np.zeros(shape=np.shape(A))

        Y1 = stats.wishart.rvs(df=df, scale=A_inv, size=num_its)

        Y2 = stats.wishart.rvs(df=df, scale=B_inv, size=num_its)

        for i in range(0, num_its):
            # This would converge to W_11^-1, but we need W_11, so don't do the last inversion
            # (see notes at 6.2, "Sampling from the MGIG")
            if (i > 0):
                X = util.cholesky_invert(X)
            X = Y1[i] + util.cholesky_invert(Y2[i] + X)
        return (X)
示例#4
0
    def _draw_W12(self, S, W, p, q, T_inv, lambda_, T=1):
        """Draw from W12 Posterior scaled by the Temperature T: P(W12|W11,T_inv,...)^(T)

        Arguments:
            T_inv {[type]} -- [description]
            w11 {[type]} -- [description]
            s12 {[type]} -- [description]
            s22 {[type]} -- [description]
            p {[type]} -- [description]
            q {[type]} -- [description]
            T {float} -- SA cooling parameter
        """
        w11 = W[0:p, 0:p]
        s12 = S[0:p, p:(p + q)]
        s22 = S[p:(p + q), p:(p + q)]

        w11_inv = util.cholesky_invert(w11)

        identity = np.eye(N=q, M=q)

        # block cholesky decomposition
        L_T = block_cholesky_BWD(s22 + lambda_ * identity, w11_inv, T_inv)
        L = L_T.T

        # method as in Notes, in my opinion a bit clearer than in initial R-code(both are ultimately similar)
        # NOTE: flatten is column major in numpy, so no need to transpose s12 prior to flattening.
        v = (s12).flatten()
        y = linalg.solve_triangular(a=L, b=-v, lower=True)
        mu = linalg.solve_triangular(a=L_T, b=y)
        r = sp.random.standard_normal(size=(p * q))
        b = linalg.solve_triangular(a=L_T, b=r)
        # cooling parameter
        b = b * np.sqrt(T)

        w12 = (mu + b).reshape(p, q)
        return (w12)
示例#5
0
    def __init__(self,
                 X,
                 p,
                 q,
                 lambda_,
                 burnin,
                 NSCAN,
                 DO_COPULA=True,
                 plugin_threshold=40,
                 TRUE_INVCOV=None,
                 gig_seed=4321,
                 use_w=False,
                 Z_save_each=-1):
        """Set options, data and initial values for the BMB.

        Arguments:
            X {ndarray} -- Data
            p {int} -- Number of query variables
            q {int} -- number of non-query variables
            burnin {int} -- Burnin of MCMC sampler
            lambda_ {float} -- Sparsity hyperparameter

        Keyword Arguments:
            NSCAN {int} -- Number of MCMC iterations (default: {1000})
            plugin_threshold {int} --  (default: {40})
            TRUE_INVCOV {ndarray} -- If available, the true inverse covariance matrix. Used for diagnostics. (default: {None})
            DO_COPULA {bool} -- Wrap semi-parametric copula around the Gibbs sampler (default: {False})

        """
        assert (np.shape(X)[1] == p + q)
        assert (q > 0 and p > 0 and lambda_ > 0)
        assert (burnin > 0 and NSCAN > 0)

        self.DO_COPULA = DO_COPULA

        self.TRUE_INVCOV = TRUE_INVCOV
        self.p = p
        self.q = q
        self.num_vars = self.p + self.q
        self.n = np.shape(X)[0]
        self.use_w = use_w

        self.lambda_ = lambda_
        self.NSCAN = NSCAN
        self.burnin = burnin
        self.X = X

        self.gig_seed = gig_seed
        self.GIG = gig.GIG(gig_seed)

        # initialize S, W and T.inv
        self.T_inv = np.random.normal(size=p * q).reshape(p, q)

        if (DO_COPULA):
            self.Z, self.S = util.cov_from_normscores(X,
                                                      scaled=False,
                                                      fill_na=True)
        else:
            self.Z, self.S = util.cov_from_normscores(X,
                                                      scaled=True,
                                                      fill_na=False)
            self.S = self.S * self.n

        self.W0 = np.eye(p + q) * self.lambda_
        if (self.n < self.S.shape[0]):
            a = self.S.shape[0] - self.n + 1
        else:
            a = 0
        self.W = stats.wishart.rvs(df=self.n + a,
                                   scale=util.cholesky_invert(self.S +
                                                              self.W0))

        # keep track of intermediate results
        self.W_list = np.zeros((NSCAN, self.W.shape[0], self.W.shape[1]))
        self.W_list_burnin = self.W_list[0:burnin, :, :]
        self.W_list_acc = self.W_list[burnin:NSCAN, :, :]
        self.T_inv_list = np.zeros((NSCAN, p, q))
        self.T_inv_list_acc = self.T_inv_list[burnin:NSCAN, :, :]

        self.Z_save_each = Z_save_each
        if (self.Z_save_each > 0):
            self.Z_saves = np.zeros((np.floor_divide(
                (self.NSCAN - self.burnin - 1),
                self.Z_save_each), self.Z.shape[0], self.Z.shape[1]))

        self.Z_mean = np.zeros((self.Z.shape[0], self.Z.shape[1]))
        self.Z_ssd = np.zeros((self.Z.shape[0], self.Z.shape[1]))
        if (DO_COPULA):
            # get the levels and number of levels
            # for the copula
            self.R = BMB.calc_R(self.X)
            self.Rlevels = np.amax(self.R, axis=0)

            self.plugin_marginal = np.apply_along_axis(
                lambda col: np.unique(col).shape[0] > plugin_threshold, 0,
                X) * 1