Пример #1
0
 def KL_distance(theta1, theta2, N):
     D = theta1.shape[0]
     p1 = transforms.compute_p(theta1)
     eta1 = transforms.compute_eta(p1)
     psi1 = transforms.compute_psi(theta1)
     p2 = transforms.compute_p(theta2)
     eta2 = transforms.compute_eta(p2)
     psi2 = transforms.compute_psi(theta2)
     S1 = energies.compute_entropy(theta1.reshape(1, D), eta1.reshape(1, D),
                                   psi1, 2)
     S2 = energies.compute_entropy(theta2.reshape(1, D), eta2.reshape(1, D),
                                   psi2, 2)
     KL1 = -S1 + psi2 - eta1.dot(theta2)
     KL2 = -S2 + psi1 - eta2.dot(theta1)
     KL = (KL1 + KL2) / 2
     return KL
Пример #2
0
def gradient_1sample(n_samples, emd):
    """
    Computes one sample of the expectation inside the equation for the
    gradient of the q function with respect to the network parameters of
    the Ising models of the main fetures.
    :param container .EMData emd:
        All data pertaining to the EM algorithm.
    """
    # Take 1 sample of theta for all time steps
    generated_theta = sample_theta(emd)
    # Compute 1 sample
    sample_value = 0
    for t in range(emd.T):
        theta_mixed = transforms.compute_mixed_theta(generated_theta[t,:], \
                                                     emd.J)
        if emd.exact:
            p = transforms.compute_p(theta_mixed)
            eta_tilde = transforms.compute_eta(p)
        else:
            eta_tilde = bethe_approximation.compute_eta_hybrid(theta_mixed, emd.N)
        a = emd.F_tilde[t,:] - eta_tilde
        # Summation for all time bins
        sample_value += emd.R * numpy.dot(a[:,numpy.newaxis], \
                                          generated_theta[t,numpy.newaxis,:])

    return sample_value
Пример #3
0
def newton_raphson(emd, t):
    """
    Computes the MAP estimate of the natural parameters at some timestep, given
    the observed spike patterns at that timestep and the one-step-prediction
    mean and covariance for the same timestep.

    :param container.EMData emd:
        All data pertaining to the EM algorithm.
    :param int t:
        Timestep for which to compute the maximum posterior probability.

    :returns:
        Tuple containing the mean and covariance of the posterior probability
        density, each as a numpy.ndarray.
    """
    # Extract observed patterns and one-step predictions for time t
    y_t = emd.y[t,:]
    theta_o = emd.theta_o[t,:]
    sigma_o = emd.sigma_o[t,:,:]
    R = emd.R
    # Initialise theta_max to the smooth theta value of the previous iteration
    theta_max = emd.theta_s[t,:]
    # Use non-normalised posterior prob. as loop guard
    lpp = -numpy.inf
    lpc = probability.log_likelihood(y_t, theta_max, R) +\
          probability.log_multivariate_normal(theta_max, theta_o, sigma_o)
    iterations = 0
    # Iterate the gradient ascent algorithm until convergence or failure
    while lpc - lpp > GA_CONVERGENCE:
        # Compute the eta of the current theta values
        p = transforms.compute_p(theta_max)
        eta = transforms.compute_eta(p)
        # Compute the inverse of one-step covariance
        sigma_o_i = numpy.linalg.inv(sigma_o)
        # Compute the first derivative of the posterior prob. w.r.t. theta_max
        dllk = R * (y_t - eta)
        dlpr = -numpy.dot(sigma_o_i, theta_max - theta_o)
        dlpo = dllk + dlpr
        # Compute the second derivative of the posterior prob. w.r.t. theta_max
        ddlpo = -R * transforms.compute_fisher_info(p, eta) - sigma_o_i
        # Dot the results to climb the gradient, and accumulate the result
        ddlpo_i = numpy.linalg.inv(ddlpo)
        theta_max -= numpy.dot(ddlpo_i, dlpo)
        # Update previous and current posterior prob.
        lpp = lpc
        lpc = probability.log_likelihood(y_t, theta_max, R) +\
              probability.log_multivariate_normal(theta_max, theta_o, sigma_o)
        # Count iterations
        iterations += 1
        # Check for check for overrun
        if iterations == MAX_GA_ITERATIONS:
            raise Exception('The maximum-a-posterior gradient-ascent '+\
                'algorithm did not converge before reaching the maximum '+\
                'number iterations.')

    return theta_max, -ddlpo_i
Пример #4
0
def compute_eta(theta, N, O, R=1000):
    """ Computes eta from given theta.

    :param numpy.ndarray theta:
        (t, d) array with natural parameters
    :param int N:
        number of cells
    :param int O:
        order of model
    :param int R:
        trials that should be sampled to estimate eta
    :return numpy.ndarray, list:
        (t, d) array with natural parameters parameters and a list with indices of bins, for which has been sampled

    Details: Tries to estimate eta by solving the forward problem from TAP. However, if it fails we fall back to
    sampling. For networks with less then 15 neurons exact solution is computed and for first order analytical solution
    is used.
    """
    T, D = theta.shape
    eta = numpy.empty(theta.shape)
    bins_to_sample = []
    if O == 1:
        eta = compute_ind_eta(theta[:, :N])
    elif O == 2:
        # if few cells compute exact rates
        if N > 15:
            for i in range(T):
                # try to solve forward problem
                try:
                    eta[i] = mean_field.forward_problem(theta[i], N, 'TAP')
                # if it fails remember bin for sampling
                except Exception:
                    bins_to_sample.append(i)
            if len(bins_to_sample) != 0:
                theta_to_sample = numpy.empty([len(bins_to_sample), D])
                for idx, bin2sampl in enumerate(bins_to_sample):
                    theta_to_sample[idx] = theta[bin2sampl]
                spikes = synthesis.generate_spikes_gibbs_parallel(
                    theta_to_sample, N, O, R, sample_steps=100)
                eta_from_sample = transforms.compute_y(spikes, O, 1)
                for idx, bin2sampl in enumerate(bins_to_sample):
                    eta[bin2sampl] = eta_from_sample[idx]

        # if large ensemble approximate
        else:
            transforms.initialise(N, O)
            for i in range(T):
                p = transforms.compute_p(theta[i])
                eta[i] = transforms.compute_eta(p)

    return eta, bins_to_sample
Пример #5
0
def compute_eta(theta, N, O, R=1000):
    """ Computes eta from given theta.

    :param numpy.ndarray theta:
        (t, d) array with natural parameters
    :param int N:
        number of cells
    :param int O:
        order of model
    :param int R:
        trials that should be sampled to estimate eta
    :return numpy.ndarray, list:
        (t, d) array with natural parameters parameters and a list with indices of bins, for which has been sampled

    Details: Tries to estimate eta by solving the forward problem from TAP. However, if it fails we fall back to
    sampling. For networks with less then 15 neurons exact solution is computed and for first order analytical solution
    is used.
    """
    T, D = theta.shape
    eta = numpy.empty(theta.shape)
    bins_to_sample = []
    if O == 1:
        eta = compute_ind_eta(theta[:,:N])
    elif O == 2:
        # if few cells compute exact rates
        if N > 15:
            for i in range(T):
                # try to solve forward problem
                try:
                    eta[i] = mean_field.forward_problem(theta[i], N, 'TAP')
                # if it fails remember bin for sampling
                except Exception:
                    bins_to_sample.append(i)
            if len(bins_to_sample) != 0:
                theta_to_sample = numpy.empty([len(bins_to_sample), D])
                for idx, bin2sampl in enumerate(bins_to_sample):
                    theta_to_sample[idx] = theta[bin2sampl]
                spikes = synthesis.generate_spikes_gibbs_parallel(theta_to_sample, N, O, R, sample_steps=100)
                eta_from_sample = transforms.compute_y(spikes, O, 1)
                for idx, bin2sampl in enumerate(bins_to_sample):
                    eta[bin2sampl] = eta_from_sample[idx]

        # if large ensemble approximate
        else:
            transforms.initialise(N, O)
            for i in range(T):
                p = transforms.compute_p(theta[i])
                eta[i] = transforms.compute_eta(p)

    return eta, bins_to_sample
