当一个神经元产生脉冲时,需要将脉冲信息发送给突触后神经元,因此,突触有两个基本的属性,即权值和延迟,权值决定了脉冲的强度,延迟决定了突触后神经元什么时候收到脉冲信息。
我们采用的时间步长驱动的方式,因此,我觉得突触最难实现的是延迟的机制。想要在指定延迟将脉冲传给后神经元,需要先弄清楚延迟机制。如图所示,假设一个延迟为5,pre在第三个产生一个脉冲,所以post需要在第二轮的第三个位置接受到该脉冲。
因此采用合适的缓冲机制,是解决脉冲延迟传输的主要方法,太难的突触我根本做不到,所以准备实现最简单的突触,而具体方法采用了论文Advancing the Boundaries of High-Connectivity Network Simulation with Distributed Computing中所采取的方法,感兴趣的可以去看看。延迟的机制
简单来说每个神经元都有一个环形缓冲区,在每个时间步长,每个神经元从时刻t的状态更新到t + h时刻的状态,其中h为模拟的时间分辨率。此更新是基于yt和wt+h(时间t+h到达的所有事件的加权总和)执行的。所有的脉冲事件都会在环形缓冲中存储。所以我重写了神经元的更新机制和代码。
但是我发现之前所写的代码过于多的考虑了面向的对象的问题,我决定花时间简化一下,首先我们要实现是一个在平台上能够运行的SNN网络,它不需要太过复杂,但是要实现SNN的基本网络,暂时不去考虑各种类的继承关系和如何分布式并行,从最简单的出发,神经元选择最简单的LIF神经元,突触选择最简单的静态突触。重新梳理一下SNN的网络过程。
SNN是由神经元组成的网络。为了表示这一点,将突触和神经元进行分离。如果一个突触被来自其突触前神经元的脉冲触发,它会将这个信息以一个权重为w、延迟为d的事件的形式传递给它的突触后神经元。每个神经元都被赋予一个唯一的索引即gid。
如图,该网络由N个唯一索引的神经元(左列)组成,每个神经元被分配一个轴突突触列表(右列)。每个神经元都有自己的状态变量,就像每个突触一样(如图所示)。此外,每个突触都包含其突触后神经元的索引。
写代码遇见一个问题,我暂时不知道怎么去解决,因为我不清楚为什么有这个问题。我将神经元定义为如下代码
#ifndef NEURON_H
#define NEURON_H
#include "Params.h"
#include "Ringbuffer.h"
class Neuron
{
private:
double v; //膜电压
double last_fired; //上次发放脉冲的的时间
int gid; //神经元全局id
double i_e; //累加电流
double dt; //时间精度
RingBuffer buffer;
NeuronParams *params;
void init(NeuronParams *params_,double v_init,int gid_);
public:
Neuron(NeuronParams *params_,int gid_);
~Neuron() = default;
void update(int from,int to,float current_t,std::vector<SpikeEvent>& spike_evnet);
void handle(SpikeEvent se);
};
Neuron::Neuron(NeuronParams *params_,int gid_)
{
init(params_,-65.0,gid_);
}
void Neuron::init(NeuronParams *params_,double v_init,int gid_)
{
params = params_;
v = v_init;
i_e = 0;
last_fired = -params->refractory;
gid = gid_;
dt = params->dt;
buffer.resize(params->len);
printf("%d init successful!\n",gid);
}
void Neuron::update(int from,int to,float current_t_,std::vector<SpikeEvent>& spike_evnet)
{
double current_t = current_t_;
for(int lag; lag < to; ++lag)
{
if (gid = 0)
{
printf("current time is: %lf\n",current_t);
}
if(current_t >= params->refractory + last_fired) //判断是否在不应期
{
double I_syn = buffer.get_value(lag);
i_e = params->i_offset + I_syn;
v += dt * ((params->v_rest - v + i_e * params->r_m)/params->tau_m);
if(v > params->v_thresh)
{
v = params->v_reset;
last_fired = current_t;
SpikeEvent se;
se.preneuron = gid;
se.lag = lag;
spike_evnet.push_back(se);
}
current_t += dt;
}
i_e = 0;
}
}
void Neuron::handle(SpikeEvent se)
{
}
#endif
在声明多个神经元时,主程序代码如下
#include <iostream>
#include <vector>
#include "Neuron.h"
#include "Synapse.h"
#include "Params.h"
int main()
{
//设置网络 定义邻接表
std::vector<std::vector<int>> adjList = {{1},{}};
//实例化神经元
NeuronParams *c_params = (NeuronParams *)malloc(sizeof(NeuronParams));
c_params->tau_m = 10.0f;
c_params->refractory = 2.0f;
c_params->v_rest = -65.0f;
c_params->v_thresh = -50.0f;
c_params->v_reset = -65.0f;
c_params->i_offset = 2.0f;
c_params->c_m = 0.250f;
c_params->r_m = 40.0f;
c_params->dt = 0.1;
// std::vector<Neuron> localNeuron;
// for (int i = 0; i < adjList.size(); i++)
// {
// localNeuron.push_back(Neuron(c_params,i));
// }
// localNeuron.push_back(Neuron(c_params,0));
// printf("adjList size is %d\n",localNeuron.size());
Neuron n(c_params,0);
Neuron n2(c_params,1);
free(c_params);
}
报错为
我知道这是一个指针问题,但是我不知道哪里有问题,我要抽时间想想