Custom synapse or connection model

This chapter will introduce how to customize connections and synapse.

Customize connection

Connection is the basic structure of neuron network, it contains weight information. Different connection way will generate different spatially structure. To meet users’ requirements, SPAIC has constructed many common connection methods. If users want to add some personalize connection, can follow the document or the format in spaic.Network.Connection.

Initialize connection method

Custom connection method need to inherit Connection class and modify the corresponding parameters. Use FullConnection as example:

def __init__(self, pre, post, name=None, link_type=('full', 'sparse_connect', 'conv','...'),
             syn_type=['basic_synapse'], max_delay=0, sparse_with_mask=False, pre_var_name='O', post_var_name='Isyn',
             syn_kwargs=None, **kwargs):
    super(FullConnection, self).__init__(pre=pre, post=post, name=name,
                                         link_type=link_type, syn_type=syn_type, max_delay=max_delay,
                                         sparse_with_mask=sparse_with_mask,
                                         pre_var_name=pre_var_name, post_var_name=post_var_name, syn_kwargs=syn_kwargs, **kwargs)
    self.weight = kwargs.get('weight', None)
    self.w_std = kwargs.get('w_std', 0.05)
    self.w_mean = kwargs.get('w_mean', 0.005)
    self.w_max = kwargs.get('w_max', None)
    self.w_min = kwargs.get('w_min', None)

    self.is_parameter = kwargs.get('is_parameter', True) # is_parameter以及is_sparse为后端使用的参数,用于确认该连接是否为可训练的以及是否为稀疏化存储的
    self.is_sparse = kwargs.get('is_sparse', False)

In this initial way, the extra parameters should get from kwargs .

Customize synapse model

To meet users requirements, SPAIC has constructed some common synapse model. But if users want to add some personalized model, they need to define synapse model as the format of Network.Synapse .

Define parameters that can be obtained externally

In the initial part of defining the neuron model, we need to define some parameters that the neuron model can change, which can be changed by passing parameters. For example, in the first-order decay model of chemical synapses, the original formula can be obtained after transformation:

class First_order_chemical_synapse(SynapseModel):
    """
    .. math:: Isyn(t) = weight * e^{-t/tau}
    """

In this formula, self.tau is changeable, so we can change it by kwargs .

self._syn_tau_variables['tau[link]'] = kwargs.get('tau', 5.0)

Define variables

In the variable definition stage, we need to understand several variable forms of synapses:

  • _syn_tau_constant_variables – Exponential decay constant

  • _syn_variables – Normal variable

To _syn_tau_constant_variables , we will transmit it as value = np.exp(-self.dt / var) ,

When defining variables, initial values need to be set at the same time. After each run of the network, the parameters of neurons will be reset to the initial values set at this point.

self._syn_variables[I] = 0
self._syn_variables[WgtSum] = 0
self._syn_tau_constant_variables[tauP] = self.tau_p

Define calculation operation

The calculation operation is the most important part of the synaptic model. The calculation operation determines how the parameters will undergo some changes during the simulation.

There are a few rules to follow when adding computations. First, each row can only evaluate one specific operator, so you need to decompose the original formula into independent operators. The current built-in operator in the platform can be found in backend.basic_operation :

  • add, minus, div

  • var_mult, mat_mult, mat_mult_pre, sparse_mat_mult, reshape_mat_mult

  • var_linear, mat_linear

  • reduce_sum, mult_sum

  • threshold

  • cat

  • exp

  • stack

  • conv_2d, conv_max_pool2d

Use the process of computing chemical current in chemical synapse as an example:

# Isyn = O * weight
# The first is the result, conn.post_var_name
# Compute operator `mat_mult_weight` at the second index
# The third is the factor of the calculation, input_name and weight[link]
# '[updated]' means the updated value of current calculation, temporary variables don't need
self._syn_operations.append(
    [conn.post_var_name + '[post]', 'mat_mult_weight', self.input_name,
     'weight[link]'])