Пример #6
0
def newton_raphson(y_t, X_t, R, theta_0, theta_o, sigma_o, sigma_o_i, *args):
    """
    TODO update comments to elaborate on how this method differs from the others

    :param container.EMData emd:
        All data pertaining to the EM algorithm.
    :param int t:
        Timestep for which to compute the maximum posterior probability.

    :returns:
        Tuple containing the mean and covariance of the posterior probability
        density, each as a numpy.ndarray.
    """
    # Initialise the loop guards
    max_dlpo = numpy.inf
    iterations = 0
    # Initialise theta_max to the smooth theta value of the previous iteration
    theta_max = theta_0
    # Iterate the gradient ascent algorithm until convergence or failure
    while max_dlpo > GA_CONVERGENCE:
        # Compute the eta of the current theta values
        p = transforms.compute_p(theta_max)
        eta = transforms.compute_eta(p)
        # Compute the first derivative of the posterior prob. w.r.t. theta_max
        dllk = R * (y_t - eta)
        dlpr = -numpy.dot(sigma_o_i, theta_max - theta_o)
        dlpo = dllk + dlpr
        # Compute the second derivative of the posterior prob. w.r.t. theta_max
        ddlpo = -R * transforms.compute_fisher_info(p, eta) - sigma_o_i
        # Dot the results to climb the gradient, and accumulate the
        # Small regularization added to avoid singular matrices
        ddlpo_i = numpy.linalg.inv(ddlpo + numpy.finfo(float).eps*\
                                   numpy.identity(eta.shape[0]))
        # Update Theta
        theta_max -= numpy.dot(ddlpo_i, dlpo)
        # Update the look guard
        max_dlpo = numpy.amax(numpy.absolute(dlpo)) / R
        # Count iterations
        iterations += 1
        # Check for check for overrun
        if iterations == MAX_GA_ITERATIONS:
            raise Exception('The maximum-a-posterior gradient-ascent '+\
                'algorithm did not converge before reaching the maximum '+\
                'number iterations.')

    return theta_max, -ddlpo_i
Пример #7
0
def newton_raphson(y_t, X_t, R, theta_0, theta_o, sigma_o, sigma_o_i, *args):
    """
    TODO update comments to elaborate on how this method differs from the others

    :param container.EMData emd:
        All data pertaining to the EM algorithm.
    :param int t:
        Timestep for which to compute the maximum posterior probability.

    :returns:
        Tuple containing the mean and covariance of the posterior probability
        density, each as a numpy.ndarray.
    """
    # Initialise the loop guards
    max_dlpo = numpy.inf
    iterations = 0
    # Initialise theta_max to the smooth theta value of the previous iteration
    theta_max = theta_0
    # Iterate the gradient ascent algorithm until convergence or failure
    while max_dlpo > GA_CONVERGENCE:
        # Compute the eta of the current theta values
        p = transforms.compute_p(theta_max)
        eta = transforms.compute_eta(p)
        # Compute the first derivative of the posterior prob. w.r.t. theta_max
        dllk = R * (y_t - eta)
        dlpr = -numpy.dot(sigma_o_i, theta_max - theta_o)
        dlpo = dllk + dlpr
        # Compute the second derivative of the posterior prob. w.r.t. theta_max
        ddlpo = -R * transforms.compute_fisher_info(p, eta) - sigma_o_i
        # Dot the results to climb the gradient, and accumulate the
        # Small regularization added to avoid singular matrices
        ddlpo_i = numpy.linalg.inv(ddlpo + numpy.finfo(float).eps*\
                                   numpy.identity(eta.shape[0]))
        # Update Theta
        theta_max -= numpy.dot(ddlpo_i, dlpo)
        # Update the look guard
        max_dlpo = numpy.amax(numpy.absolute(dlpo)) / R
        # Count iterations
        iterations += 1
        # Check for check for overrun
        if iterations == MAX_GA_ITERATIONS:
            raise Exception('The maximum-a-posterior gradient-ascent '+\
                'algorithm did not converge before reaching the maximum '+\
                'number iterations.')

    return theta_max, -ddlpo_i
Пример #8
0
def generate_data_figure1(data_path = '../Data/'):
    N, O, R, T = 15, 2, 200, 500
    mu = numpy.zeros(T)
    x = numpy.arange(1, 401)
    mu[100:] = 1. * (3. / (2. * numpy.pi * (x/400.*3.) ** 3)) ** .5 * \
               numpy.exp(-3. * ((x/400.*3.) - 1.) ** 2 / (2. * (x/400.*3.)))
    theta1 = synthesis.generate_thetas(N, O, T, mu1=-2.)
    theta2 = synthesis.generate_thetas(N, O, T, mu1=-2.)
    theta1[:, :N] += mu[:, numpy.newaxis]
    theta2[:, :N] += mu[:, numpy.newaxis]
    D = transforms.compute_D(N * 2, O)
    theta_all = numpy.empty([T, D])
    theta_all[:, :N] = theta1[:, :N]
    theta_all[:, N:2 * N] = theta2[:, :N]
    triu_idx = numpy.triu_indices(N, k=1)
    triu_idx_all = numpy.triu_indices(2 * N, k=1)
    for t in range(T):
        theta_ij = numpy.zeros([2 * N, 2 * N])
        theta_ij[triu_idx] = theta1[t, N:]
        theta_ij[triu_idx[0] + N, triu_idx[1] + N] = theta2[t, N:]
        theta_all[t, 2 * N:] = theta_ij[triu_idx_all]

    psi1 = numpy.empty([T, 3])
    psi2 = numpy.empty([T, 3])
    eta1 = numpy.empty(theta1.shape)
    eta2 = numpy.empty(theta2.shape)
    alpha = [.999,1.,1.001]
    transforms.initialise(N, O)
    for i in range(T):
        for j, a in enumerate(alpha):
            psi1[i, j] = transforms.compute_psi(a * theta1[i])
        p = transforms.compute_p(theta1[i])
        eta1[i] = transforms.compute_eta(p)
        for j, a in enumerate(alpha):
            psi2[i, j] = transforms.compute_psi(a * theta2[i])
        p = transforms.compute_p(theta2[i])
        eta2[i] = transforms.compute_eta(p)

    psi_all = psi1 + psi2
    S1 = -numpy.sum(eta1 * theta1, axis=1) + psi1[:, 1]
    S1 /= numpy.log(2)
    S2 = -numpy.sum(eta2 * theta2, axis=1) + psi2[:, 1]
    S2 /= numpy.log(2)
    S_all = S1 + S2

    C1 = (psi1[:, 0] - 2. * psi1[:, 1] + psi1[:, 2]) / .001 ** 2
    C1 /= numpy.log(2)
    C2 = (psi2[:, 0] - 2. * psi2[:, 1] + psi2[:, 2]) / .001 ** 2
    C2 /= numpy.log(2)

    C_all = C1 + C2

    spikes = synthesis.generate_spikes_gibbs_parallel(theta_all, 2 * N, O, R,
                                                      sample_steps=10,
                                                      num_proc=4)

    print 'Model and Data generated'

    emd = __init__.run(spikes, O, map_function='cg', param_est='pseudo',
                       param_est_eta='bethe_hybrid', lmbda1=100, lmbda2=200)

    f = h5py.File(data_path + 'figure1data.h5', 'w')
    g_data = f.create_group('data')
    g_data.create_dataset('theta_all', data=theta_all)
    g_data.create_dataset('psi_all', data=psi_all)
    g_data.create_dataset('S_all', data=S_all)
    g_data.create_dataset('C_all', data=C_all)
    g_data.create_dataset('spikes', data=spikes)
    g_data.create_dataset('theta1', data=theta1)
    g_data.create_dataset('theta2', data=theta2)
    g_data.create_dataset('psi1', data=psi1)
    g_data.create_dataset('S1', data=S1)
    g_data.create_dataset('C1', data=C1)
    g_data.create_dataset('psi2', data=psi2)
    g_data.create_dataset('S2', data=S2)
    g_data.create_dataset('C2', data=C2)
    g_fit = f.create_group('fit')
    g_fit.create_dataset('theta_s', data=emd.theta_s)
    g_fit.create_dataset('sigma_s', data=emd.sigma_s)
    g_fit.create_dataset('Q', data=emd.Q)
    f.close()

    print 'Fit and saved'

    f = h5py.File(data_path + 'figure1data.h5', 'r+')
    g_fit = f['fit']
    theta = g_fit['theta_s'].value
    sigma = g_fit['sigma_s'].value

    X = numpy.random.randn(theta.shape[0], theta.shape[1], 100)
    theta_sampled = \
        theta[:, :, numpy.newaxis] + X * numpy.sqrt(sigma)[:, :, numpy.newaxis]

    T = range(theta.shape[0])
    eta_sampled = numpy.empty([theta.shape[0], theta.shape[1], 100])
    psi_sampled = numpy.empty([theta.shape[0], 100, 3])

    func = partial(get_sampled_eta_psi, theta_sampled=theta_sampled, N=2*N)
    pool = multiprocessing.Pool(10)
    results = pool.map(func, T)

    for eta, psi, i in results:
        eta_sampled[i] = eta
        psi_sampled[i] = psi
    S_sampled = \
        -(numpy.sum(eta_sampled*theta_sampled, axis=1) - psi_sampled[:, :, 1])
    S_sampled /= numpy.log(2)
    C_sampled = \
        (psi_sampled[:, :, 0] - 2.*psi_sampled[:, :, 1] +
         psi_sampled[:, :, 2])/.001**2
    C_sampled /= numpy.log(2)
    g_sampled = f.create_group('sampled_results')
    g_sampled.create_dataset('theta_sampled', data=theta_sampled)
    g_sampled.create_dataset('eta_sampled', data=eta_sampled)
    g_sampled.create_dataset('psi_sampled', data=psi_sampled)
    g_sampled.create_dataset('S_sampled', data=S_sampled)
    g_sampled.create_dataset('C_sampled', data=C_sampled)
    f.close()

    print 'Done'
