静态突触的实现过程

本文讨论了在神经元网络中实现延迟机制,特别是使用环形缓冲解决突触延迟问题的方法。作者提到简化了代码,采用LIF神经元和静态突触,并描述了神经元和突触的初始化、更新过程。最后提及在编程过程中遇到的指针问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

当一个神经元产生脉冲时,需要将脉冲信息发送给突触后神经元,因此,突触有两个基本的属性,即权值和延迟,权值决定了脉冲的强度,延迟决定了突触后神经元什么时候收到脉冲信息。

我们采用的时间步长驱动的方式,因此,我觉得突触最难实现的是延迟的机制。想要在指定延迟将脉冲传给后神经元,需要先弄清楚延迟机制。如图所示,假设一个延迟为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);
  
}

报错为

我知道这是一个指针问题,但是我不知道哪里有问题,我要抽时间想想

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值