Example #1
0
    def update(self, model, cache=None):
        """
        TODO: Handle truncated Gaussians noise for channel params
        """
        # Keep sufficient stats for a Gaussian noise model
        N = 0
        beta_V_hat = 0
        # beta_ch_hat = 0

        # Get the latent voltages
        for ds in model.data_sequences:
            latent = as_matrix(ds.latent)
            # The transition model is a noisy Hodgkin Huxley proposal
            prop = TruncatedHodgkinHuxleyProposal(
                model.population, ds.t, ds.input,
                as_matrix(np.zeros(1, dtype=model.population.latent_dtype)))
            dt = ds.t[1:] - ds.t[:-1]
            # import pdb; pdb.set_trace()
            pred = np.zeros((latent.shape[0], ds.T - 1))
            for t in np.arange(ds.T - 1):
                pt, _, _ = prop.sample_next(t, latent[:, t, np.newaxis], t + 1)
                pred[:, t] = pt.ravel()

            # pred2,_ = prop.sample_next(np.arange(ds.T-1),
            #                           latent[:,:-1],
            #                           np.arange(1,ds.T))

            # if not np.allclose(pred, pred2):
            #     import pdb; pdb.set_trace()
            for neuron in model.population.neurons:
                for compartment in neuron.compartments:
                    V = get_item_at_path(
                        as_sarray(latent, model.population.latent_dtype),
                        compartment.path)['V']
                    Vpred = get_item_at_path(
                        as_sarray(pred, model.population.latent_dtype),
                        compartment.path)['V']
                    dV = (Vpred - V[1:]) / dt

                    # Update sufficient stats
                    N += len(dV)
                    beta_V_hat += (dV**2).sum()

        # Sample a new beta_V
        sig2_V = 1.0 / np.random.gamma(
            hypers['a_sig_V'].value + N / 2., 1.0 /
            (hypers['b_sig_V'].value + beta_V_hat / 2.))

        hypers['sig_V'].value = np.sqrt(sig2_V)
Example #2
0
    def logp(self, X, Z):
        # View as the model's dtypes
        obs = as_sarray(X, self.model.observation.observed_dtype)
        latent = as_sarray(Z, self.model.population.latent_dtype)
        logp = self.model.observation.logp(latent, obs)

        # Check if any observations are out of the allowable range
        # oob_lb = np.any(Z < self.lb, axis=0)
        oob_lb = np.sum(Z < self.lb, axis=0) > 0
        oob_ub = np.sum(Z > self.ub, axis=0) > 0
        oob = oob_lb | oob_ub
        logp[oob] = -np.inf
        # logp += -np.inf * oob

        return logp
Example #3
0
 def _hh_dynamics(z_vec, ti):
     # Set the inputs
     inpt = I[ti]
     latent = as_sarray(z_vec, population.latent_dtype)
     # state = as_sarray(population.evaluate_state(latent, inpt), population.state_dtype)
     dzdt = population.kinetics(latent, inpt)
     return dzdt.view(np.float)
Example #4
0
 def _hh_dynamics(z_vec, ti):
     # Set the inputs
     inpt = I[ti]
     latent = as_sarray(z_vec, population.latent_dtype)
     # state = as_sarray(population.evaluate_state(latent, inpt), population.state_dtype)
     dzdt = population.kinetics(latent, inpt)
     return dzdt.view(np.float)
Example #5
0
    def update(self, model, cache=None):
        """

        :param current_state:
        :return:
        """
        population = model.population

        # Update each data sequence one at a time
        for data in model.data_sequences:
            t = data.t
            T = data.T
            latent = data.latent
            inpt = data.input
            state = data.states
            obs = data.observations

            # View the latent state as a matrix
            D = sz_dtype(latent.dtype)
            z = as_matrix(latent, D)
            x = as_matrix(obs)

            lb = population.latent_lb
            ub = population.latent_ub
            p_initial = StaticTruncatedGaussianDistribution(
                D, self.mu_initial, self.sig_initial, lb, ub)

            # The observation model gives us a noisy version of the voltage
            lkhd = ObservationLikelihood(model)

            # The transition model is a noisy Hodgkin Huxley proposal
            # prop = TruncatedHodgkinHuxleyProposal(population, t, inpt, self.sig_trans)
            prop = HodgkinHuxleyProposal(population, t, inpt, self.sig_trans)

            # Run the particle Gibbs step with ancestor sampling
            # Create a conditional particle filter with ancestor sampling
            pf = ParticleGibbsAncestorSampling(D,
                                               T,
                                               0,
                                               x[:, 0],
                                               prop,
                                               lkhd,
                                               p_initial,
                                               z,
                                               Np=self.N_particles)

            for ind in np.arange(1, T):
                x_curr = x[:, ind]
                pf.filter(ind, x_curr)

            # Sample a particular weight trace given the particle weights at time T
            i = np.random.choice(np.arange(pf.Np), p=pf.trajectory_weights)
            # z_inf = pf.trajectories[:,i,:].reshape((D,T))
            z_inf = pf.get_trajectory(i).reshape((D, T))

            # Update the data sequence's latent and state
            data.latent = as_sarray(z_inf, population.latent_dtype)
            data.states = population.evaluate_state(data.latent, inpt)