Пример #9
0
def plot_figure1(data_path='../Data/', plot_path='../Plots/'):

    N, O = 30, 2
    f = h5py.File(data_path + 'figure1data.h5', 'r')
    # Figure A
    fig = pyplot.figure(figsize=(30, 20))

    ax = fig.add_axes([0.07, 0.68, .4, .4])
    ax.imshow(-f['data']['spikes'][:, 0, :].T, cmap='gray', aspect=5,
              interpolation='nearest')
    ax.set_xticks([])
    ax.set_yticks([])
    ax = fig.add_axes([.06, 0.65, .4, .4])
    ax.imshow(-f['data']['spikes'][:, 1, :].T, cmap='gray', aspect=5,
              interpolation='nearest')
    ax.set_xticks([])
    ax.set_yticks([])
    ax = fig.add_axes([.05, 0.62, .4, .4])
    ax.imshow(-f['data']['spikes'][:, 2, :].T, cmap='gray', aspect=5,
              interpolation='nearest')
    ax.set_xticks([])
    ax.set_yticks([])
    ax.set_xlabel('Time [AU]', fontsize=26)
    ax.set_ylabel('Neuron ID', fontsize=26)

    ax = fig.add_axes([.05, 0.5, .4, .2])
    ax.set_frame_on(False)
    ax.plot(numpy.mean(numpy.mean(f['data']['spikes'][:, :, :], axis=1),
                       axis=1), linewidth=4, color='k')
    ymin, ymax = ax.get_yaxis().get_view_interval()
    xmin, xmax = ax.get_xaxis().get_view_interval()
    ax.add_artist(pyplot.Line2D((xmin, xmin), (ymin, ymax), color='black',
                                linewidth=2))
    ax.add_artist(pyplot.Line2D((xmin, xmax), (ymin, ymin), color='black',
                                linewidth=3))
    ax.yaxis.set_ticks_position('left')
    ax.xaxis.set_ticks_position('bottom')
    ax.set_yticks([.1, .2, .3])
    ax.set_xticks([50, 150, 300])
    ax.set_ylabel('Data $p_{\\mathrm{spike}}$', fontsize=26)
    ax.set_xlabel('Time [AU]', fontsize=26)
    ax.tick_params(axis='both', which='major', labelsize=20)

    theta = f['fit']['theta_s'].value
    sigma_s = f['fit']['sigma_s'].value
    bounds = numpy.empty([theta.shape[0], theta.shape[1] - N, 2])
    bounds[:, :, 0] = theta[:, N:] - 2.58 * numpy.sqrt(sigma_s[:, N:])
    bounds[:, :, 1] = theta[:, N:] + 2.58 * numpy.sqrt(sigma_s[:, N:])
    # Figure B (Networks)
    graph_ax = [fig.add_axes([.52, 0.78, .15, .2]),
                fig.add_axes([.67, 0.78, .15, .2]),
                fig.add_axes([.82, 0.78, .15, .2])]
    T = [50, 150, 300]
    for i, t in enumerate(T):
        idx = numpy.where(numpy.logical_or(bounds[t, :, 0] > 0, bounds[t, :, 1]
                                           < 0))[0]
        conn_idx_all = numpy.arange(0, N * (N - 1) / 2)
        conn_idx = conn_idx_all[idx]
        all_conns = itertools.combinations(range(N), 2)
        conns = numpy.array(list(all_conns))[conn_idx]
        G1 = nx.Graph()
        G1.add_nodes_from(range(N))
        # conns = itertools.combinations(range(30),2)
        G1.add_edges_from(conns)
        pos1 = nx.circular_layout(G1)
        net_nodes = \
            nx.draw_networkx_nodes(G1, pos1, ax=graph_ax[i],
                                   node_color=theta[t, :N],
                                   cmap=pyplot.get_cmap('hot'), vmin=-3,
                                   vmax=-1.)
        e1 = nx.draw_networkx_edges(G1, pos1, ax=graph_ax[i],
                                    edge_color=theta[t, conn_idx].tolist(),
                                    edge_cmap=pyplot.get_cmap('seismic'),
                                    edge_vmin=-.7, edge_vmax=.7, width=2)
        graph_ax[i].axis('off')
        x0, x1 = graph_ax[i].get_xlim()
        y0, y1 = graph_ax[i].get_ylim()
        graph_ax[i].set_aspect(abs(x1 - x0) / abs(y1 - y0))
        graph_ax[i].set_title('t=%d' % t, fontsize=24)
    cbar_ax = fig.add_axes([0.62, 0.79, 0.1, 0.01])
    cbar_ax.tick_params(axis='both', which='major', labelsize=20)
    cbar = fig.colorbar(net_nodes, cax=cbar_ax, orientation='horizontal')
    cbar.set_ticks([-3, -2, -1])
    cbar_ax.set_title('$\\theta_{i}$', fontsize=22)
    cbar_ax = fig.add_axes([0.77, 0.79, 0.1, 0.01])
    cbar = fig.colorbar(e1, cax=cbar_ax, orientation='horizontal')
    cbar.set_ticks([-.5, 0., .5])
    cbar_ax.set_title('$\\theta_{ij}$', fontsize=22)
    cbar_ax.tick_params(axis='both', which='major', labelsize=20)

    # Figure B (Thetas)
    theta = f['data']['theta_all'][:, [165, 170, 182]]
    theta_fit = f['fit']['theta_s'][:, [165, 170, 182]]
    sigma_fit = f['fit']['sigma_s'][:, [165, 170, 182]]
    ax1 = fig.add_axes([.55, 0.68, .4, .1])
    ax1.set_frame_on(False)
    ax1.fill_between(range(0, 500), theta_fit[:, 0] - 2.58 *
                     numpy.sqrt(sigma_fit[:, 0]), theta_fit[:, 0] + 2.58 *
                     numpy.sqrt(sigma_fit[:, 0]), color=[.4, .4, .4])
    ax1.plot(range(500), theta[:, 0], linewidth=4, color='k')
    ax1.set_yticks([-1, 0, 1])
    ax1.set_ylim([-1.1, 1.1])
    ymin, ymax = ax1.get_yaxis().get_view_interval()
    xmin, xmax = ax1.get_xaxis().get_view_interval()
    ax1.add_artist(pyplot.Line2D((xmin, xmin), (ymin, ymax), color='black',
                                 linewidth=2))
    ax1.set_xticks([])
    ax1.yaxis.set_ticks_position('left')
    ax1.xaxis.set_ticks_position('bottom')
    ax1.tick_params(axis='both', which='major', labelsize=20)
    ax1 = fig.add_axes([.55, 0.57, .4, .1])
    ax1.set_frame_on(False)
    ax1.fill_between(range(0, 500), theta_fit[:, 1] - 2.58 *
                     numpy.sqrt(sigma_fit[:, 1]),
                     theta_fit[:, 1] + 2.58 * numpy.sqrt(sigma_fit[:, 1]),
                     color=[.5, .5, .5])
    ax1.plot(range(500), theta[:, 1], linewidth=4, color='k')
    ax1.set_yticks([-1, 0, 1])
    ax1.set_ylim([-1.1, 1.5])
    ymin, ymax = ax1.get_yaxis().get_view_interval()
    xmin, xmax = ax1.get_xaxis().get_view_interval()
    ax1.add_artist(pyplot.Line2D((xmin, xmin), (ymin, ymax), color='black',
                                 linewidth=2))
    ax1.set_xticks([])
    ax1.yaxis.set_ticks_position('left')
    ax1.xaxis.set_ticks_position('bottom')
    ax1.set_ylabel('$\\theta_{ij}$', fontsize=26)
    ax1.tick_params(axis='both', which='major', labelsize=20)
    ax1 = fig.add_axes([.55, 0.46, .4, .1])
    ax1.set_frame_on(False)
    ax1.fill_between(range(0, 500),
                     theta_fit[:, 2] - 2.58 * numpy.sqrt(sigma_fit[:, 2]),
                     theta_fit[:, 2] + 2.58 * numpy.sqrt(sigma_fit[:, 2]),
                     color=[.6, .6, .6])
    ax1.plot(range(500), theta[:, 2], linewidth=4, color='k')
    ax1.set_ylim([-1.1, 1.1])
    ymin, ymax = ax1.get_yaxis().get_view_interval()
    xmin, xmax = ax1.get_xaxis().get_view_interval()
    ax1.add_artist(pyplot.Line2D((xmin, xmin), (ymin, ymax), color='black',
                                 linewidth=2))
    ax1.add_artist(pyplot.Line2D((xmin, xmax), (ymin, ymin), color='black',
                                 linewidth=3))
    ax1.set_xticks([50, 150, 300])
    ax1.yaxis.set_ticks_position('left')
    ax1.xaxis.set_ticks_position('bottom')
    ax1.set_xlabel('Time [AU]', fontsize=26)
    ax1.set_yticks([-1, 0, 1])
    ax1.tick_params(axis='both', which='major', labelsize=20)

    # Figure C
    psi_color = numpy.array([51, 153., 255]) / 256.
    eta_color = numpy.array([0, 204., 102]) / 256.
    S_color = numpy.array([255, 162, 0]) / 256.
    C_color = numpy.array([204, 60, 60]) / 256.
    psi_quantiles = mquantiles(f['sampled_results']['psi_sampled'][:, :, 1],
                               prob=[.01, .99], axis=1)
    psi_true = f['data']['psi_all'].value
    eta_quantiles = mquantiles(numpy.mean(
        f['sampled_results']['eta_sampled'][:, :N, :], axis=1), prob=[.01, .99],
                               axis=1)
    C_quantiles = mquantiles(f['sampled_results']['C_sampled'][:, :],
                             prob=[.01, .99], axis=1)
    C_true = f['data']['C_all']
    S_quantiles = mquantiles(f['sampled_results']['S_sampled'][:, :],
                             prob=[.01, .99], axis=1)
    S_true = f['data']['S_all']
    eta1 = numpy.empty(f['data']['theta1'].shape)
    eta2 = numpy.empty(f['data']['theta2'].shape)
    T = eta1.shape[0]
    N1, N2 = 15, 15
    transforms.initialise(N1, O)
    for i in range(T):
        p = transforms.compute_p(f['data']['theta1'][i])
        eta1[i] = transforms.compute_eta(p)
        p = transforms.compute_p(f['data']['theta2'][i])
        eta2[i] = transforms.compute_eta(p)

    ax1 = fig.add_axes([.08, 0.23, .4, .15])
    ax1.set_frame_on(False)
    ax1.fill_between(range(0, 500), eta_quantiles[:, 0], eta_quantiles[:, 1],
                     color=eta_color)
    eta_true = 1. / 2. * (numpy.mean(eta1[:, :N1], axis=1) +
                          numpy.mean(eta2[:, :N2], axis=1))
    ax1.fill_between(range(0, 500), eta_quantiles[:, 0], eta_quantiles[:, 1],
                     color=eta_color)
    ax1.plot(range(500), eta_true, linewidth=4, color=eta_color * .8)

    ax1.set_yticks([.1, .2, .3])
    ax1.set_ylim([.09, .35])
    ymin, ymax = ax1.get_yaxis().get_view_interval()
    xmin, xmax = ax1.get_xaxis().get_view_interval()
    ax1.add_artist(pyplot.Line2D((xmin, xmin), (ymin, ymax), color='black',
                                 linewidth=2))
    ax1.add_artist(pyplot.Line2D((xmin, xmax), (ymin, ymin), color='black',
                                 linewidth=3))
    ax1.set_xticks([50, 150, 300])
    ax1.yaxis.set_ticks_position('left')
    ax1.xaxis.set_ticks_position('bottom')
    ax1.set_ylabel('$p_{\\mathrm{spike}}$', fontsize=26)
    ax1.tick_params(axis='both', which='major', labelsize=20)

    ax1 = fig.add_axes([.08, 0.05, .4, .15])
    ax1.set_frame_on(False)
    ax1.fill_between(range(0, 500), numpy.exp(-psi_quantiles[:, 0]),
                     numpy.exp(-psi_quantiles[:, 1]), color=psi_color)
    ax1.plot(range(500), numpy.exp(-psi_true), linewidth=4, color=psi_color * .8)
    ax1.set_yticks([.0, .01, .02])
    ax1.set_ylim([.0, .025])
    ymin, ymax = ax1.get_yaxis().get_view_interval()
    xmin, xmax = ax1.get_xaxis().get_view_interval()
    ax1.add_artist(pyplot.Line2D((xmin, xmin), (ymin, ymax), color='black',
                                 linewidth=2))
    ax1.add_artist(pyplot.Line2D((xmin, xmax), (ymin, ymin), color='black',
                                 linewidth=3))
    ax1.set_xticks([50, 150, 300])
    ax1.yaxis.set_ticks_position('left')
    ax1.xaxis.set_ticks_position('bottom')
    ax1.set_ylabel('$p_{\\mathrm{silence}}$', fontsize=26)
    ax1.set_xlabel('Time [AU]', fontsize=26)
    ax1.tick_params(axis='both', which='major', labelsize=20)
    # Entropy
    ax2 = fig.add_axes([.52, 0.23, .4, .15])
    ax2.set_frame_on(False)

    ax2.fill_between(range(0, 500), S_quantiles[:, 0] / numpy.log2(numpy.exp(1)),
                     S_quantiles[:, 1] / numpy.log2(numpy.exp(1)), color=S_color)
    ax2.plot(range(500), S_true / numpy.log2(numpy.exp(1)), linewidth=4, color=S_color * .8)
    ax2.set_xticks([50, 150, 300])
    ax2.set_yticks([10, 14, 18])
    ymin, ymax = ax2.get_yaxis().get_view_interval()
    xmin, xmax = ax2.get_xaxis().get_view_interval()
    ax2.add_artist(pyplot.Line2D((xmin, xmin), (ymin, ymax), color='black',
                                 linewidth=2))
    ax2.add_artist(pyplot.Line2D((xmin, xmax), (ymin, ymin), color='black',
                                 linewidth=3))
    ax2.yaxis.set_ticks_position('left')
    ax2.xaxis.set_ticks_position('bottom')
    ax2.set_ylabel('$S$', fontsize=26)
    ax2.tick_params(axis='both', which='major', labelsize=20)
    # Heat capacity
    ax2 = fig.add_axes([.52, 0.05, .4, .15])
    ax2.set_frame_on(False)
    ax2.fill_between(range(0, 500),
                     C_quantiles[:, 0] / numpy.log2(numpy.exp(1)),
                     C_quantiles[:, 1] / numpy.log2(numpy.exp(1)),
                     color=C_color)
    ax2.plot(range(500), C_true / numpy.log2(numpy.exp(1)), linewidth=5,
             color=C_color * .8)
    ymin, ymax = ax2.get_yaxis().get_view_interval()
    xmin, xmax = ax2.get_xaxis().get_view_interval()
    ax2.add_artist(pyplot.Line2D((xmin, xmin), (ymin, ymax), color='black',
                                 linewidth=2))
    ax2.add_artist(pyplot.Line2D((xmin, xmax), (ymin, ymin), color='black',
                                 linewidth=3))
    ax2.set_xticks([50, 150, 300])
    ax2.set_yticks([5, 10])
    ax2.yaxis.set_ticks_position('left')
    ax2.xaxis.set_ticks_position('bottom')
    ax2.set_xlabel('Time [AU]', fontsize=26)
    ax2.set_ylabel('$C$', fontsize=26)
    ax2.tick_params(axis='both', which='major', labelsize=20)
    ax = fig.add_axes([0.03, 0.95, .05, .05], frameon=0)
    ax.set_yticks([])
    ax.set_xticks([])
    ax.text(.0, .0, 'A', fontsize=26, fontweight='bold')
    ax = fig.add_axes([0.52, 0.95, .05, .05], frameon=0)
    ax.set_yticks([])
    ax.set_xticks([])
    ax.text(.0, .0, 'B', fontsize=26, fontweight='bold')
    ax = fig.add_axes([0.05, 0.4, .05, .05], frameon=0)
    ax.set_yticks([])
    ax.set_xticks([])
    ax.text(.0, .0, 'C', fontsize=26, fontweight='bold')
    fig.savefig(plot_path+'fig1.eps')
    pyplot.show()
