Esempio n. 1
0
def _L21_gamma_hypermodel_sampler(M, G, X0, gammas, n_orient, beta, n_burnin,
                                  n_samples, sc_n_samples=10,
                                  ss_n_samples=200,
                                  random_state=None,
                                  verbose=False):
    """Run Gamma sampler

    Parameters
    ----------
    M : array, shape (n_samples, n_times)
        The data.
    G : array, shape (n_samples, n_features)
        The forward operator / design matrix.
    X0 : array, shape (n_features, n_times)
        The initial X.
    gammas : array, shape (n_locations, n_times)
        The initial gammas.
    n_orient : int
        The number of orientation (1 : fixed or 3 : free or loose).
        Used for M/EEG application as there is 3 features per
        physical locations. We have n_locations = n_features // n_orient.
    bela : float
        The beta scale paraemter of the gamma distribution
    n_burnin : int
        The number of iterations in the burnin phase.
    n_samples : int
        The number of sampels to draw.
    ss_n_samples : int
        The number of samples in the slice sampler.
    random_state : int | None
        An integer to fix the seed of the numpy random number
        generator. Necessary to have replicable results.
    verbose : bool
        If True print info on optimization.

    Returns
    -------
    XChain : array, shape (n_features, n_times, n_samples)
        The X samples along the chain.
    gammaChain : array, shape (n_locations, n_samples)
        The gamma samples along the chain.
    """
    rng = check_random_state(random_state)
    n_dipoles = G.shape[1]
    n_locations = n_dipoles // n_orient
    _, n_times = M.shape

    XChain = np.zeros((n_dipoles, n_times, n_samples))
    gammaChain = np.zeros((n_locations, n_samples))

    # precompute some terms
    GColSqNorm = np.sum(G ** 2, axis=0)
    GTM = np.dot(G.T, M)
    GTG = np.dot(G.T, G)

    if not X0.all():
        X = np.zeros((n_locations * n_orient, n_times))
    else:
        X = X0

    for k in range(-n_burnin, n_samples):
        if verbose:
            print("Running iter %d" % k)
        # update X by single component Gibbs sampler
        # initialize with 0 instead of current state (this had a proper reason,
        # but we should re-examine)
        # X = np.zeros((n_locations * n_orient, n_times))

        for kSCGibbs in range(sc_n_samples):
            # print(" -- Running SC iter %d" % kSCGibbs)
            randLocOrder = rng.permutation(n_locations)
            for jLoc in randLocOrder:
                # a only depends on the location
                a = GColSqNorm[jLoc] / 2.
                c = 1. / gammas[jLoc]

                # extract X for this location
                XLoc = X[jLoc * n_orient: (jLoc + 1) * n_orient, :]
                XLocSqNorm = linalg.norm(XLoc, 'fro') ** 2

                # update all time points and all dir without random shuffle
                for jTime in range(n_times):
                    for jDir in range(n_orient):
                        # get corresponding dipole, time and block index
                        jComp = jDir + jLoc * n_orient
                        XjComp = X[jComp, jTime]
                        # compute b and d
                        b = GTM[jComp, jTime] - np.dot(X[:, jTime].T,
                                                       GTG[:, jComp]) + \
                            2 * a * XjComp
                        d = XLocSqNorm - XjComp**2
                        # call slice sampler
                        XjComp = _sc_slice_sampler(
                            a, b, c, d, XjComp, ss_n_samples, rng)
                        # update auxillary variables
                        XLocSqNorm = d + XjComp**2
                        X[jComp, jTime] = XjComp

        # check for instabilities cause by insufficient sampling steps,
        # usually leading to an explosion of the residual
        # if (linalg.norm(G.dot(X) - M, 'fro') / linalg.norm(M, 'fro')) > 10:
        #     raise ValueError('relative residual exceeded threshold, '
        #                      'the sampler is likely to diverge due to '
        #                      'insufficient precision in the block-sampling')

        # update gamma by umbrella sampler
        # Compute the amplitudes of the sources for one hyperparameter
        XBlkNorm = np.sqrt(groups_norm2(X.copy(), n_orient))
        gammas = _cond_gamma_hyperprior_sampler(XBlkNorm, beta, rng)

        # store results
        if k >= 0:
            XChain[:, :, k] = X
            gammaChain[:, k] = gammas

    return XChain, gammaChain