Example #6
0
    def update(self, model, cache=None):
        """
        TODO: Handle truncated Gaussians noise for channel params
        """
        # Keep sufficient stats for a Gaussian noise model
        N = 0
        beta_V_hat = 0
        # beta_ch_hat = 0

        # Get the latent voltages
        for ds in model.data_sequences:
            latent = as_matrix(ds.latent)
            # The transition model is a noisy Hodgkin Huxley proposal
            prop = TruncatedHodgkinHuxleyProposal(model.population, ds.t, ds.input,
                                                  as_matrix(np.zeros(1, dtype=model.population.latent_dtype)))
            dt = ds.t[1:] - ds.t[:-1]
            # import pdb; pdb.set_trace()
            pred = np.zeros((latent.shape[0], ds.T-1))
            for t in np.arange(ds.T-1):
                pt,_,_ = prop.sample_next(t, latent[:,t,np.newaxis], t+1)
                pred[:,t] = pt.ravel()

            # pred2,_ = prop.sample_next(np.arange(ds.T-1),
            #                           latent[:,:-1],
            #                           np.arange(1,ds.T))

            # if not np.allclose(pred, pred2):
            #     import pdb; pdb.set_trace()
            for neuron in model.population.neurons:
                for compartment in neuron.compartments:
                    V = get_item_at_path(as_sarray(latent, model.population.latent_dtype),
                                         compartment.path)['V']
                    Vpred = get_item_at_path(as_sarray(pred, model.population.latent_dtype),
                                             compartment.path)['V']
                    dV = (Vpred - V[1:])/dt

                    # Update sufficient stats
                    N += len(dV)
                    beta_V_hat += (dV**2).sum()

        # Sample a new beta_V
        sig2_V = 1.0/np.random.gamma(hypers['a_sig_V'].value + N/2.,
                                     1.0/(hypers['b_sig_V'].value + beta_V_hat/2.))

        hypers['sig_V'].value = np.sqrt(sig2_V)
Example #7
0
    def _hh_kinetics(self, index, Z):
        D,Np = Z.shape
        # Get the current input and latent states
        current_inpt = self.inpt[index]
        latent = as_sarray(Z, self.population.latent_dtype)

        # Run the kinetics forward
        dxdt = self.population.kinetics(latent, current_inpt)

        # TODO: Wow, this is terrible. Converting to/from numpy struct array and
        # regular arrays, and maintaining the correct shape, is a mega pain in the ass
        return dxdt.view(np.float).reshape((Np,D)).T
Example #8
0
    def update(self, model, cache=None):
        """

        :param current_state:
        :return:
        """
        population = model.population

        # Update each data sequence one at a time
        for data in model.data_sequences:
            t = data.t
            T = data.T
            latent = data.latent
            inpt = data.input
            state = data.states
            obs = data.observations

            # View the latent state as a matrix
            D = sz_dtype(latent.dtype)
            z = as_matrix(latent, D)
            x = as_matrix(obs)


            lb = population.latent_lb
            ub = population.latent_ub
            p_initial = StaticTruncatedGaussianDistribution(D, self.mu_initial, self.sig_initial, lb, ub)

            # The observation model gives us a noisy version of the voltage
            lkhd = ObservationLikelihood(model)

            # The transition model is a noisy Hodgkin Huxley proposal
            # prop = TruncatedHodgkinHuxleyProposal(population, t, inpt, self.sig_trans)
            prop = HodgkinHuxleyProposal(population, t, inpt, self.sig_trans)

            # Run the particle Gibbs step with ancestor sampling
            # Create a conditional particle filter with ancestor sampling
            pf = ParticleGibbsAncestorSampling(D, T, 0, x[:,0],
                                               prop, lkhd, p_initial, z,
                                               Np=self.N_particles)

            for ind in np.arange(1,T):
                x_curr = x[:,ind]
                pf.filter(ind, x_curr)

            # Sample a particular weight trace given the particle weights at time T
            i = np.random.choice(np.arange(pf.Np), p=pf.trajectory_weights)
            # z_inf = pf.trajectories[:,i,:].reshape((D,T))
            z_inf = pf.get_trajectory(i).reshape((D,T))

            # Update the data sequence's latent and state
            data.latent = as_sarray(z_inf, population.latent_dtype)
            data.states = population.evaluate_state(data.latent, inpt)