Пример #10
0
def line_search(theta_max, y, R, p, s, dlpo, theta_o, sigma_o_i):
    """ Searches the minimum on a line with quadratic approximation

    :param numpy.ndarray theta_max:
        Starting point on the line
    :param numpy.ndarray y:
        Empirical mean of the data (sufficient statistics)
    :param int R:
        Number of trials
    :param numpy.ndarray p:
        Probability for each pattern
    :param numpy.ndarray s:
        Direction that is searched in
    :param numpy.ndarray dlpo:
        Derivative of of th posterior at the current theta
    :param numpy.ndarray theta_o:
        One-step prediction of theta
    :param numpy.ndarray sigma_o_i:
        One-step prediction of the covariance matrix

    :returns
        Tuple containing the minimum on the line, the log posterior gradient,
        the current p and current eta vector

    This method approximates at each point the log posterior quadratically
    and searches iteratively for the minimum.

    @author: Christian Donner
    """
    y_s = numpy.dot(y, s)
    # Project theta on p_map
    theta_p = transforms.p_map.dot(theta_max)
    # Project p-map on search direction
    p_map_s = transforms.p_map.dot(s)
    # Projected eta on search direction
    eta_s = numpy.dot(p_map_s, p)
    # Project inverse one-step covariance matrix on search direction
    sigma_o_i_s = numpy.dot(sigma_o_i, s)
    # Project gradient of log posterior on search direction
    dlpo_s = numpy.dot(dlpo, s)
    # Get Metric of fisher info along s direction
    s_G_s = R*(numpy.dot(p_map_s, p*p_map_s) - eta_s**2) + \
            numpy.dot(s, sigma_o_i_s)
    # Initialize iteration variable and alpha
    dalpha = numpy.inf
    alpha = 0
    snorm = numpy.sum(numpy.absolute(s))
    while dalpha*snorm > 1e-2:
        # Compute alpha due to gradient
        alpha_new = alpha + dlpo_s/s_G_s
        # If new alpha is negative take the half of old alpha
        if alpha_new < 0:
            alpha /= 2.
            dalpha = alpha
        # Else take new
        else:
            dalpha = numpy.absolute(alpha - alpha_new)
            alpha = alpha_new
        # Update theta
        theta_tmp = theta_max + alpha*s
        # Compute new psi
        psi_new = numpy.log(numpy.sum(numpy.exp(theta_p + alpha*p_map_s)))
        # psi = numpy.log(p*numpy.exp(alpha*p_map_s))
        p = numpy.exp(theta_p + alpha*p_map_s - psi_new)
        # Project eta on search direction
        eta_s = numpy.dot(p_map_s, p)
        # Project fisher information on search direction
        s_G_s = R*(numpy.dot(p_map_s, p*p_map_s) - eta_s**2) + \
                numpy.dot(s, sigma_o_i_s)
        # Compute log posterior gradient projected on s
        dllk_s = R*(y_s - eta_s)
        dlpr_s = -numpy.dot(sigma_o_i_s, theta_tmp - theta_o)
        dlpo_s = dllk_s + dlpr_s
    # return optimized theta and current gradient of log posterior

    eta = transforms.compute_eta(p)
    dllk = R*(y - eta)
    dlpr = -numpy.dot(sigma_o_i, theta_tmp - theta_o)
    dlpo = dllk + dlpr
    return theta_tmp, dlpo, p, eta
