PyNest——part 2: populations of neurons
part 2: populations of neurons
introduction
在这篇讲义中,我们着眼于创建和参数化神经元批次,并将它们连接起来。 当你完成这些材料时,你会知道如何:
创建具有特定参数的神经元群体
在创建之前设置模型参数
用定制参数定义模型
随机参数创建后
在人群之间进行随机连接
设置设备以启动,停止并将数据保存到文件
重置模拟
creating parameterised populations of nodes
在前面的讲义中,我们介绍了函数Create(model,n = 1,params = None)。 它的强制参数是模型名称,它决定了要创建的节点的类型。 它的两个可选参数是n,它给出了要创建的节点数(默认值:1)和params,它是一个字典,给出了应该初始化节点的参数。 因此,创建一批相同参数化神经元的最基本方法是利用Create()的可选参数:
ndict = {"I_e": 200.0, "tau_m": 20.0}
neuronpop = nest.Create("iaf_psc_alpha", 100, params=ndict)
变量neuronpop是创建的神经元的所有id的列表。
在创建时对神经元进行参数化比在创建后使用SetStatus()更有效,所以请尽可能地做到这一点。
我们还可以在创建之前设置神经元模型的参数,这使得我们可以在许多情况下更简洁地定义模拟。 如果要生产许多单个批次的神经元,则设置模型的默认值会更方便,以便从该模型创建的所有神经元都将自动具有相同的参数。 可以使用GetDefaults(model)查询模型的默认值,并使用SetDefaults(model,params)进行设置,其中params是包含所需参数/值对的字典。 例如:
ndict = {"I_e": 200.0, "tau_m": 20.0}
nest.SetDefaults("iaf_psc_alpha", ndict)
neuronpop1 = nest.Create("iaf_psc_alpha", 100)
neuronpop2 = nest.Create("iaf_psc_alpha", 100)
neuronpop3 = nest.Create("iaf_psc_alpha", 100)
除了I_e和tau_m以外,所有参数的常用模型默认值都具有相同的参数,这三个参数具有字典ndict中指定的值。
如果批次的神经元应该是相同的模型,但使用不同的参数,则使用CopyModel(现有的,新的,参数=无)来自定义版本的神经元模型并使用其默认参数很方便。 此功能是帮助您编写更清晰的仿真脚本的有效工具,因为您可以使用模型的名称来指示它在模拟中扮演的角色。 使用SetDefaults()分两步设置您的自定义模型:
edict = {"I_e": 200.0, "tau_m": 20.0}
nest.CopyModel("iaf_psc_alpha", "exc_iaf_neuron")
nest.SetDefaults("exc_iaf_neuron", edict)
或者在一个步骤中:
idict = {"I_e": 300.0}
nest.CopyModel("iaf_psc_alpha", "inh_iaf_neuron", params=idict)
无论哪种方式,新定义的模型现在可以用于生成神经元种群,并且也将由函数Models()返回。
epop1 = nest.Create("exc_iaf_neuron", 100)
epop2 = nest.Create("exc_iaf_neuron", 100)
ipop1 = nest.Create("inh_iaf_neuron", 30)
ipop2 = nest.Create("inh_iaf_neuron", 30)
也可以创建具有不均匀参数集合的群体。 通常根据实验限制创建一组完整的参数,然后一次创建所有神经元。 为此,提供与创建的神经元(或突触)数量相同长度的字典列表:
parameter_list = [{"I_e": 200.0, "tau_m": 20.0}, {"I_e": 150.0, "tau_m": 30.0}]
epop3 = nest.Create("exc_iaf_neuron", 2, parameter_list)
setting parameters for populations of neurons
在创建之前或之前,并不总是可以为神经元模型设置所有参数。 一个典型的例子是,当一些参数应该从随机分布中抽取。 当然,总是可以对群体进行循环并设置每个人的状态:
Vth=-55.
Vrest=-70.
for neuron in epop1:
nest.SetStatus([neuron], {"V_m": Vrest+(Vth-Vrest)*numpy.random.rand()})
但是,SetStatus()需要一个节点列表,并且可以为每个节点设置参数,这样更有效,因此是首选。 一种方法是给出一个字典列表,其长度与要参数化的节点数量相同,例如使用列表理解:
dVms = [{"V_m": Vrest+(Vth-Vrest)*numpy.random.rand()} for x in epop1]
nest.SetStatus(epop1, dVms)
如果我们只需要随机选择一个参数,那么通过传入参数的名称和所需值的列表就可以得到更简洁的方式。 再一次,列表必须与要参数化的节点数量相同:
Vms = Vrest+(Vth-Vrest)*numpy.random.rand(len(epop1))
nest.SetStatus(epop1, "V_m", Vms)
请注意,我们在这里随机数字相当宽松。 真的,我们必须更加小心,特别是如果我们使用多个线程或分布在多台机器上。 我们稍后会担心这一点。
generating populations of neurons with deterministic connections
在前面的讲义中,两个神经元使用突触规范进行连接。 在本节中,我们将这个例子扩展到每个十个神经元的两个群体。
import pylab
import nest
pop1 = nest.Create("iaf_neuron", 10)
nest.SetStatus(pop1, {"I_e": 376.0})
pop2 = nest.Create("iaf_neuron", 10)
multimeter = nest.Create("multimeter", 10)
nest.SetStatus(multimeter, {"withtime":True, "record_from":["V_m"]})
如果未指定连接模式,则通过默认规则(即all_to_all)连接总体。 pop1的每个神经元连接到pop2中的每个神经元,导致102个连接。
nest.Connect(pop1, pop2, syn_spec={"weight":20.0})
或者,神经元可以与one_to_one连接。 这意味着pop1中的第一个神经元连接到pop2中的第一个神经元,第二个神经元连接到第二个神经元等,总共创建了10个连接。
nest.Connect(pop1, pop2, "one_to_one", syn_spec={"weight":20.0, "delay":1.0})
最后,multimeters使用默认规则连接
nest.Connect(multimeter, pop2)
这里我们只使用了非常简单的连接方案。 必须在包含关键规则和与规则关联的参数的关键字的字典中定义需要指定其他参数(例如入度或连接概率)的连接模式。 请参阅连接管理了解连接使用说明。
connecting populations with random connections
在前面的讲义中,我们考察了连接模式one_to_one和all_to_all。 但是,我们通常希望看到网络的连通性要比所有人都要稀疏。 这里我们介绍四种连接模式,它们在两个神经元群体之间产生随机连接。
连接规则fixed_indegree允许我们为目标人群中的每个神经元创建n个随机连接,将其从源头群体中随机选择的神经元前置。 可以不指定变量权重和延迟,在这种情况下使用默认权重和延迟。 或者,我们可以在syn_spec中设置它们,因此每个创建的连接具有相同的权重和延迟。 这里是一个例子:
d = 1.0
Je = 2.0
Ke = 20
Ji = -4.0
Ki = 12
conn_dict_ex = {"rule": "fixed_indegree", "indegree": Ke}
conn_dict_in = {"rule": "fixed_indegree", "indegree": Ki}
syn_dict_ex = {"delay": d, "weight": Je}
syn_dict_in = {"delay": d, "weight": Ji}
nest.Connect(epop1, ipop1, conn_dict_ex, syn_dict_ex)
nest.Connect(ipop1, epop1, conn_dict_in, syn_dict_in)
现在目标群体ipop1中的每个神经元具有从源群体epop1选择的具有权重Je和延迟d的Ke传入随机连接,并且目标群体epop1中的每个神经元具有从源群体ipop1选择的具有权重Ji和延迟的Ki传入随机连接d。
连接规则fixed_outdegree以类似的方式工作,其中n个连接(关键字outdegree)从目标人口岗位中随机选择来源群体中的每个神经元前。 出于效率的原因,特别是以分布式模拟时,如果可能的话最好使用fixed_indegree。
可用的另一个连接模式是fixed_total_number。 这里n个连接(关键字N)是通过随机从人群中的源头神经元和人群中的神经元群体创建的。
在选择连通性规则时,pairwise_bernoulli连接通过遍历所有可能的源 - 目标对并使用概率p(关键字p)创建每个连接来生成。
除规则特定参数indegree,outdegree,N和p外,conn_spec可以包含关键字autapses和multapses(设置为False或True),分别允许或禁止两个神经元之间的自连接和多连接。
请注意,对于所有连接规则而言,在前后角色中同时拥有相同的人口是完全合法的。
有关连接神经元的更多信息,请阅读连接功能的文档,并参阅连接管理中的指南。
specifying the behaviour of devices
所有设备都实现基本的计时能力; 参数start(默认值0)决定设备的活动开始和参数stop(默认:∞)结束。 这些值取决于原点的值(默认值:0)。 例如,下面的示例创建一个仅在100到150毫秒之间激活的poisson_generator:
pg = nest.Create("poisson_generator")
nest.SetStatus(pg, {"start": 100.0, "stop": 150.0})
此功能对于设置具有在特定时间开始和停止的刺激的实验协议很有用。
到目前为止,我们通过提取事件的值直接访问设备记录的数据。 但是,对于较大或较长的模拟,我们可能更愿意将数据写入文件以供日后分析。 所有记录设备都允许通过参数to_memory(默认值:True),to_file(默认值:False)和to_screen(默认值:False)指定数据的存储位置。 以下代码设置万用表以将数据记录到指定文件中:
recdict = {"to_memory" : False, "to_file" : True, "label" : "epop_mp"}
mm1 = nest.Create("multimeter", params=recdict)
如果使用label参数未指定文件的名称,则NEST将使用设备的名称及其ID来生成它自己的名称。 如果仿真是多线程或分布式的,则会创建多个文件,每个进程和/或线程一个文件。 有关如何自定义录制设备的行为和输出格式的更多信息,请阅读RecordingDevice的文档。
resetting simulations
我们经常会发生需要重置模拟的情况。例如,如果您正在开发脚本,那么您可能需要多次从ipython控制台运行它,然后才能对其行为感到满意。在这种情况下,使用函数ResetKernel()会很有用。这会摆脱您创建的所有节点,您创建的任何自定义模型,并将内部时钟重置为0。
重置的另一个主要用途是当您需要在循环中运行模拟时,例如测试不同的参数设置。在这种情况下,通常不需要丢弃整个网络并创建并连接所有的设备,只需重新设置网络即可。一个好的策略是在环路外创建并连接网络,然后在环路内执行参数化,模拟和数据收集步骤。在每次循环迭代中调用函数ResetNetwork()通常很有帮助。它将所有节点重置为其默认配置,并擦除记录设备中的数据。
command overview
这些是我们为这个讲义中的例子介绍的新功能。
Getting and setting basic settings and parameters of NEST
获取模拟内核的参数。返回:
- 参数字典如果调用没有参数
- 如果使用单个参数名称调用单个参数值
- 如果使用参数名称列表调用参数值列表
- 设置模拟内核的参数。
Models
用字符串指定给定模型的默认参数返回字典。
将给定模型的默认参数设置为在params字典中指定的值。
CopyModel(existing, new, params=None)
:通过复制现有模型来创建新模型。 默认参数可以作为参数给出,或者从现有参数中获取。
Simulation control
重置模拟内核。 这将破坏网络以及使用CopyModel()创建的所有自定义模型。 内置模型的参数被重置为默认值。 调用此函数相当于重新启动NEST。
将所有节点和连接重置为其各自型号的默认值。