Example #9
0
def recreate(model, t, I):
    # TODO: Iterate over populations and neurons
    assert model.population is not None, "Models population must be instantiated"
    population = model.population
    T = len(t)

    # Set up the initial conditions with steady state values
    z0 = population.steady_state()

    # Create a function to implement hodgkin huxley dynamics
    def _hh_dynamics(z_vec, ti):
        # Set the inputs
        inpt = I[ti]
        latent = as_sarray(z_vec, population.latent_dtype)
        # state = as_sarray(population.evaluate_state(latent, inpt), population.state_dtype)
        dzdt = population.kinetics(latent, inpt)
        return dzdt.view(np.float)

    # Do forward euler by hand.
    z0 = z0.view(np.float)
    D = len(z0)
    z = np.zeros((D, T))
    z[:, 0] = z0
    lb = population.latent_lb
    ub = population.latent_ub

    for ti in np.arange(1, T):
        dt = t[ti] - t[ti - 1]
        z[:, ti] = z[:, ti - 1] + dt * _hh_dynamics(z[:, ti - 1], ti - 1)
        z[:, ti] = np.clip(z[:, ti], lb, ub)

    # Convert back to numpy struct array
    Z = as_sarray(z, population.latent_dtype)

    # Compute the corresponding states
    S = population.evaluate_state(Z, I)

    # sample the observation model given the latent variables of the neuron
    O = model.observation.sample(Z)

    # Package into a data sequence
    ds = DataSequence(name, t, stimuli, O, Z, I, S)

    return ds
Example #10
0
def recreate(model, t, I):
    # TODO: Iterate over populations and neurons
    assert model.population is not None, "Models population must be instantiated"
    population = model.population
    T = len(t)

    # Set up the initial conditions with steady state values
    z0 = population.steady_state()
    # Create a function to implement hodgkin huxley dynamics
    def _hh_dynamics(z_vec, ti):
        # Set the inputs
        inpt = I[ti]
        latent = as_sarray(z_vec, population.latent_dtype)
        # state = as_sarray(population.evaluate_state(latent, inpt), population.state_dtype)
        dzdt = population.kinetics(latent, inpt)
        return dzdt.view(np.float)

    # Do forward euler by hand.
    z0 = z0.view(np.float)
    D = len(z0)
    z = np.zeros((D,T))
    z[:,0] = z0
    lb = population.latent_lb
    ub = population.latent_ub

    for ti in np.arange(1,T):
        dt = t[ti]-t[ti-1]
        z[:,ti] = z[:,ti-1] + dt * _hh_dynamics(z[:,ti-1], ti-1)
        z[:,ti] = np.clip(z[:,ti], lb, ub)

    # Convert back to numpy struct array
    Z = as_sarray(z, population.latent_dtype)

    # Compute the corresponding states
    S = population.evaluate_state(Z, I)

    # sample the observation model given the latent variables of the neuron
    O = model.observation.sample(Z)

    # Package into a data sequence
    ds = DataSequence(name, t, stimuli, O, Z, I, S)

    return ds
Example #11
0
def simulate(model, t, stimuli, name=None, have_noise=True, I=None):
    """
    Simulate a model containing a population of neurons, an observation model,
    and a stimulus.

    Right now this only is set up for a single neuron model

    :param model:
    :return:
    """
    # TODO: Iterate over populations and neurons
    assert model.population is not None, "Models population must be instantiated"
    population = model.population
    #import pdb; pdb.set_trace()
    # Make sure stimuli is a list
    if isinstance(stimuli, Stimulus):
        stimuli = [stimuli]
    else:
        assert isinstance(stimuli, list) or I is not None

    T = len(t)
    if I is None:
        I = np.zeros((T, ), dtype=population.input_dtype)
        for stim in stimuli:
            stim.set_input(t, I)

    # Set up the initial conditions with steady state values
    z0 = population.steady_state()

    # Create a function to implement hodgkin huxley dynamics
    def _hh_dynamics(z_vec, ti):
        # Set the inputs
        inpt = I[ti]
        #import pdb; pdb.set_trace()
        latent = as_sarray(z_vec, population.latent_dtype)
        # state = as_sarray(population.evaluate_state(latent, inpt), population.state_dtype)
        dzdt = population.kinetics(latent, inpt)
        return dzdt.view(np.float)

    # Do forward euler by hand.
    z0 = z0.view(np.float)
    D = len(z0)
    z = np.zeros((D, T))
    z[:, 0] = z0
    lb = population.latent_lb
    ub = population.latent_ub

    if have_noise:
        noisedistribution = TruncatedGaussianDistribution()
        # TODO: Fix this hack
        sig_trans = np.ones(1, dtype=population.latent_dtype)
        sig_trans.fill(np.asscalar(hypers['sig_ch'].value))
        for neuron in population.neurons:
            for compartment in neuron.compartments:
                sig_trans[neuron.name][
                    compartment.name]['V'] = hypers['sig_V'].value
                sig_trans = sig_trans.view(dtype=np.float)

    for ti in np.arange(1, T):
        dt = t[ti] - t[ti - 1]
        z[:, ti] = z[:, ti - 1] + dt * _hh_dynamics(z[:, ti - 1], ti - 1)
        z[:, ti] = np.clip(z[:, ti], lb, ub)

        if have_noise:
            # Add Gaussian noise
            noise_lb = lb - z[:, ti]
            noise_ub = ub - z[:, ti]

            # Scale down the noise to account for time delay
            # sig = sig_trans * np.sqrt(dt)
            sig = sig_trans * dt

            # TODO: Remove the zeros_like requirement
            noise = noisedistribution.sample(mu=np.zeros_like(z[:, ti]),
                                             sigma=sig,
                                             lb=noise_lb,
                                             ub=noise_ub)
            # import pdb; pdb.set_trace()
            z[:, ti] += noise

    # Convert back to numpy struct array
    Z = as_sarray(z, population.latent_dtype)

    # Compute the corresponding states
    S = population.evaluate_state(Z, I)

    # sample the observation model given the latent variables of the neuron
    O = model.observation.sample(Z)

    # Package into a data sequence
    ds = DataSequence(name, t, stimuli, O, Z, I, S)

    return ds