Пример #11
0
def bfgs(y_t, X_t, R, theta_0, theta_o, sigma_o, sigma_o_i, *args):
    """ Fits due to `Broyden-Fletcher-Goldfarb-Shanno algorithm
    <https://en.wikipedia.org/wiki/Broyden%E2%80%93Fletcher%E2%80%93Goldfarb%E2%
    80%93Shanno_algorithm>`_.

    :param container.EMData emd:
        All data pertaining to the EM algorithm.
    :param int t:
        Timestep for which to compute the maximum posterior probability.

    :returns:
        Tuple containing the mean and covariance of the posterior probability
        density, each as a numpy.ndarray.

    @author: Christian Donner
    """

    # # Initialize theta with previous smoothed theta
    theta_max = theta_0
    # Get p and eta values for current theta
    p = transforms.compute_p(theta_max)
    eta = transforms.compute_eta(p)
    # Initialize the estimate of the inverse fisher info
    ddlpo_i_e = numpy.identity(theta_max.shape[0])
    # Compute derivative of posterior
    dllk = R*(y_t - eta)
    dlpr = -numpy.dot(sigma_o_i, theta_max - theta_o)
    dlpo = dllk + dlpr
    # Initialize stopping criterion variables
    max_dlpo = 1.
    iterations = 0

    # Iterate until convergence or failure
    while max_dlpo > GA_CONVERGENCE:
        # Compute direction for line search
        s_dir = numpy.dot(dlpo, ddlpo_i_e)
        # Set theta to old theta
        theta_prev = numpy.copy(theta_max)
        # Set current log posterior gradient to previous
        dlpo_prev = dlpo
        # Perform line search
        theta_max, dlpo, p, eta = line_search(theta_max, y_t, R, p, s_dir, dlpo,
                                              theta_o, sigma_o_i)
        # Get the difference between old and new theta
        d_theta = theta_max - theta_prev
        # Difference in log posterior gradients
        dlpo_diff = dlpo_prev - dlpo
        # Project gradient change on theta change
        dlpo_diff_dth = numpy.inner(dlpo_diff, d_theta)
        # Compute estimate of covariance matrix with Sherman-Morrison Formula
        a = (dlpo_diff_dth + \
             numpy.dot(dlpo_diff, numpy.dot(ddlpo_i_e, dlpo_diff.T)))*\
            numpy.outer(d_theta, d_theta)
        b = numpy.inner(d_theta, dlpo_diff)**2
        c = numpy.dot(ddlpo_i_e, numpy.outer(dlpo_diff, d_theta)) + \
            numpy.outer(d_theta, numpy.inner(dlpo_diff, ddlpo_i_e))
        d = dlpo_diff_dth
        ddlpo_i_e += (a/b - c/d)
        # Get maximal entry of log posterior grad divided by number of trials
        max_dlpo = numpy.amax(numpy.absolute(dlpo)) / R
        # Count iterations
        iterations += 1
        if iterations == MAX_GA_ITERATIONS:
            raise Exception('The maximum-a-posterior bfgs-gradient '+\
                'algorithm did not converge before reaching the maximum '+\
                'number iterations.')

    # Compute final covariance matrix
    ddllk = -R*transforms.compute_fisher_info(p, eta)
    ddlpo = ddllk - sigma_o_i
    ddlpo_i = numpy.linalg.inv(ddlpo)

    return theta_max, -ddlpo_i
Пример #12
0
def conjugate_gradient(y_t, X_t, R, theta_0, theta_o, sigma_o, sigma_o_i,
                       *args):
    """ Fits with `Nonlinear Conjugate Gradient Method
    <https://en.wikipedia.org/wiki/Nonlinear_conjugate_gradient_method>`_.

    :param container.EMData emd:
        All data pertaining to the EM algorithm.
    :param int t:
        Timestep for which to compute the maximum posterior probability.

    :returns:
        Tuple containing the mean and covariance of the posterior probability
        density, each as a numpy.ndarray.

    @author: Christian Donner
    """

    # Initialize theta with previous smoothed theta
    theta_max = theta_0
    # Get p and eta values for current theta
    p = transforms.compute_p(theta_max)
    eta = transforms.compute_eta(p)
    # Compute derivative of posterior
    dllk = R * (y_t - eta)
    dlpr = -numpy.dot(sigma_o_i, theta_max - theta_o)
    dlpo = dllk + dlpr
    # Initialize stopping criterion variables
    max_dlpo = 1.
    iterations = 0
    # Get theta gradient
    d_th = dlpo
    # Set initial search direction
    s = dlpo
    # Compute line search
    theta_max, dlpo, p, eta = line_search(theta_max, y_t, R, p, s, dlpo,
                                          theta_o, sigma_o_i)

    # Iterate until convergence or failure
    while max_dlpo > GA_CONVERGENCE:

        # Set current theta gradient to previous
        d_th_prev = d_th
        # The new theta gradient
        d_th = dlpo
        # Calculate beta
        beta = compute_beta(d_th, d_th_prev)
        # New search direction
        s = d_th + beta * s
        # Line search
        theta_max, dlpo, p, eta = line_search(theta_max, y_t, R, p, s, dlpo,
                                              theta_o, sigma_o_i)
        # Get maximal entry of log posterior grad divided by number of trials
        max_dlpo = numpy.amax(numpy.absolute(dlpo)) / R
        # Count iterations
        iterations += 1
        if iterations == MAX_GA_ITERATIONS:
            raise Exception('The maximum-a-posterior conjugate-gradient '+\
                'algorithm did not converge before reaching the maximum '+\
                'number iterations.')

    # Compute final covariance matrix
    ddllk = -R * transforms.compute_fisher_info(p, eta)
    ddlpo = ddllk - sigma_o_i
    ddlpo_i = numpy.linalg.inv(ddlpo)

    return theta_max, -ddlpo_i
