
分布式模拟脉冲神经网络
从0开始的脉冲神经网络的分布式仿真
黄芍药
这个作者很懒,什么都没留下…
展开
-
产品注册模板类+单例工厂模板类实现神经元和突触的创建
昨天设计了突触和神经元的类图的,因为在实际的实现过程中需要大量实例化对象和突触,因此,我考虑到使用工厂模式,看了博客。很有启发,决定设计产品注册模板类+单例工厂模板类。基本上按照这个思路去做。这样就完成了对神经元和突触的封装。原创 2023-12-19 12:18:25 · 437 阅读 · 0 评论 -
最近的进展
几天前,我还在老老实实的写着博客,突然晚上睡了一觉,发现左脚的脚踝特别疼,疼的无法直立行走,我想去医院,但是真的没办法走动,我没办法一个人去医院,这两天才好了一点,那几天晚上疼的睡不着,白天也疼的受不了,所以耽误了学习的进度。我再来想一想开发的方向吧,我是想设计成一个自定义的分布式模拟器,神经元就做三种,HH,LIF和Izhikevich,还有一个泊松发射器。突触做两种,一种是静态突触,另一种是stdp突触。其他辅助类,比如时间类啊,辅助类等统一放到time.h和utils的下面。原创 2023-12-18 22:54:51 · 444 阅读 · 0 评论 -
皮质微电路模型
我实现了一个简单的皮质微电路模型的缩放版本代码如下。原创 2023-12-14 22:43:25 · 392 阅读 · 0 评论 -
STDP突触的设计(二)
之前写过一个简单STDP突触的窗口函数,但是实际上的STDP突触远比一个窗口函数难得多,然后在拜读了论文Spike-Timing-Dependent Plasticity in Balanced Random Networks中有具体的分布式突触的设计,然后我按照他们给出的思路,复现了STDP突触的代码。最后是记录各种历史的类。原创 2023-12-13 21:12:55 · 616 阅读 · 0 评论 -
目前进度记录
这样的数据结构,使用set为了避免重复的脉冲发送,使用这个数据结构的好处是,可以不在使用全局的邻接表,减少了内存的占用。目前基本上已经完成了大部分的基础工作,接下来我希望能够在我代码中实现STDP的机制。目前已经把之前记录的方法都实现了,目前的主函数可以写的更简单比如。我优化了很多的方面。最大的优化在脉冲传输阶段。原创 2023-12-13 17:29:16 · 411 阅读 · 0 评论 -
严重错误(一)
我本来想每次向test添加不同的元素,但是每次都没有成功,问题在于 my 对象是在每次迭代的循环体内创建的。这意味着在每次迭代结束时,my 对象会超出其作用域并被销毁。因此,当你在 test 向量中存储 my 对象的地址时,实际上是存储了一个已被销毁的对象的地址,这会导致未定义行为。为了解决这个问题,你可以使用动态内存分配来创建 MyClass 对象,并在使用完后手动释放该内存。这几天写代码的时候遇见一个严重的错误,导致我思考很久没有想到原因,一开始代码。原创 2023-12-13 11:20:15 · 422 阅读 · 0 评论 -
数据结构传参及相关问题
在世界的开发过程中,我遇见一个函数需要传参一个数据结构,但是,我想这个数据结构的设初始值而不需要重新声明一个新的数据结构,代码如下。我本来打算之传输name,但在c++中函数参数的传递是按照参数的顺序进行的,不能直接从指定的第二个参数开始。原创 2023-12-08 20:48:53 · 454 阅读 · 0 评论 -
创建脉冲神经网络(一)
那时候我就在想,这些事情是不是可以提前做,避免脉冲的脉冲的判断,比如定义一个std::unordered_map<int, std::vector<int>> communication_diagram这样一个通信图, key值是神经元的gid,value代表需要通信的进程id集合。看一看出来在创建的过程中消耗了大部分的内存,所我决定重新设计一下,以减少内存的使用,其实问题最大的难点依旧在,脉冲的传输阶段,需要准确判断脉冲需要发送的位置,我之前的做法是这样。还有一点需要考虑,比如考虑如下种群创建实例。原创 2023-12-08 19:34:25 · 752 阅读 · 0 评论 -
种群的设计(二)
重新复盘了一下种群的特性,除了内在参数外,种群也对应的兴奋性种群和抑制性种群,兴奋种群的神经元释放的脉冲能够增加后神经元的膜电位,而抑制性神经元则相反。那用程序语言描述就是。接下来就是代码的全部重新整理了,呜呜呜~,加油。原创 2023-12-06 16:19:37 · 970 阅读 · 0 评论 -
MPI学习(一)
还有就是在写很多的类文件中,一定要注意不可以类之间的相互引用。另外就是如果你没有项目引用,但是依然报一个连接错误,请清理项目,然后重新生成即可。我之前一直不太清楚c里面三种传参方式的区别,在代码的时候,弄出很多错误,我是这样计划的所有的临济表都在0号进程创建,然后再传输到其他进程。最近在狂补mpi的相关知识,看到一些不错的文章,比如。还有就是返回指针和引用指针的区别。当然也可采用广播的方式。原创 2023-12-06 15:36:50 · 705 阅读 · 0 评论 -
分布式仿真思考(三)成功运行啦,哈哈哈
不过这个系列不会结束,我只是实现了最基本的功能,代码的注释和一些工作还没有做,算是一个小范围的成功,接下啦要再接再厉,加油。我们都知道localAdj[i].size()<=globalAdj[i].size()。但是实际情况却存在三种,在我实际的运行过程中,存在严重错误,导致我没有的到争取到结果,尤其是。终于,终于成功的进行了分布式的仿真,呜呜呜~,真不容易啊,来看效果。这种写法漏掉第三种情况,所以我们还得重新分析。原创 2023-12-05 20:21:23 · 631 阅读 · 0 评论 -
轮询分区的设置
所幸,在配置MPI环境时保存了之前的版本, 又重新配置了MPI环境,还好没问题,不得不说,有时候写代码真的跟玄学一样,但保存备份真的是一个无比好的习惯,赞颂。现在最大的问题是:因为创建SNN网络的时候,种群之间的连接是随机的。终于可以写MPI了,没想到,刚开始就当头一棒,我按照之前的配置MPI环境,配置完成就报错。SNN分区阶段:主要是对SNN网络进行分区比如轮询方式,均匀的分配每一个神经元。目前已经实现了网络的创建阶段,又实现了一个简单的轮询分区阶段。创建网络阶段:主要是神经元的创建和 神经元的连接。原创 2023-12-05 11:31:26 · 604 阅读 · 0 评论 -
脉冲数据的压缩
两个int和两个double一共占有24个字节,如果一万个脉冲就是240000,大约230多个kb这样看起来很小,但是如果使用mpi传输时,却会占有很大的时间。所以我采用一种压缩方式,记录一共脉冲仅仅需要他的发射神经元id以及发射的时间即可代码如下。这样就完美的实现了对source_gid和spike_tim的压缩,使用了无符号int,仅仅四个字节就描述了一个脉冲时间,这样应该是最完美的。在进行脉冲数据的传输时,如果一直采用事件的方式,比如我这样。原创 2023-12-04 15:53:03 · 501 阅读 · 0 评论 -
目前开发进展
说完了缺点,来说一下下一步准备干什么,下一步准备写MPI方面的代码了,MPI的管理类我也实现了,我一直在思考一个问题,我怎么判断我是否开启了MPI呢,其实也不是什么大问题,我把这个版本的保存一下,以后的设计都向mpi上边考虑,感觉这是一种比较稳妥的办法,所以先完成mpi的初始工作,包括对神经元的循环分配等。我按照之前的仿真框架更新了自己的代码。重新梳理了结构,有一说一,这对一个新手来说一点也不容易,中间遇见各种的问题,所幸,花了很多的时间的终于改好了,对所有的函数基本上实现了封装。原创 2023-12-04 15:45:46 · 597 阅读 · 0 评论 -
种群和种群之间连接的设计
我们知道神经元的创建方式是以种群为基础的,一个种群内的所有神经元的参数都一样,而种群与种群之间的连接也是随机概率的。创建的邻接表存储在名为global_adjacency中,在主函数中创建神经元和突触。在创建神经元的同时给每一个神经元附上一个gid。在连接两个神经元群落时,需要设置连接点概率。就可以实现群落的是神经元的创建和连接。原创 2023-12-03 16:52:33 · 395 阅读 · 0 评论 -
仿真的整体框架和类图设计
这个类是核心类,负责对所有管理类的实例化,单例模式实现,并提供Kernel()方法,方便对所有类进行访问。之前的写的模拟代码没有模块,没有对象,写的逻辑结构也很混乱。我花了些时间进行整理,首先所有的类如下图。我希望在这个类中管理所有的脉冲事件管理,比如收集脉冲事件等工作,判断是否属于本地脉冲等工作。在管理类中有统一的管理类的接口 ,提供所有管理类的虚拟初始化和关闭方法。这个类中,我打算实现网络的构建,突触邻接表的构建,脉冲的传递工作。这个类是杂类,负责对所有的仿真过程中的参数进行构造。原创 2023-12-02 12:30:13 · 457 阅读 · 0 评论 -
STDP突触设计(一)
这两篇的介绍的代码非常的详细,我就不再赘述了。最近看了很多的STDP的工作原理,比如。回来我会写出符合我之前设计的代码。原创 2023-12-01 18:18:12 · 818 阅读 · 0 评论 -
分布式仿真SNN的思考(二)
但换一种思考,只存储每个神经元的后神经元的个数,即。当一个神经元i是本地神经元时,且adj1[i].size()<global_adj[i].size()。当一个神经元i是本地神经元时,且adj1[i].size()=global_adj[i].size(),那么一定是本地脉冲。当一个神经元i不是本地神经元,adj1[i].size()<global_adj[i].size(),远程脉冲。当一个神经元i不是本地神经元,adj1[i].size()=global_adj[i].size(),远程脉冲。原创 2023-12-01 12:51:53 · 445 阅读 · 0 评论 -
分布式仿真SNN的思考
观察每一个图的CSR的存储,你就会发现,对于一个名为gid的神经元,如果他的xadj[gid]<xadj[gid+1],那么该神经元的后神经元就一定存在本地。明显,对于神经元来说,很容易将其进行分区,但是对于突触来说就没那么简单了,有些文献建议将突触和后神经元存储在一起,邻接表就变成上图的格式。将整体的网络构成见一个邻接表,突触和神经元作为类分别存储,所以当一个神经元发射脉冲时,很容易的将脉冲传输到突触指向的后神经元。对于第一个问题,我想出一种方案,能够解决一个神经元的后神经元是否在本地。原创 2023-11-30 16:09:52 · 900 阅读 · 0 评论 -
关于图的存储方式的一些转换
这项工作主要是对以后存在的SNN网络的拓扑结构的探讨,对于SNN网络来说,大部分的拓扑结构都是稀疏性,所以我们不可能使用邻接矩阵的方式存储,因为假设模拟1000个神经元,这开销太大,不能接受。相反采用邻接表或者CSR的格式,可以节省内部空间。将数据保存为graph.txt。然后读取代码保存为邻接表,则代代码为。再将邻接表转换成一个CSR存储的稀疏矩阵。假设SNN是如下图表示的网络。很容易得出他的边列表。原创 2023-11-30 12:49:40 · 378 阅读 · 0 评论 -
MPI的NBX的实现
首先,假设每一进程都有需要发送给其他进程的数据,我们在这里可以理解为脉冲,那其实每一个进程都有一个邻接表,而邻接表的内容代表需要和其他进程通信的需求。我这里使用4个进程。关于邻接表的创建,我打算随机生成。那么整体的代码应该为。原创 2023-11-29 20:35:10 · 756 阅读 · 0 评论 -
重新理一下SNN的模拟过程,及其分布式的初步构想
我设计成如下图所示的更新流程图这是仿真器的更新流程图,对于一个普通的SNN网络不考虑分布式的其内部网络如图所示分布模拟最明显分布式模拟的要求是神经元是分布的,突触也必须是分布的。最简单的负载平衡是为每台机器分配相同数量的神经元。由于网络中可能有不同的神经元模型和不同的相关计算成本,因此使用模运算执行此分配,以便在所有机器中分配连续的神经元块,从而很好地估计最公平的负载分布。如图所示因此,分布式模拟是一个极其复杂的过程。原创 2023-11-29 16:14:53 · 754 阅读 · 0 评论 -
开发遇见错误(一)
我一开始所有的类文件都是写在.h文件中。后来又重新所有.h文件添加了源文件,直接把类的定义内部成员函数,复制粘贴到类的外面。所有函数都有inline关键字,导致错误入戏。因为是一次写一些比较大的项目。而且自定义的,总是想到哪里就写到哪里,特别容易出现一下问题,下面是我经常遇见的。以后将类定义放在类外,以提高代码的可维护性和可读性。解决方式:删除inline关键字即可。我查看官方文件错误类型为。原创 2023-11-29 14:27:41 · 378 阅读 · 0 评论 -
成功模拟脉冲神经网络
终于成功的模拟了一个脉冲神经网络的更新过程了,呜呜呜,真不容易啊,改代码改了好久,断断续续的查论文,看SNN的机制。现在终于可以说自己完成了(自豪),开心。因为在每一个时间片都需要保存已经运行的时间步,而且对全局可用,所以,在Manager.h中加入set和get方法。接下来就是代码的优化了。其实最终目的肯定是分布式运行,不过也没必要着急。具体代码我不粘贴,因为写的有点多,一下全粘贴出来,可能不太好。来看看最终的运行效果。原创 2023-11-28 17:04:40 · 491 阅读 · 0 评论 -
时间类的创建
在第二个时间片中,当lag=0时,moduli[0]=2, 而buffer[moduli[0]] = 0,说明neuron2是没有接收到脉冲的,当lag=1时moduli[1] = 3。此时呢,moduli[3]=0。在这个表中 neuron第一次发射脉冲的时间为 2 那么对neuron1来说他会在2+2时刻接受到neron的脉冲,但是因为是从零开始的,所以要减一,2+2-1=3,也就是说moduli[3]=1的,但是buffer最大的长度是3怎么办呢,buffer[3%3=0]=1;原创 2023-11-28 16:50:05 · 1254 阅读 · 0 评论 -
辅助类的设计
今天主要设计了一下辅助类的,因为对于双缓冲,在neuron神经元和main函数中都需要使用moduli缓冲,所以我思考了很久,决定写一个辅助函数Manager,并且使用单例模式实现它,这样无论是neuron修改moduli,还是main函数修改moduli都可以实现统一的读写机制。今天只是搭建了一个简单的框架,内容还没有进行填充,明天可能没有时间写代码,所以后台我会更新一下代码的逻辑。原创 2023-11-25 19:08:10 · 316 阅读 · 0 评论 -
突触的双缓冲区域的设置
脉冲传输: neuron1:buffer[moduli(1+delay1-update)% max_delay=1]=1 buffer2[moduli(1+delay2-update)% max_delay=2]=1。脉冲传输: neuron1:buffer[moduli(1+delay1-update)% max_delay=0]=1 buffer2[moduli(1+delay2-update)% max_delay=1]=1。上面的的表就是更新的步骤,代码我会慢慢写的。我们假设这样一个网络。原创 2023-11-24 17:48:43 · 423 阅读 · 1 评论 -
突触延迟的论文阅读
在设计神经元网络的离散时间仿真工具时,在定义神经元的连续动态和它们交换的点事件(尖峰)之间的相互作用时经常遇到概念上的困难。当该工具被设计为分布在许多计算机上时,这些问题就会显著增加。在本章中,我们汇集了过去几年来为处理这些困难而发展起来的方法。我们描述了一个框架,在这个框架中,模拟中的事件的时间顺序保持一致。它适用于具有任意亚阈动态的神经元网络,具有或不具有延迟,交换点事件约束于离散时间网格或连续时间网格,并且与分布式计算兼容。原创 2023-11-23 18:34:34 · 127 阅读 · 0 评论 -
静态突触的实现过程
但是我发现之前所写的代码过于多的考虑了面向的对象的问题,我决定花时间简化一下,首先我们要实现是一个在平台上能够运行的SNN网络,它不需要太过复杂,但是要实现SNN的基本网络,暂时不去考虑各种类的继承关系和如何分布式并行,从最简单的出发,神经元选择最简单的LIF神经元,突触选择最简单的静态突触。此外,每个突触都包含其突触后神经元的索引。当一个神经元产生脉冲时,需要将脉冲信息发送给突触后神经元,因此,突触有两个基本的属性,即权值和延迟,权值决定了脉冲的强度,延迟决定了突触后神经元什么时候收到脉冲信息。原创 2023-11-21 16:11:22 · 94 阅读 · 0 评论 -
对突触网络的分析
但是一个大的SNN网络中,不同的突触的延迟是不相同的,我想重新梳理一下这种机制,当SNN网络中一个神经元发射脉冲时,假设此时的时间为T,而网络中的最大延迟和最小延迟分别为max_delay和min_delay,这意味该脉冲的最早交付时间为T+min_delay,而最晚的交付时间为T+(min_delay-1)+max_delay。从我们之间的描述来看,脉冲的模拟一直是按照时间走的,所有的神经元的ringbuffer在同一时刻都执行的时刻的输入电流。因此0<=S-T_d<=max_del-1。原创 2023-11-22 21:07:34 · 111 阅读 · 0 评论 -
重新设计仿真方案
昨天的问题顺利解决,原因是我对指针的操作不熟悉,但至于详细原因是什么我也不知道,所以我就放弃了指针的操作,下面给出神经元的代码。在2.2时刻0号神经元也发射一个脉冲,而一号神经元处于静默期,所以没有收到,符合流程。我只模拟了两个神经元,突触的延迟设置为1ms,仿真精度为0.1。每个神经元的缓冲机制为。脉冲事件的数据结构为。原创 2023-11-22 08:42:15 · 63 阅读 · 0 评论 -
神经元的实现细节问题
神经元只是模拟很简单的一部分,接下来我会思考如何使用突触来连接这些神经元,并且能够实现脉冲的交互,这可能要花几天时间,突触也同样有很多的类型,比如静态突触,STDP等,我计划先实现静态突触,然后再去实现更有难度的突触,目前计划和神经元一样,给突触做一个父类,其他突触类型都继承于它。今天主要时实现三种神经元的c++代码,并且展示他的膜电位随着时间的变化而变化,如果时间充足我会记录一下电位,并且画出其膜电位随着时间的变化。以上代码中的实现细节很简单,但是涉及的参数量众多,我暂时还有想好如何去管理这些参数量。原创 2023-11-20 14:52:44 · 117 阅读 · 1 评论 -
脉冲神经网络的神经元的实现
明显可以看到三种神经元虽然有着相同的放电机制,但是其内部方程的参数完全不同,至于HH神经元,我觉得他太过于复杂,所以本文不再讨论。在SNN中,脉冲神经网络有很多的神经元类型,包括HH、LIF和izhikevich等,所以在我的设计中,我希望所有的神经元都继承于一个Neuron的总类,这样在创建和使用时比较方便。但是存在的一个问题就是这些神经元的超参数相同,在创建的过程中,我暂时不清楚用什么方法完成。tau_m 是膜时间常数(Membrane time constant),表示膜电位衰减的速度。原创 2023-11-20 09:34:33 · 244 阅读 · 1 评论 -
脉冲神经网络的分布式模拟开篇
我计划记录自己从零开发脉冲神经网路的步骤,每天都会记录开发情况,之前一直想要做的,但是因为本人太过懒散,缺乏自制力。因此,希望在此写下开发步骤,希望大家能够监督和指导,我都会虚心接受。随着神经网络规模的增加和计算需求的提高,对于大规模SNN的模拟和仿真,分布式计算是一种常用的策略。分布式开发包括神经元的微分方程更新,神经元的通信步骤,如何在分布式中实现,以及指数型突触的搭建,网络的存储和读取等一系列步骤。所有的开发都基于c++语言。分布式通信基于MPI,我所搭建的模型是基于时间步长驱动的解决方案。原创 2023-11-19 15:20:28 · 86 阅读 · 0 评论