def compute_block_norms(w, n_orient):
    return np.sqrt(groups_norm2(w.copy(), n_orient))
Esempio n. 3
0
def compute_block_norms(w, nDir):
    return np.sqrt(groups_norm2(w.copy(), nDir))
Esempio n. 4
0
def _L21_gamma_hypermodel_sampler(M, G, X0, gammas, n_orient, beta, n_burnin,
                                  n_samples, sc_n_samples=10,
                                  ss_n_samples=200, verbose=False):
    # XXX : add docstring
    rng = np.random.RandomState(42)
    n_dipoles = G.shape[1]
    n_locations = n_dipoles // n_orient
    _, n_times = M.shape

    XChain = np.zeros((n_dipoles, n_times, n_samples))
    gammaChain = np.zeros((n_locations, n_samples))

    # precompute some terms
    GColSqNorm = np.sum(G ** 2, axis=0)
    GTM = np.dot(G.T, M)
    GTG = np.dot(G.T, G)

    if not X0.all():
        X = np.zeros((n_locations * n_orient, n_times))
    else:
        X = X0

    for k in range(-n_burnin, n_samples):
        if verbose:
            print("Running iter %d" % k)
        # update X by single component Gibbs sampler
        # initialize with 0 instead of current state (this had a proper reason,
        # but we should re-examine)
        # X = np.zeros((n_locations * n_orient, n_times))

        for kSCGibbs in range(sc_n_samples):
            # print(" -- Running SC iter %d" % kSCGibbs)
            randLocOrder = rng.permutation(n_locations)
            for jLoc in randLocOrder:
                # a only depends on the location
                a = GColSqNorm[jLoc] / 2.
                c = 1. / gammas[jLoc]

                # extract X for this location
                XLoc = X[jLoc * n_orient: (jLoc + 1) * n_orient, :]
                XLocSqNorm = linalg.norm(XLoc, 'fro') ** 2

                # update all time points and all dir without random shuffle
                for jTime in range(n_times):
                    for jDir in range(n_orient):
                        # get corresponding dipole, time and block index
                        jComp = jDir + jLoc * n_orient
                        XjComp = X[jComp, jTime]
                        # compute b and d
                        b = GTM[jComp, jTime] - np.dot(X[:, jTime].T,
                                                       GTG[:, jComp]) + \
                            2 * a * XjComp
                        d = XLocSqNorm - XjComp**2
                        # call slice sampler
                        XjComp = _sc_slice_sampler(
                            a, b, c, d, XjComp, ss_n_samples)
                        # update auxillary variables
                        XLocSqNorm = d + XjComp**2
                        X[jComp, jTime] = XjComp

        # check for instabilities cause by insufficient sampling steps,
        # usually leading to an explosion of the residual
        # if (linalg.norm(G.dot(X) - M, 'fro') / linalg.norm(M, 'fro')) > 10:
        #     raise ValueError('relative residual exceeded threshold, '
        #                      'the sampler is likely to diverge due to '
        #                      'insufficient precision in the block-sampling')

        # update gamma by umbrella sampler
        # Compute the amplitudes of the sources for one hyperparameter
        XBlkNorm = np.sqrt(groups_norm2(X.copy(), n_orient))
        gammas = _cond_gamma_hyperprior_sampler(XBlkNorm, beta)

        # store results
        if k >= 0:
            XChain[:, :, k] = X
            gammaChain[:, k] = gammas

    return XChain, gammaChain