Пример #13
0
def newton_raphson(emd, t):
    """
    Computes the MAP estimate of the natural parameters at some timestep, given
    the observed spike patterns at that timestep and the one-step-prediction
    mean and covariance for the same timestep.
    :param container.EMData emd:
        All data pertaining to the EM algorithm.
    :param int t:
        Timestep for which to compute the maximum posterior probability.
    :returns:
        Tuple containing the mean and covariance of the posterior probability
        density, each as a numpy.ndarray.
    """
    # Extract one-step predictions for time t
    theta_o = emd.theta_o[t, :]
    sigma_o = emd.sigma_o[t, :, :]
    R = emd.R
    N = emd.N
    exact = emd.exact
    # Extract the feature vector for time t
    f_t = emd.f[t, :]
    # Extract the fitted parameters of the original Ising models
    J = emd.J
    # Initialise theta_max to the smooth theta value of the previous iteration
    theta_max = emd.theta_s[t, :]
    # Use non-normalised posterior prob. as loop guard
    lpp = -numpy.inf
    lpc = probability.log_likelihood(f_t, theta_max, J, R, N, exact) +\
          probability.log_multivariate_normal(theta_max, theta_o, sigma_o)
    iterations = 0
    # Iterate the gradient ascent algorithm until convergence or failure
    while lpc - lpp > GA_CONVERGENCE:
        # Compute mixed theta
        theta_mixed = transforms.compute_mixed_theta(theta_max, J)
        # Compute the eta of the current theta values
        if exact:
            p = transforms.compute_p(theta_mixed)
            eta_tilde = transforms.compute_eta(p)
        else:
            eta_tilde = bethe_approximation.compute_eta_hybrid(theta_mixed, N)
        eta = transforms.compute_eta_LD(eta_tilde, J)
        # Compute the inverse of one-step covariance
        sigma_o_i = numpy.linalg.inv(sigma_o)
        # Compute the first derivative of the posterior prob. w.r.t. theta_max
        dllk = R * (f_t - eta)
        dlpr = -numpy.dot(sigma_o_i, theta_max - theta_o)
        dlpo = dllk + dlpr
        # Compute the second derivative of the posterior prob. w.r.t. theta_max
        if exact:
            fisher_tilde = transforms.compute_fisher_info(p, eta_tilde)
        else:
            fisher_tilde = numpy.diag(
                bethe_approximation.construct_fisher_diag(eta_tilde, N))
        fisher = transforms.compute_fisher_info_LD(fisher_tilde, J)
        ddlpo = -R * fisher - sigma_o_i
        # Dot the results to climb the gradient, and accumulate the result
        ddlpo_i = numpy.linalg.inv(ddlpo)
        theta_max -= numpy.dot(ddlpo_i, dlpo)

        # Update previous and current posterior prob.
        lpp = lpc
        lpc = probability.log_likelihood(f_t, theta_max, J, R, N, exact)\
              + probability.log_multivariate_normal(theta_max, theta_o, sigma_o)
        # Count iterations
        iterations += 1
        # Check for check for overrun
        if iterations == MAX_GA_ITERATIONS:
            raise Exception('The maximum-a-posterior gradient-ascent '+\
                'algorithm did not converge before reaching the maximum '+\
                'number iterations.')

    return theta_max, -ddlpo_i
