PyNN:神经网络模拟器的通用接口
计算神经科学已经产生了用于模拟神经元网络的多样化软件,同时具有消极和积极的后果。一方面,每个模拟器都使用自己的编程或配置语言,导致将模型从一个模拟器移植到另一个模拟器相当困难。这妨碍了调查人员之间的交流,使得难以复制和建立他人的工作。另一方面,仿真结果可以在不同的仿真器之间进行交叉检查,对其正确性给予更大的信心,并且每个仿真器具有不同的优化,因此可以为给定的建模任务选择最合适的仿真器。对多个模拟器的通用编程接口将减少或消除模拟器多样性的问题,同时保留好处。 PyNN就是这样的一个接口,可以使用Python编程语言编写一次仿真脚本,并在任何支持的仿真器(目前NEURON,NEST,PCSIM,Brian和Heidelberg VLSI神经形态硬件)上进行修改。 PyNN通过提供高级抽象,通过促进代码共享和重用以及为模拟器不可知的分析,可视化和数据管理工具提供基础来提高神经元网络建模的生产力。 PyNN通过使得在多个模拟器上检查结果变得更容易,提高了建模研究的可靠性。 PyNN是开源软件,可从http://neuralensemble.org/PyNN获得
介绍
科学依赖于公开交流的三大支柱,结果的可重复性和建立在以前的基础之上。 在这些方面,计算神经科学应该处于一个很好的位置,因为计算机通过设计擅长重复同样的任务而没有变化,所需的次数:计算结果的再现性应该是一项微不足道的任务。 类似地,互联网使实验室之间几乎可以即时传输研究材料,即源代码。
然而,在实践中,这种重复性和沟通的理论上的简易性很少在单个实验室以及几个月或几年的时间范围之外实现。虽然某个科学家可能很容易就能够再现几个月前所获得的结果,但是正确地再现几年前获得的结果可能会更加困难,而一般的经验似乎是再现别人的结果是困难的耗时:很多已发表的论文缺乏足够的细节从头开始重建模型,印刷错误是常见的。
可用的模型的源代码大大改善了这种情况,但是在这里仍然有许多障碍重复性和建立在以前发表的模型。一个是随着计算机体系结构,编译器标准和模拟器的发展,源代码可能会快速过时。另一个原因是模型源代码通常不是在考虑重用和扩展的情况下编写的,因此需要对模块化代码进行大量的重写。可能最重要的障碍是为一个模拟器编写的代码与任何其他模拟器不兼容。
尽管神经科学中的许多计算模型是从一开始就用通用编程语言(如C ++或Fortran)编写的,但大多数人可能使用一种特殊目的的模拟器,使模型可以用神经科学特定的概念来表示,如神经元,离子通道,突触;模拟器负责将这些概念转化为方程组和数值求解方程组。大多数这样的模拟器是可用的(在Brette等人,2007中进行了评论),大多数是开源软件,并且各自具有其自己的编程语言,配置语法和/或图形界面,这在将模型翻译一个模拟器到另一个模拟器,或者甚至理解别人的代码,对于调查人员之间的沟通,他人模型的再现性以及在现有模型上的构建都有明显的负面影响。
然而,模拟器的多样性也带来了一些积极的后果:(1)它允许交叉检查 - 两个不同模拟器具有相同错误或隐藏假设的概率非常小; (ii)每个仿真器在效率(仿真运行的速度),灵活性(添加新功能的容易程度,可模拟的模型的范围),可扩展性(并行,群集上的分布式计算或超级计算机)和易用性,所以可以选择最适合的任务。
解决与多个模拟器生态系统相关的问题同时保留好处将极大地增加神经科学中计算模型的重现性,从而更容易验证已发表模型的有效性并构建以前的工作。
至少有两种可能的(和相辅相成的)方法。一个是在不同的模拟器之间进行直接高效的通信,允许在不同的模拟器上模拟模型的不同部分(Ekeberg and Djurfeldt,2008)。这种方法解决了从不同组件构建模型的问题,但仍然留下不得不使用不同编程语言的问题,并且不能直接进行交叉检查。另一种方法是开发一个模拟器独立的模型规范系统。那么翻译只需要为每个模拟器完成一次,而不是每个模型一次。
在这里,我们可以利用Python编程语言最近迅速的出现,作为几个更广泛使用的模拟器的替代接口。因此,例如,NEURON和NEST都可以通过原始的本地解释器(分别是Hoc和SLI)或者通过Python来控制。最近的模拟器(例如PCSIM,Brian)将Python作为唯一可用的脚本语言。 Python的广泛采用可能是由于许多因素造成的,包括强大的数据结构,清晰和表达的语法,丰富的库,用于数值分析和可视化的工具的成熟度(允许使用单一语言来模拟整个工作流程分析到图形化),以及Python作为一种粘合语言的易用性,允许在低级语言(如C)中编写的计算密集型代码在高级Python代码中被透明地访问。
Python本身并没有解决翻译问题(尽管它确实使翻译过程更容易,因为至少简单的数据结构,如列表和数组,对于每个模拟器是相同的),因为神经科学特定的概念仍然表达不同。 然而,现在可以为神经网络模拟器定义一个与模拟器无关的Python接口,并实现自动翻译到任何支持Python的模拟器。 我们设计和实现了这样一个接口,PyNN(发音为“松”)。 在本文中,我们描述其设计,概念,实施和使用。 我们不试图在这里提供一个完整的用户指南 - 这可以在网上找到http://neuralensemble.org/PNNN。
设计目标
在设计和实现一个通用的模拟器接口时,应该考虑以下目标。这些是我们在设计和实现PyNN接口时一直牢记的目标,但是它们同样适用于任何其他这样的接口。
一次编写一个模型的代码,在任何支持的模拟器或硬件设备上运行,无需修改。这是PyNN的主要设计目标。
支持高层次的抽象。例如,处理代表神经元群体的单个对象通常比直接处理所有单个神经元更好。必要时可以访问每个单个神经元,但在许多情况下,人口是更有用的抽象。这种方法的优点是:(i)保持模型的概念性思想比较容易,而不会被实施细节分散注意力;(ii)对象的内部实现可以针对速度,并行化或存储器需求进行优化改变呈现给用户的界面。
支持至少两个支持的模拟器提供的任何功能。目标是在支持所有模拟器的所有特性(不可行)和仅支持所有模拟器共有的特性子集(过度限制)之间取得平衡。
允许混合PyNN和本地模拟器代码。 PyNN不应限制可执行模型的范围。遵循上面的两个模拟器规则,在一个模拟器中将会有可能的事情,而不是任何其他事情。尽管由100%PyNN组成的模型实现是在多个模拟器上运行的最佳场景,但是具有50%PyNN代码的实现将比在没有PyNN代码的模拟器之间转换更容易。
便于在模拟器之间移植模型。 PyNN改变了在模拟器之间移植模型的过程,从完全或者完全没有,在翻译完成之前翻译模型的有效性不能被测试到增量的方法,其中本地代码逐渐被模拟器取代独立的代码。在每个阶段,混合代码仍然是可运行的,因此可以直接验证模型行为没有改变。
最大限度地减少依赖关系,尽可能简化安装并最大限度地提高灵活性。 PyNN没有内置的可视化和少量的数据分析工具,这意味着用户可以使用任何他们想要的工具。
在输出和输入上呈现一致的界面。用于模拟输出的格式在模拟器后端是一致的,使其成为建立更复杂的模拟控制,数据分析和可视化系统的稳定基础。
优先考虑兼容性,但允许通过慎重选择用户选择兼容性中断优化(例如,各种print()方法的compatible_output标志默认为True,但可以设置为False以获得可能更快的写入的数据到文件)。
API版本。随着时间的推移,PyNN API将不可避免地演化,因为支持更多的模拟器并考虑用户社区的偏好。为了确保向后兼容性,应该对API进行版本化,以便用户可以指出哪个版本用于特定的实现。请注意,本文中给出的示例使用API??的0.4版本。
透明的并行化。在单个处理器上运行的代码应该可以在多个处理器(使用MPI)上运行而不用更改。
其中一些目标有点矛盾:例如,抽象程度高,移植简单。调和这对特定的目标导致PyNN中出现了一个高级的,面向对象的接口和一个与许多现有模拟器的接口更相似的低级过程接口。这些将在下面进一步讨论。
使用例子
在详细描述PyNN接口的基本概念之前,我们将通过一些在实践中使用它的例子来进行工作:首先是一个简单的例子,使用低级的过程接口,然后是使用高级对象的更复杂的例子 面向界面。
举个简单的例子,我们将建立一个网络,由一个单一的集成和火灾(IF)单元接收来自泊松过程的尖峰输入。
首先,我们通过从PyNN导入相关模块来选择使用哪个模拟器:
如果我们想要使用PCSIM,我们只需要导入pyNN.pcsim等。无论我们使用哪个模拟器后端,下面的代码都不会改变。
接下来我们设置模拟器的全局参数:
现在我们创建两个细胞:带有突触的IF神经元,对突触作出响应,突触传导逐步增加,然后呈指数衰减;“尖峰源”是一个在预定时间发射尖峰但不能接收输入尖峰的简单细胞。
在这种情况下,create()函数将标准PyNN模型名称IF_cond_exp转换为模拟器使用的模型名称,standard_IF用于NEURON,iaf_cond_exp用于NEST,还将参数名称和单位转换为模拟器 - 具体的名称和单位。 举一个例子,i_offset参数表示注入到单元中的恒定电流的幅度,并且以毫安表示。 NEST iaf_cond_exp模型的等价参数名称为I_e,单位为picoamps,因此在使用NEST运行时,PyNN都会转换名称并将数字值乘以1000。 标准单元模型和自动翻译将在下一节详细讨论。
create()函数返回一个ID对象,它提供对单元模型参数的访问,例如:
创建细胞后,我们用connect()函数连接它们:
现在我们告诉系统记录哪些变量或变量,运行模拟并完成。
运行上述模型的结果如图1所示,其中还显示了对于这样一个简单的网络,不同模拟器之间可获得的再现性程度。
图1.文中给出的第一个例子的运行结果,NEURON,NEST和PCSIM作为后端模拟器。 (A)积分时间步0.1 ms的整个膜电位曲线。 (B)放大迹线的较小区域,显示不同模拟器的结果之间的小的数字差异。 (C)积分时间步长为0.01ms的仿真结果显示数值差异大大减小。
使用create(),connect()和record()函数的低级过程接口对于简单模型或移植使用创建/连接方式的不同语言编写的现有模型时非常有用。对于更大,更复杂的网络,我们发现具有更高抽象层次的面向对象方法更为有效,因为它通过隐藏实现细节来澄清模型的概念结构,场景优化。
为了说明高级的,面向对象的界面,我们现在从一些简单的例子,从一些神经元转变为一个更复杂的例子:一个由数千个兴奋和抑制神经元组成的网络,显示自我维持的活动(基于“CUBA” Vogels和Abbott(2005)模型,再现了Brette等人(2007)使用的基准模型)。这仍然不是一个特别复杂的网络,因为它只有两种细胞类型,没有空间结构,没有神经元或连接特性的异质性,但是在演示如何使用PyNN构建这样的网络变得微不足道的时候,我们希望说服读者,真正建设复杂,结构化和异构化的网络变得易于管理。
再次,我们从选择使用哪个模拟器开始。我们还从PyNN的随机模块导入了一些类。
我们接下来指定神经元模型的参数(相同的模型和相同的参数用于兴奋性神经元和抑制性神经元)。
参数的电压值是毫伏,时间以毫秒为单位,电容为毫法。 单位公约将在下一节进一步讨论。
我们现在初始化模拟,这次接受全局参数的默认值。
现在,不是分别创建每个细胞,而是为每个不同类型的细胞创建一个Population对象:
默认情况下,给定Population的所有细胞都使用相同的参数创建,但可以随后进行更改。 这里我们希望在模拟开始时将膜电位的值随机化至-50和-70 mV之间的值。
andomInit()是随机化初始膜电位的一种方便的方法。 对于随机化任何单元格参数的更一般情况,请使用rset()。
正如单个神经元被封装在群体中,神经元之间的连接被封装在投影中。 要创建一个Projection对象,我们需要指定神经元如何连接,或者通过一个算法,或者通过一个明确的列表。 不同的算法封装在不同的连接器类中,例如FixedProbabilityConnector,AllToAllConnector。 连接的显式列表可以通过FromListConnector或FromFileConnector提供。
请注意,权重以微西门子(导电度单位)和毫秒延迟。 在没有指定延迟的情况下,使用setup()函数中指定的全局最小延迟。 在这里,我们将投影的所有权重和延迟设置为相同的值,但同样可以将构造函数传递给RandomDistribution对象,就像我们上面为初始膜电位所做的那样,或者是一个明确的值列表。
要创建投影,我们需要指定突触前和突触后Population,连接器对象和突触类型。 标准IF细胞各自具有两种突触类型,“兴奋性”和“抑制性”。 用户定义的模型可以使用任意名称,例如 “AMPA”,“NMDA”。
构建了网络之后,我们现在需要使用Population对象的record()(用于记录尖峰)和record_v()(膜电位)方法来对其进行检测。 在这里,我们选择记录1000个兴奋性神经元(随机选择)和所有抑制性神经元的峰值,并记录两个特定兴奋性神经元的膜电位。 然后,我们运行1000毫秒的模拟。
运行仿真后,我们可以访问结果或写入文件。
图2显示了使用两个不同的仿真器后端运行上述网络的仿真结果。
图2.运行本文第二个例子的结果,NEURON和NEST作为后端模拟器。 请注意,在这两种情况下,网络连接和初始条件是相同的。 (A)两个兴奋性神经元的膜电位曲线。 请注意,NEST和NEURON曲线在开始的50毫秒内非常相似,但在此之后,由于网络活动的影响而快速发散,从而放大了较小的数值积分差异。 (B)兴奋性(黑色)和抑制性(绿色)神经元的刺激活动。 每个点代表一个尖峰,每一行点都是不同的神经元。 显示了所有5000个神经元。 (C)兴奋性和抑制性神经元的汇集间刺激间隔(ISI)的分布。 (D)ISI变异系数[CV(ISI)]的神经元分布。
主要概念
为了实现“一次编写模型的代码,在任何支持的模拟器上运行而不需要修改”的目标,需要(i)通用接口,(ii)跨模拟器标准化的神经元和突触模型,(iii) (iv)一致处理(伪)随机数。 为了实现支持高级抽象和便于在模拟器之间移植模型的双重目标,需要面向对象和过程接口。 所有这些要求的实施将在下面进行更深入的描述。 我们还通过描述对多分区模型的支持来说明PyNN和本地模拟器代码的混合,以及PyNN如何支持仅在单个模拟器后端找到的功能。
标准细胞模型
PyNN中的一个基本概念是细胞类型 - 一个给定的神经元模型,可由一组方程表示,并包括亚阈值行为,尖峰机制和突触后响应。细胞类型的公共接口主要由其参数定义。相同细胞类型的不同神经元如果具有不同的参数值,则可能具有非常不同的行为。例如,Izhikevich模型(Izhikevich,2003)可以重现各种各样的尖峰模式,从快速跳动到正常尖峰到多种类型的爆发,取决于所选的参数值。因此细胞类型是模型类型而不是生物学定义的细胞类型(例如,“层V锥体神经元”)。
当使用给定的模拟器后端时,PyNN可以使用该模拟器支持的任何单元类型。在这种情况下,单元类型通常由一个字符串表示,保持对该模拟器有意义的模型名称,例如, “iaf_neuron”在NEST。
当然,这种细胞类型只能与一个模拟器一起工作。要创建一个可以在不同模拟器上运行的模型,需要使用PyNN内置的标准单元模型,每个模型都由StandardCell类的子类表示。由PyNN提供的模型包括各种简单的IF模型,Izhikevich自适应指数IF模型(Brette和Gerstner,2005),霍奇金 - 赫胥黎钠和钾通道的单室神经元,以及各种模型,到泊松过程),但不能接收它们。
StandardCell类包含用于在PyNN标准化值和模拟器特定值之间转换模型名称,参数名称和参数单位的机器。当基础模拟器使用不同的单位系统或相同方程组的不同参数化时,这是特别有用的。当一个模拟器期望膜时间常数和另一个膜渗漏电导。表1给出了由PyNN执行的翻译的一个例子。
目前,所有的标准细胞类型都是单室或点神经元模型,因为PyNN目前仅支持一个用于多分区模型(NEURON)的模拟器。 下面给出了有关PyNN的NEURON后端使用多分区模型的更多细节。 我们计划在将来允许使用NeuroML描述来指定多隔室细胞类型(Crook等,2005)。
单位
从前面的部分可以清楚地看出,每个模拟器后端都有自己的约定,哪个单位使用哪个物理量。 Brian的例外情况是,它有一个明确指定单位和检查方程式在维度上一致的系统。今后,我们打算采用Brian的PyNN系统,但是现在我们选择了一个与NEURON和NEST类似的惯例,因为这些单元是那些倾向于被实验生理学家使用的单元。 PCSIM(也是GENESIS模拟器)使用纯SI单位而没有前缀的一个替代方案是另一种选择。后一种惯例的优点是不需要检查尺寸一致性的方程式。缺点是这种系统中的数值通常非常大或很小,因此人们对于合理和不合理的参数值的直觉大部分都会丢失。
考虑不同惯例的优点,最重要的是PyNN现在提供了一个在模拟器中有效的单一约定。具体来说,约定如下:电压 - mV,电流 - nA,电导 - μS,时间 - ms,电容 - nF。
标准突触模型
在PyNN中,初级突触后电流或电导变化响应于突触前峰值的形状和时间过程被认为是突触后神经元模型的一部分,而突触连接的所有其他性质,特别是其重量(突触响应的峰值电流或电导),延迟(对于点模型,这隐含地包括轴突传播,化学传递和树突传播;更多形态学和/或生物物理学详细模型可以明确地模拟这些源的一些或全部延迟)以及短期和长期的可塑性被认为取决于突触前和突触后神经元,因此被封装在与上述“细胞类型”相反的“突触类型”的概念中。
PyNN中默认的突触连接类型是静态的,具有固定的突触权重。为了对动态突触进行建模,突触权重(以及可能的其他特性,如上升时间)取决于最近的突触后活动史和/或突触前活动的变化,我们使用与神经元相同的思想,命名模型在模拟器中具有相同的接口和行为,即使底层的实现可能会有很大的不同。
动态突触的方法不同于神经元的方法是我们尝试更大程度的组合性,即我们将模型分解成多个分量,例如短期和长期动力学,或时间依赖性和STDP规则的权重依赖,然后可以以不同方式组成。
这样做的好处是,如果我们有组件A的n个不同的模型和组件B的m个模型,那么我们只需要n + m模型而不是n×m,这在代码简单性和模型名称短。缺点是并不是所有的组合都可能存在,如果底层模拟器实现复合模型而不是自己使用组件:在这种情况下,PyNN检查一个给定的模拟器是否存在给定的复合模型AB,如果不存在,则引发异常。根据复合突触模型的经验,复合方法可能会扩展到未来PyNN接口版本的神经元模型。
目前在PyNN中只有一个模型存在于短期可塑性组分Tsodyks-Markram模型(Markram等,1998)。对于长期可塑性,有一个尖峰时间相关的可塑性STDP分量,它本身是由独立的时序依赖和重量依赖分量组成的。
低级程序接口
我们将程序界面称为“低级”,因为它涉及的是一个较低级别的抽象 - 个体神经元和个体突触 - 而不是面向对象的界面。过程接口由函数create(),connect(),set(),record()(用于记录尖峰)和record_v()(用于记录膜电位)组成。这些功能中的每一个对单个单元ID对象或这些对象的列表进行操作或返回。正如使用示例部分所述,以及作为参数传递,ID对象可以用于访问/修改单个神经元的参数,并使用上述的StandardCell机制来处理参数转换。
在一定程度上可以混合低级和高级接口。例如,可以访问Population中的单个神经元作为ID对象,然后使用connect()函数来连接它们,而不是使用Projection对象。
为什么同时拥有低级和高级界面?两者都是用户混淆的潜在来源,绝对是开发人员的维护负担。主要原因是支持使用PyNN作为移植工具。使用现有模拟器的大多数神经元网络模型使用程序方法,因此如果PyNN支持相同的方法,则向PyNN的转换更容易。另外,当为仿真器或神经形态硬件开发PyNN接口时,主要处理单个单元和突触连接,因为只能实现低级接口,所以更容易实现,因为高级接口可以建立在它上面。
高级的,面向对象的接口
面向对象程序设计作为一种降低程序复杂度的方法已经在计算机科学中使用了多年。由于计算神经科学的限制因素变成了程序员的生产力,而不是计算机的能力,所以随着大规模,生物详细的神经元网络建模的雄心和范围的增加,降低程序复杂性将变得越来越重要(Wilson, 2006)。正因为如此,PyNN开发新模型的首选接口是面向对象的接口。
面向对象的接口建立在三个主要的类上:
人口 - 所有具有相同细胞类型(模型类型)的一组细胞。通常认为,总体中的细胞应该全部代表相同的生物细胞类型,即虽然参数值可以在组中的细胞之间变化,但是所有细胞应当具有定性的相同的反应。这不是强制执行的,但是对于产生可理解的代码是一个很好的指导原则。人口类消除繁琐的迭代在神经元列表,并使神经元属性更有效的,基于数组的管理。
投影 - 两个人群之间给定突触类型的连接集合。创建投影需要指定突触前和突触后的种群,突触类型以及用于确定哪些神经元与哪些神经元连接的算法。
连接器 - 用于创建投影的连接算法的封装。这种算法的简单例子是“全部到全部”,“一对一”和“连接每个事件之前和之后的突触 - 细胞 - 固定概率”。也可以提供哪个单元将被连接到哪个单元的明确列表。每个算法都是在Connector类的子类中定义的。 PyNN包含许多这样的类,但用户定义自己的算法是相当简单的。
在PyNN的未来发展中,我们计划将界面扩展到更高层次的抽象,如图层,皮质柱,大脑区域和区域间预测。我们还打算使用高级界面作为扣人心弦的网络模型和不代表单个神经元的抽象模型(如平均场模型)之间的联系。
随机数字
中枢神经系统包含许多噪声源,活动模式往往足够复杂,可能是混沌的,使随机表示成为一个合理的模型。
当比较在不同模拟器上运行的给定模型的行为时,这可能成为问题,因为随机差异可能模糊模型的实现之间的实际不一致。同样,在并行计算机上执行分布式计算时,模型行为不应该取决于所使用的处理器的数量(Morrison等,2005),随机差异可以隐藏并行和串行实现之间的实际差异。
由于这些原因,能够在不同的仿真器中使用相同的随机数序列是重要的,并且在程序执行中的特定点处使用的随机数独立于它在哪个处理器上运行。
另一个考虑是大多数情况下的模拟只使用伪随机序列,低质量的随机数发生器(RNG)可能在序列的不同元素之间存在相关性,这可能会显着影响网络的定性行为。因此,有必要能够用不同的RNG测试模拟。
PyNN支持与模拟器无关的RNG,并使用不同的生成器 - 目前,可以使用numpy软件包或GNU Scientific Library(GSL)提供的任何生成器。
这是通过将numpy和GSL RNGs包装在具有通用接口的类中来完成的。 PyNN的随机模块包含NumpyRNG和GSLRNG类,它们都有一个方法,next(n,distribution,参数),它从带有参数参数的类型分布分布返回n个随机数。
由于所有使用随机数的PyNN代码只能通过next()方法访问RNG类,所以用户可以简单地用这种方法定义一个包装类来代替它们自己的RNG。
由于通常希望重复使用相同的随机分布,而不是每次改变分布,所以随机模块也提供RandomDistribution类,该类使用分布名称和参数初始化,然后简化next()方法 一个参数,从分布中抽取的值的数量,例如,
请注意,NumpyRNG和GSLRNG分布可能不具有相同的名称,例如 NumpyRNG的“正常”和GSLRNG的“高斯”,参数也可能不同。 我们未来的计划之一是扩展随机模块,以便跨RNG协调名称。
多分区模型
PyNN目前仅支持单个模拟器NEURON,它适用于多室模型。由于支持模拟器独立的原则仅适用于至少两个支持的模拟器共享的特性,并且PyNN专注于网络建模,PyNN不提供用于指定模拟器独立的多分区模型的API。这是一个可能的未来发展 - 在MOIN模拟器的一个PyNN接口上已经做了初步的工作(Ray和Bhalla,2008),但更可能的路径是使用NeuroML标准来指定多分区模型。在这种情况下,指定单个单元格类型的NeuroML 2级文件的文件名将作为单元类参数传递给PyNN create()函数或Population构造函数。
但是,由于本地和PyNN代码可以混合,pyNN.neuron模块已经支持多分区模型的模拟。可以使用Projection构造函数的源参数和目标参数指定的突触后机制来指定电压被注视以触发突触传递(例如,轴突终端)的突触前隔室。
调试
如果在PyNN模拟中出现错误,首先要在另一个模拟器的后端重新运行,特别是将问题的源头缩小到一个后端。 尽管如此,PyNN提供的附加抽象层有时使得追踪错误来源变得更加困难。 为了平衡这一点,PyNN捕捉来自模拟器核心的错误,并采用Python的内省功能来提供关于错误上下文的附加信息。 例如,如果向神经元模型提供了无效的参数名称,则错误消息会列出该模型的所有有效参数名称。 此外,可以通过pyNN.utility模块中的init_logging()函数来开启日志记录功能,以便详细了解系统正在写入文件的内容,这是追踪错误的宝贵资源。
实现
PyNN既是通用模拟器接口的定义,又是每个支持模拟器的接口实现。 PyNN被实现为一个Python包,其中包含一个通用模块,该模块定义了API,并包含所有模拟器后端通用的功能,随机模块(如上所述)以及每个模拟器后端的模块,如图3所示。 每个模拟器模块都分别实现了API,尽管它可以使用很多共享代码。 在大多数情况下,模拟器模块已经由模拟器开发者或与之密切合作实施。
图3. PyNN的体系结构
PyNN目前完全支持以下模拟器:NEURON(Carnevale和Hines,2006; Hines和Carnevale,1997; Hines等,2008),NEST(Eppler等,2008; Gewaltig和Diesmann,2007),PCSIM 和Brian(Goodman和Brette,2008)。 目前正在开发支持MOOSE(Ray和Bhalla,2008年)和以NeuroML格式出口(Crook等,2005年)。
PyNN也支持海德堡神经形态硬件系统(Schemmel et al。,2007)。 这说明了一个共同的神经元仿真接口存在的主要好处:新颖的仿真或仿真系统不需要开发他们自己的编程接口,但可以从现有的保证与现有工具的互操作性的现有益处。 使用PyNN作为神经形态硬件系统的接口提供了缩小数值模拟和物理仿真两个领域之间的差距的可能性,迄今为止,这两个领域已经相互独立
重复性的限制
对于具有给定参数集的给定模型,在给定模拟器的给定版本上运行,应该可以精确地再现模拟结果,而不依赖于计算机体系结构(除了影响浮点表示的精度的情况外)或者操作系统。对于并行系统,结果也应该与计算中使用多少个线程或进程无关,尽管这里精确的定量再现很难实现。如果指定了用于生成给定结果的精确版本,则给定仿真器的不同版本之间的重现性不是必需的,但是当然是非常可取的。在不同的模拟器上运行模型时,除了在简单的情况下,由于浮点计算中的舍入误差,无法实现准确的再现。因此,在通过在两个或多个仿真器上运行模型来验证模型实现时,可达到的重现性水平如何,我们如何判断是否有任何差异是由于舍入误差或实现错误?
为了初步处理这个问题,我们将两个模拟器之间的模型活动的差异与同一个模拟器的两个不同初始条件的差异进行了比较。
我们的测试案例是基于Vogels和Abbott(2005)的平衡随机网络,其实现如上所示。这个网络的活动模式对初始条件非常敏感(混沌或接近混沌),所以我们不能使用精确尖峰模式的差异来衡量重复性:我们更关心活动的统计特性,所以我们已经选择兴奋性神经元的刺激间期(ISI)的分布(见图2C)作为网络活动的量度。
为了测量来自两个不同运行的分布之间的差异,我们使用Kolmogorov-Smirnov双样本测试。我们运行了模拟十次,每次用不同的种子用于产生初始膜电位分布的RNG,同时使用NEURON和NEST后端。这给出了Kolmogorov-Smirnov D-统计量在0.008和0.026之间(n是19000)的平均值为0.015,相关联的p值(两个分布相同的概率)在6.3×10-5和0.68之间意味着0.15。
然后,我们在NEURON上运行20次模拟,每次使用不同的RNG种子,给出10对分布。在这种情况下,D值在0.007-0.026的范围内,平均值为0.015,在2.8×10-5至0.77的范围内的p值平均为0.20。
总而言之,由于不同模拟器的差异与由于不同的初始条件而产生的差异几乎完全相同,这表明模拟器之间的差异确实是由于四舍五入误差造成的,因此不存在任何实现错误在这种情况下。
值得注意的是,在大多数情况下,支持零假设,即分布是相同的,但是对于一些初始条件,ISI分布之间存在非常显着的差异。因此,在这种情况下,ISI分布可能不是重现性的最佳措施。
讨论
在本文中,我们介绍了PyNN,一个基于Python的通用模拟器接口,它允许模拟器无关的模型规范。 PyNN已经在许多研究小组中使用,并且一直是一个关键技术,使得泛欧合作项目中的实验室之间的沟通更加顺畅,并且成为建模和神经形态硬件开发的主要组成部分(FACETS项目:http:// www.facets-project.org)。
通过提供一个标准的模拟平台,PyNN也有可能成为其他仿真器不可知的基础,但是神经科学专用的工具,如分析,可视化和数据管理软件。
PyNN不是解决与模拟器无关的模型规范和模拟器互操作性的唯一项目(Cannon等,2007)。 neuroConstruct(Gleeson et al。,2007)是一种使用图形用户界面(GUI)开发形态细节神经元网络的工具,可以为NEURON和GENESIS模拟器生成代码。对PyNN的一个限制是,由于它使用的是代码生成而不是直接的界面,neuroConstruct不能从模拟器接收信息,除非通过读取生成的数据文件。第二个限制是通过GUI不可用的功能不能被包含在模型中。 NeuroML标准(Crook等人,2005,http://www.neuroml.org)旨在以模拟器独立的方式提供用于在组之间交换模型规范的基础结构。它们的范围包括更详细的建模级别,例如膜离子通道和详细的树突形态,比PyNN支持。与PyNN相比,它们具有独立于语言的优势,因为规范是用XML编写的,对于这些工具,所有主要编程语言都存在这些工具。纯声明性规范的主要缺点是缺乏灵活性:如果标准中没有定义一个概念或实体,就不可能指定使用它的模型,而使用程序性/命令性或混合的声明性 - 程序性规范,如用PyNN可以实现任意规格。
尽管我们在这里强调GUI,纯声明和编程接口方法与模拟器无关的模型规范之间的差异,事实上它们是高度互补的。图形界面对于初学者,教学,系统高层概述,以及集成分析和可视化工具特别有用。例如,除了NEURON和GENESIS的代码之外,neuroConstruct能够生成PyNN代码是非常有用的。声明性规范达到了最高级别的系统独立性,支持的概念范围。它们也特别适合转换成人类可读格式和自动生成GUI。因此,它们似乎最适合于建模方法相当稳定的领域,例如用于描述神经元形态或非随机离子通道模型。在PyNN中,我们计划使用NeuroML支持与模拟器无关的多分区模型:在这种情况下,将在NeuroML中指定单元模型,而PyNN将用于网络规范和模拟设置和控制。
PyNN未来发展的主要优先事项是增加支持的模拟器的数量(模拟器开发者如果对模拟器的PyNN支持感兴趣,请与我们联系),改进对多分区建模的支持,并将接口向更高水平的抽象,如皮质列和更抽象的建模方法。 PyNN是开源软件(CeCILL许可证,http://www.cecill.info),并有一个开放的开发模式:任何人谁愿意贡献是受欢迎的,并邀请这样做。
参考文献:https://www.frontiersin.org/articles/10.3389/neuro.11.011.2008/full