Example #12
0
def simulate(model, t, stimuli, name=None, have_noise=True, I=None):
    """
    Simulate a model containing a population of neurons, an observation model,
    and a stimulus.

    Right now this only is set up for a single neuron model

    :param model:
    :return:
    """
    # TODO: Iterate over populations and neurons
    assert model.population is not None, "Models population must be instantiated"
    population = model.population
    #import pdb; pdb.set_trace()
    # Make sure stimuli is a list
    if isinstance(stimuli, Stimulus):
        stimuli = [stimuli]
    else:
        assert isinstance(stimuli, list) or I is not None

    T = len(t)
    if I is None:
        I = np.zeros((T,), dtype=population.input_dtype)
        for stim in stimuli:
            stim.set_input(t, I)

    # Set up the initial conditions with steady state values
    z0 = population.steady_state()
    # Create a function to implement hodgkin huxley dynamics
    def _hh_dynamics(z_vec, ti):
        # Set the inputs
        inpt = I[ti]
        #import pdb; pdb.set_trace()
        latent = as_sarray(z_vec, population.latent_dtype)
        # state = as_sarray(population.evaluate_state(latent, inpt), population.state_dtype)
        dzdt = population.kinetics(latent, inpt)
        return dzdt.view(np.float)

    # Do forward euler by hand.
    z0 = z0.view(np.float)
    D = len(z0)
    z = np.zeros((D,T))
    z[:,0] = z0
    lb = population.latent_lb
    ub = population.latent_ub

    if have_noise:
        noisedistribution = TruncatedGaussianDistribution()
        # TODO: Fix this hack
        sig_trans = np.ones(1, dtype=population.latent_dtype)
        sig_trans.fill(np.asscalar(hypers['sig_ch'].value))
        for neuron in population.neurons:
            for compartment in neuron.compartments:
                sig_trans[neuron.name][compartment.name]['V'] = hypers['sig_V'].value
                sig_trans = sig_trans.view(dtype=np.float)

    for ti in np.arange(1,T):
        dt = t[ti]-t[ti-1]
        z[:,ti] = z[:,ti-1] + dt * _hh_dynamics(z[:,ti-1], ti-1)
        z[:,ti] = np.clip(z[:,ti], lb, ub)

        if have_noise:
            # Add Gaussian noise
            noise_lb = lb - z[:,ti]
            noise_ub = ub - z[:,ti]

            # Scale down the noise to account for time delay
            # sig = sig_trans * np.sqrt(dt)
            sig = sig_trans * dt

            # TODO: Remove the zeros_like requirement
            noise = noisedistribution.sample(mu=np.zeros_like(z[:,ti]), sigma=sig,
                                         lb=noise_lb, ub=noise_ub)
            # import pdb; pdb.set_trace()
            z[:,ti] += noise

    # Convert back to numpy struct array
    Z = as_sarray(z, population.latent_dtype)

    # Compute the corresponding states
    S = population.evaluate_state(Z, I)

    # sample the observation model given the latent variables of the neuron
    O = model.observation.sample(Z)

    # Package into a data sequence
    ds = DataSequence(name, t, stimuli, O, Z, I, S)

    return ds