Пример #14
0
psi = numpy.zeros((12, T))
epsilon = 1e-3
C = numpy.zeros((12, T))
p_silence = numpy.zeros((12, T))
p_spike = numpy.zeros((12, T))
S2 = numpy.zeros((12, T))
theta_ind = numpy.zeros((12, T, N))
eta_ind = numpy.zeros((12, T, N))
psi_ind = numpy.zeros((12, T))
S1 = numpy.zeros((12, T))
for k in range(12):
    if emd.marg_llk == probability.log_marginal:  # If exact:
        for t in range(T):
            p = transforms.compute_p(theta_m[k, t, :])
            psi[k, t] = transforms.compute_psi(theta_m[k, t, :])
            eta[k, t, :] = transforms.compute_eta(p)
            tmp1 = transforms.compute_psi(theta_m[k, t, :] * (1 + epsilon))
            tmp2 = transforms.compute_psi(theta_m[k, t, :] * (1 - epsilon))
            c = tmp1 - 2 * psi[k, t] + tmp2
            d = epsilon**2
            C[k, t] = c / d
    else:  # If approximations
        for t in range(T):
            eta[k, t, :], psi[k, t] = bethe_approximation.compute_eta_hybrid(
                theta_m[k, t, :], N, return_psi=True)
            tmp1 = bethe_approximation.compute_eta_hybrid(theta_m[k, t, :] *
                                                          (1 + epsilon),
                                                          N,
                                                          return_psi=True)[1]
            tmp2 = bethe_approximation.compute_eta_hybrid(theta_m[k, t, :] *
                                                          (1 - epsilon),
Пример #15
0
def line_search(theta_max, y, R, p, s, dlpo, theta_o, sigma_o_i):
    """ Searches the minimum on a line with quadratic approximation

    :param numpy.ndarray theta_max:
        Starting point on the line
    :param numpy.ndarray y:
        Empirical mean of the data (sufficient statistics)
    :param int R:
        Number of trials
    :param numpy.ndarray p:
        Probability for each pattern
    :param numpy.ndarray s:
        Direction that is searched in
    :param numpy.ndarray dlpo:
        Derivative of of th posterior at the current theta
    :param numpy.ndarray theta_o:
        One-step prediction of theta
    :param numpy.ndarray sigma_o_i:
        One-step prediction of the covariance matrix

    :returns
        Tuple containing the minimum on the line, the log posterior gradient,
        the current p and current eta vector

    This method approximates at each point the log posterior quadratically
    and searches iteratively for the minimum.

    @author: Christian Donner
    """
    y_s = numpy.dot(y, s)
    # Project theta on p_map
    theta_p = transforms.p_map.dot(theta_max)
    # Project p-map on search direction
    p_map_s = transforms.p_map.dot(s)
    # Projected eta on search direction
    eta_s = numpy.dot(p_map_s, p)
    # Project inverse one-step covariance matrix on search direction
    sigma_o_i_s = numpy.dot(sigma_o_i, s)
    # Project gradient of log posterior on search direction
    dlpo_s = numpy.dot(dlpo, s)
    # Get Metric of fisher info along s direction
    s_G_s = R*(numpy.dot(p_map_s, p*p_map_s) - eta_s**2) + \
            numpy.dot(s, sigma_o_i_s)
    # Initialize iteration variable and alpha
    dalpha = numpy.inf
    alpha = 0
    snorm = numpy.sum(numpy.absolute(s))
    while dalpha * snorm > 1e-2:
        # Compute alpha due to gradient
        alpha_new = alpha + dlpo_s / s_G_s
        # If new alpha is negative take the half of old alpha
        if alpha_new < 0:
            alpha /= 2.
            dalpha = alpha
        # Else take new
        else:
            dalpha = numpy.absolute(alpha - alpha_new)
            alpha = alpha_new
        # Update theta
        theta_tmp = theta_max + alpha * s
        # Compute new psi
        psi_new = numpy.log(numpy.sum(numpy.exp(theta_p + alpha * p_map_s)))
        # psi = numpy.log(p*numpy.exp(alpha*p_map_s))
        p = numpy.exp(theta_p + alpha * p_map_s - psi_new)
        # Project eta on search direction
        eta_s = numpy.dot(p_map_s, p)
        # Project fisher information on search direction
        s_G_s = R*(numpy.dot(p_map_s, p*p_map_s) - eta_s**2) + \
                numpy.dot(s, sigma_o_i_s)
        # Compute log posterior gradient projected on s
        dllk_s = R * (y_s - eta_s)
        dlpr_s = -numpy.dot(sigma_o_i_s, theta_tmp - theta_o)
        dlpo_s = dllk_s + dlpr_s
    # return optimized theta and current gradient of log posterior

    eta = transforms.compute_eta(p)
    dllk = R * (y - eta)
    dlpr = -numpy.dot(sigma_o_i, theta_tmp - theta_o)
    dlpo = dllk + dlpr
    return theta_tmp, dlpo, p, eta
Пример #16
0
def bfgs(y_t, X_t, R, theta_0, theta_o, sigma_o, sigma_o_i, *args):
    """ Fits due to `Broyden-Fletcher-Goldfarb-Shanno algorithm
    <https://en.wikipedia.org/wiki/Broyden%E2%80%93Fletcher%E2%80%93Goldfarb%E2%
    80%93Shanno_algorithm>`_.

    :param container.EMData emd:
        All data pertaining to the EM algorithm.
    :param int t:
        Timestep for which to compute the maximum posterior probability.

    :returns:
        Tuple containing the mean and covariance of the posterior probability
        density, each as a numpy.ndarray.

    @author: Christian Donner
    """

    # # Initialize theta with previous smoothed theta
    theta_max = theta_0
    # Get p and eta values for current theta
    p = transforms.compute_p(theta_max)
    eta = transforms.compute_eta(p)
    # Initialize the estimate of the inverse fisher info
    ddlpo_i_e = numpy.identity(theta_max.shape[0])
    # Compute derivative of posterior
    dllk = R * (y_t - eta)
    dlpr = -numpy.dot(sigma_o_i, theta_max - theta_o)
    dlpo = dllk + dlpr
    # Initialize stopping criterion variables
    max_dlpo = 1.
    iterations = 0

    # Iterate until convergence or failure
    while max_dlpo > GA_CONVERGENCE:
        # Compute direction for line search
        s_dir = numpy.dot(dlpo, ddlpo_i_e)
        # Set theta to old theta
        theta_prev = numpy.copy(theta_max)
        # Set current log posterior gradient to previous
        dlpo_prev = dlpo
        # Perform line search
        theta_max, dlpo, p, eta = line_search(theta_max, y_t, R, p, s_dir,
                                              dlpo, theta_o, sigma_o_i)
        # Get the difference between old and new theta
        d_theta = theta_max - theta_prev
        # Difference in log posterior gradients
        dlpo_diff = dlpo_prev - dlpo
        # Project gradient change on theta change
        dlpo_diff_dth = numpy.inner(dlpo_diff, d_theta)
        # Compute estimate of covariance matrix with Sherman-Morrison Formula
        a = (dlpo_diff_dth + \
             numpy.dot(dlpo_diff, numpy.dot(ddlpo_i_e, dlpo_diff.T)))*\
            numpy.outer(d_theta, d_theta)
        b = numpy.inner(d_theta, dlpo_diff)**2
        c = numpy.dot(ddlpo_i_e, numpy.outer(dlpo_diff, d_theta)) + \
            numpy.outer(d_theta, numpy.inner(dlpo_diff, ddlpo_i_e))
        d = dlpo_diff_dth
        ddlpo_i_e += (a / b - c / d)
        # Get maximal entry of log posterior grad divided by number of trials
        max_dlpo = numpy.amax(numpy.absolute(dlpo)) / R
        # Count iterations
        iterations += 1
        if iterations == MAX_GA_ITERATIONS:
            raise Exception('The maximum-a-posterior bfgs-gradient '+\
                'algorithm did not converge before reaching the maximum '+\
                'number iterations.')

    # Compute final covariance matrix
    ddllk = -R * transforms.compute_fisher_info(p, eta)
    ddlpo = ddllk - sigma_o_i
    ddlpo_i = numpy.linalg.inv(ddlpo)

    return theta_max, -ddlpo_i
Пример #17
0
def conjugate_gradient(y_t, X_t, R, theta_0, theta_o, sigma_o, sigma_o_i, *args):
    """ Fits with `Nonlinear Conjugate Gradient Method
    <https://en.wikipedia.org/wiki/Nonlinear_conjugate_gradient_method>`_.

    :param container.EMData emd:
        All data pertaining to the EM algorithm.
    :param int t:
        Timestep for which to compute the maximum posterior probability.

    :returns:
        Tuple containing the mean and covariance of the posterior probability
        density, each as a numpy.ndarray.

    @author: Christian Donner
    """

    # Initialize theta with previous smoothed theta
    theta_max = theta_0
    # Get p and eta values for current theta
    p = transforms.compute_p(theta_max)
    eta = transforms.compute_eta(p)
    # Compute derivative of posterior
    dllk = R*(y_t - eta)
    dlpr = -numpy.dot(sigma_o_i, theta_max - theta_o)
    dlpo = dllk + dlpr
    # Initialize stopping criterion variables
    max_dlpo = 1.
    iterations = 0
    # Get theta gradient
    d_th = dlpo
    # Set initial search direction
    s = dlpo
    # Compute line search
    theta_max, dlpo, p, eta = line_search(theta_max, y_t, R, p, s, dlpo,
                                          theta_o, sigma_o_i)

    # Iterate until convergence or failure
    while max_dlpo > GA_CONVERGENCE:

        # Set current theta gradient to previous
        d_th_prev = d_th
        # The new theta gradient
        d_th = dlpo
        # Calculate beta
        beta = compute_beta(d_th, d_th_prev)
        # New search direction
        s = d_th + beta * s
        # Line search
        theta_max, dlpo, p, eta = line_search(theta_max, y_t, R, p, s, dlpo,
                                              theta_o, sigma_o_i)
        # Get maximal entry of log posterior grad divided by number of trials
        max_dlpo = numpy.amax(numpy.absolute(dlpo)) / R
        # Count iterations
        iterations += 1
        if iterations == MAX_GA_ITERATIONS:
            raise Exception('The maximum-a-posterior conjugate-gradient '+\
                'algorithm did not converge before reaching the maximum '+\
                'number iterations.')

    # Compute final covariance matrix
    ddllk = - R*transforms.compute_fisher_info(p, eta)
    ddlpo = ddllk - sigma_o_i
    ddlpo_i = numpy.linalg.inv(ddlpo)

    return theta_max, -ddlpo_i
Пример #18
0
def generate_data_figure2(data_path='../Data/', max_network_size=60):
    N, O, R, T = 10, 2, 200, 500
    num_of_networks = max_network_size/N
    mu = numpy.zeros(T)
    x = numpy.arange(1, 401)
    mu[100:] = 1. * (3. / (2. * numpy.pi * (x / 400. * 3.) ** 3)) ** .5 * \
               numpy.exp(-3. * ((x / 400. * 3.) - 1.) ** 2 /
                         (2. * (x / 400. * 3.)))

    D = transforms.compute_D(N, O)
    thetas = numpy.empty([num_of_networks, T, D])
    etas = numpy.empty([num_of_networks, T, D])
    psi = numpy.empty([num_of_networks, T])
    S = numpy.empty([num_of_networks, T])
    C = numpy.empty([num_of_networks, T])
    transforms.initialise(N, O)
    for i in range(num_of_networks):
        thetas[i] = synthesis.generate_thetas(N, O, T, mu1=-2.)
        thetas[i, :, :N] += mu[:, numpy.newaxis]
        for t in range(T):
            p = transforms.compute_p(thetas[i, t])
            etas[i, t] = transforms.compute_eta(p)
            psi[i, t] = transforms.compute_psi(thetas[i, t])
            psi1 = transforms.compute_psi(.999 * thetas[i, t])
            psi2 = transforms.compute_psi(1.001 * thetas[i, t])
            C[i, t] = (psi1 - 2. * psi[i, t] + psi2) / .001 ** 2
            S[i, t] = -(numpy.sum(etas[i, t] * thetas[i, t]) - psi[i, t])
    C /= numpy.log(2)
    S /= numpy.log(2)
    f = h5py.File(data_path + 'figure2data.h5', 'w')
    g1 = f.create_group('data')
    g1.create_dataset('thetas', data=thetas)
    g1.create_dataset('etas', data=etas)
    g1.create_dataset('psi', data=psi)
    g1.create_dataset('S', data=S)
    g1.create_dataset('C', data=C)
    g2 = f.create_group('error')
    g2.create_dataset('MISE_thetas', shape=[num_of_networks])
    g2.create_dataset('MISE_population_rate', shape=[num_of_networks])
    g2.create_dataset('MISE_psi', shape=[num_of_networks])
    g2.create_dataset('MISE_S', shape=[num_of_networks])
    g2.create_dataset('MISE_C', shape=[num_of_networks])
    g2.create_dataset('population_rate', shape=[num_of_networks, T])
    g2.create_dataset('psi', shape=[num_of_networks, T])
    g2.create_dataset('S', shape=[num_of_networks, T])
    g2.create_dataset('C', shape=[num_of_networks, T])
    f.close()
    for i in range(num_of_networks):
        print 'N=%d' % ((i + 1) * N)
        D = transforms.compute_D((i + 1) * N, O)
        theta_all = numpy.empty([T, D])
        triu_idx = numpy.triu_indices(N, k=1)
        triu_idx_all = numpy.triu_indices((i + 1) * N, k=1)
        for j in range(i + 1):
            theta_all[:, N * j:(j + 1) * N] = thetas[j, :, :N]
            for t in range(T):
                theta_ij = numpy.zeros([(i + 1) * N, (i + 1) * N])
                for j in range(i + 1):
                    theta_ij[triu_idx[0] + j * N, triu_idx[1] + j * N] = \
                        thetas[j, t, N:]

            theta_all[t, (i + 1) * N:] = theta_ij[triu_idx_all]

        spikes = synthesis.generate_spikes_gibbs_parallel(theta_all
                                                          , (i + 1) * N, O, R,
                                                          sample_steps=10,
                                                          num_proc=4)
        emd = __init__.run(spikes, O, map_function='cg', param_est='pseudo',
                           param_est_eta='bethe_hybrid', lmbda1=100,
                           lmbda2=200)

        eta_est = numpy.empty(emd.theta_s.shape)
        psi_est = numpy.empty(T)
        S_est = numpy.empty(T)
        C_est = numpy.empty(T)
        for t in range(T):
            eta_est[t], psi_est[t] = bethe_approximation.compute_eta_hybrid(
                emd.theta_s[t], (i + 1) * N, return_psi=1)
            psi1 = bethe_approximation.compute_eta_hybrid(
                .999 * emd.theta_s[t], (i + 1) * N, return_psi=1)[1]
            psi2 = bethe_approximation.compute_eta_hybrid(
                1.001 * emd.theta_s[t], (i + 1) * N, return_psi=1)[1]
            S_est[t] = -(numpy.sum(eta_est[t] * emd.theta_s[t]) - psi_est[t])
            C_est[t] = (psi1 - 2. * psi_est[t] + psi2) / .001 ** 2
        S_est /= numpy.log(2)
        C_est /= numpy.log(2)
        population_rate = numpy.mean(numpy.mean(etas[:i + 1, :, :N], axis=0),
                                     axis=1)
        population_rate_est = numpy.mean(eta_est[:, :(i + 1) * N], axis=1)
        psi_true = numpy.sum(psi[:(i + 1), :], axis=0)
        S_true = numpy.sum(S[:(i + 1), :], axis=0)
        C_true = numpy.sum(C[:(i + 1), :], axis=0)

        f = h5py.File(data_path + 'figure2data.h5', 'r+')
        f['error']['MISE_thetas'][i] = numpy.mean(
            (theta_all - emd.theta_s) ** 2)
        f['error']['MISE_population_rate'][i] = numpy.mean(
            (population_rate - population_rate_est) ** 2)
        f['error']['MISE_psi'][i] = numpy.mean((psi_est - psi_true) ** 2)
        f['error']['MISE_S'][i] = numpy.mean((S_est - S_true) ** 2)
        f['error']['MISE_C'][i] = numpy.mean((C_est - C_true) ** 2)
        f['error']['population_rate'][i] = population_rate_est
        f['error']['psi'][i] = psi_est
        f['error']['S'][i] = S_est
        f['error']['C'][i] = C_est
        f.close()

    f = h5py.File(data_path + 'figure2data.h5', 'r+')
    thetas = f['data']['thetas'].value
    etas = f['data']['etas'].value
    psi = f['data']['psi'].value
    S = f['data']['S'].value
    C = f['data']['C'].value

    g2 = f.create_group('error500')
    g2.create_dataset('population_rate', shape=[num_of_networks, T])
    g2.create_dataset('psi', shape=[num_of_networks, T])
    g2.create_dataset('S', shape=[num_of_networks, T])
    g2.create_dataset('C', shape=[num_of_networks, T])
    g2.create_dataset('MISE_thetas', shape=[num_of_networks])
    g2.create_dataset('MISE_population_rate', shape=[num_of_networks])
    g2.create_dataset('MISE_psi', shape=[num_of_networks])
    g2.create_dataset('MISE_S', shape=[num_of_networks])
    g2.create_dataset('MISE_C', shape=[num_of_networks])
    f.close()

    R = 500

    for i in range(num_of_networks):
        print 'N=%d' % ((i + 1) * N)
        D = transforms.compute_D((i + 1) * N, O)
        theta_all = numpy.empty([T, D])
        triu_idx = numpy.triu_indices(N, k=1)
        triu_idx_all = numpy.triu_indices((i + 1) * N, k=1)

        for j in range(i + 1):
            theta_all[:, N * j:(j + 1) * N] = thetas[j, :, :N]

        for t in range(T):
            theta_ij = numpy.zeros([(i + 1) * N, (i + 1) * N])
            for j in range(i + 1):
                theta_ij[triu_idx[0] + j * N, triu_idx[1] + j * N] = \
                    thetas[j, t, N:]

            theta_all[t, (i + 1) * N:] = theta_ij[triu_idx_all]

        spikes = synthesis.generate_spikes_gibbs_parallel(theta_all,
                                                          (i + 1) * N, O, R,
                                                          sample_steps=10,
                                                          num_proc=4)
        emd = __init__.run(spikes, O, map_function='cg', param_est='pseudo',
                           param_est_eta='bethe_hybrid', lmbda1=100,
                           lmbda2=200)

        eta_est = numpy.empty(emd.theta_s.shape)
        psi_est = numpy.empty(T)
        S_est = numpy.empty(T)
        C_est = numpy.empty(T)

        for t in range(T):
            eta_est[t], psi_est[t] = \
                bethe_approximation.compute_eta_hybrid(emd.theta_s[t],
                                                       (i + 1) * N,
                                                       return_psi=1)
            psi1 = bethe_approximation.compute_eta_hybrid(.999 * emd.theta_s[t],
                                                          (i + 1) * N,
                                                          return_psi=1)[1]
            psi2 = bethe_approximation.compute_eta_hybrid(
                1.001 * emd.theta_s[t], (i + 1) * N, return_psi=1)[1]
            S_est[t] = -(numpy.sum(eta_est[t] * emd.theta_s[t]) - psi_est[t])
            C_est[t] = (psi1 - 2. * psi_est[t] + psi2) / .001 ** 2
        S_est /= numpy.log(2)
        C_est /= numpy.log(2)
        population_rate = numpy.mean(numpy.mean(etas[:i + 1, :, :N], axis=0),
                                     axis=1)
        population_rate_est = numpy.mean(eta_est[:, :(i + 1) * N], axis=1)
        psi_true = numpy.sum(psi[:(i + 1), :], axis=0)
        S_true = numpy.sum(S[:(i + 1), :], axis=0)
        C_true = numpy.sum(C[:(i + 1), :], axis=0)

        f = h5py.File(data_path + 'figure2data.h5', 'r+')
        f['error500']['MISE_thetas'][i] = numpy.mean(
            (theta_all - emd.theta_s) ** 2)
        f['error500']['MISE_population_rate'][i] = numpy.mean(
            (population_rate - population_rate_est) ** 2)
        f['error500']['MISE_psi'][i] = numpy.mean((psi_est - psi_true) ** 2)
        f['error500']['MISE_S'][i] = numpy.mean((S_est - S_true) ** 2)
        f['error500']['MISE_C'][i] = numpy.mean((C_est - C_true) ** 2)
        f['error500']['population_rate'][i] = population_rate_est
        f['error500']['psi'][i] = psi_est
        f['error500']['S'][i] = S_est
        f['error500']['C'][i] = C_est
        f.close()