对应实验:projects/balanced_network.py
输出图片:outputs/project_balanced_network.png
前面的章节逐个学习了:
- NeuronGroup。
- PoissonInput。
- Synapses。
- 随机连接。
- 突触延迟。
- SpikeMonitor。
- PopulationRateMonitor。
现在把它们组合成一个小型循环网络。
“综合”不等于追求复杂。这个项目的目标是建立完整因果链:
外部随机输入
-> 神经元达到阈值
-> 兴奋/抑制脉冲在网络中传播
-> 网络活动反馈到自身
-> Monitor 记录个体与群体行为
兴奋性输入使突触后神经元更接近阈值。
抑制性输入使突触后神经元远离阈值。
只有兴奋性循环时,可能出现:
一个神经元放电
-> 推动更多神经元
-> 更多神经元继续推动网络
-> 活动快速爆发
抑制反馈可以限制这种正反馈,使网络保持在可持续活动范围。
“平衡”不表示任意时刻兴奋电流和抑制电流精确相等,也不表示 E/I 群体放电率必须完全相等。
更合理的理解是:
兴奋驱动与抑制反馈在统计和动力学上相互制约,使网络既不长期沉默,也不无限爆发。
代码:
N_E = 160
N_I = 40总数:
N = 200
兴奋性占 80%,抑制性占 20%。
这是许多教学网络常用的比例,粗略反映皮层中兴奋性神经元多于抑制性神经元的事实。
但它不是普适常数。不同脑区、细胞分类和实验定义会不同。
本项目主要使用这一比例来展示:
- 兴奋性连接更多。
- 单次抑制权重需要更强,才能形成制衡。
neurons = NeuronGroup(
N_E + N_I,
"dv/dt = -v/tau : 1",
...
)方程没有固定正驱动:
dv/dt = -v/tau
如果没有输入,v 会衰减到 0,网络最终沉默。
因此活动必须来自:
- 外部 PoissonInput。
- 网络内部兴奋性反馈。
抑制性反馈只会降低 v,不能独自启动网络。
excitatory = neurons[:N_E]
inhibitory = neurons[N_E:]两个子组共享:
- 同一神经元方程。
- 同一阈值和 reset。
- 同一 tau。
差别来自它们发出的突触作用:
- excitatory 的脉冲让
v_post += 0.06。 - inhibitory 的脉冲让
v_post -= 0.25。
这是一种极简分类:
神经元类型由输出突触符号定义,而不是由膜方程差异定义。
更真实模型可以让 E/I 神经元拥有不同:
- 时间常数。
- 阈值。
- 不应期。
- 适应机制。
neurons.v = "rand()"初始 v 在 0 到 1 之间。
部分神经元一开始接近阈值,更容易被早期外部输入触发。这可以:
- 打破完全同步。
- 缩短网络启动瞬态。
但初始随机状态不是持续活动来源。没有外部输入时,它们最终仍会衰减。
external = PoissonInput(
neurons,
"v",
N=100,
rate=12 * Hz,
weight=0.05,
)每个神经元接收 100 路、每路 12 Hz 的泊松输入。
每秒期望事件数:
100 * 12 = 1200 events/s
每次增加 0.05,因此未考虑漏衰减和 reset 时,输入总量尺度约:
1200 * 0.05 = 60 / second
在 20 ms 时间常数内,平均会有:
1200/s * 0.02s = 24 个事件
这给出外部驱动为何足以启动网络的直觉。
不能简单用 24*0.05=1.2 断言必然放电,因为:
- 事件时刻随机。
- v 同时指数衰减。
- 脉冲后 reset。
- 抑制事件会降低 v。
但它是检查参数量级是否合理的有用估算。
exc_synapses.connect(p=0.08)兴奋性源数量 160,目标数量 200。
可能连接数:
160 * 200 = 32000
每条以 8% 概率创建,期望连接数:
32000 * 0.08 = 2560
实际输出示例约为:
2596
随机结果围绕期望值波动是正常的。
抑制性源 40,目标 200:
40 * 200 = 8000 个可能连接
期望连接数:
8000 * 0.08 = 640
示例输出正好为 640 只是一次随机实现的结果,不代表每次都精确等于期望值。
兴奋事件:
v_post += 0.06抑制事件:
v_post -= 0.25单次抑制作用约为单次兴奋的:
0.25 / 0.06 ≈ 4.17 倍
因为:
- 兴奋性神经元数量是抑制性的 4 倍。
- 两类连接概率相同。
- 兴奋连接总数约为抑制连接的 4 倍。
使用更强的抑制单次作用,可以在总量尺度上形成制衡。
这只是粗略设计。真正的动态平衡还取决于:
- 两群放电率。
- 连接相关性。
- 延迟。
- reset 和不应期。
- 外部输入。
exc_synapses.delay = 1.5 * ms
inh_synapses.delay = 0.8 * ms抑制反馈更快到达。
直觉上:
- 兴奋活动开始增长。
- 抑制神经元被网络和外部输入激活。
- 较快抑制作用压制进一步增长。
延迟差可能影响:
- 同步。
- 振荡频率。
- 爆发持续时间。
- 网络稳定性。
本项目参数用于教学现象,不声称对应某个具体生物回路的测量值。
代码只写:
connect(p=0.08)没有排除 i == j 的条件。
因此在 source 和 target 指向同一底层神经元时,可能创建自连接。
若模型假设不允许自突触,应显式写连接条件,例如根据索引关系排除同一神经元。
网络结构中的默认行为必须主动检查,不能依赖“生物上一般不会这样”来猜测软件。
spikes = SpikeMonitor(neurons)
rate_e = PopulationRateMonitor(excitatory)
rate_i = PopulationRateMonitor(inhibitory)SpikeMonitor:
- 保留每个神经元身份。
- 用于栅格图。
- 用于计算每个神经元计数。
RateMonitor:
- 分别聚合 E/I 群体。
- 观察群体活动随时间的变化。
- 便于比较反馈时序。
一个全群 SpikeMonitor 可以通过索引区分 E/I,但单独 RateMonitor 让在线统计和绘图更直接。
兴奋性群体:
mean_rate_e = (
spikes.count[:N_E].sum()
/ N_E
/ (0.5 * second)
)顺序:
- 对 160 个兴奋性神经元的脉冲数求和。
- 除以 160,得到每个神经元平均脉冲数。
- 除以 0.5 秒,得到每秒脉冲数。
单位为 Hz。
若总脉冲数是 2866:
2866 / 160 / 0.5s
≈ 35.8 Hz
这与输出量级一致。
示例输出:
兴奋性群体平均放电率: 约 35.8 Hz
抑制性群体平均放电率: 约 34.4 Hz
两者接近是一个现象,但不能单独证明输入电流平衡。
原因:
- E 与 I 单次突触权重不同。
- 群体大小不同。
- 每个神经元接收的 E/I 连接数不同。
- 脉冲时间相关性不同。
验证动态平衡更直接的方法包括记录:
- 每个神经元接收的总兴奋事件。
- 总抑制事件。
- 分离的兴奋/抑制电流或电导。
- 净输入的均值和方差。
红线位于 N_E=160。
- 线下:兴奋性神经元。
- 线上:抑制性神经元。
观察:
- 是否持续活动。
- 是否出现整齐垂直同步条纹。
- 是否有长时间沉默或爆发。
- E/I 活动是否时间上相关。
E 和 I 两条曲线显示群体活动时间结构。
观察:
- 抑制活动是否跟随兴奋活动。
- 是否存在稳定振荡。
- 峰值是否过高。
- 是否逐渐沉默或发散。
- 几乎没有脉冲。
- 外部输入太弱或抑制太强。
- 大量神经元近乎同步放电。
- 兴奋反馈过强或抑制延迟过大。
- 脉冲持续存在。
- 个体时刻不完全同步。
- 群体率在一定范围波动。
本项目意图展示第三种状态,但严格判断需要更长仿真和统计分析。
为了保持可读性,本项目没有加入:
- 电导型突触。
- 不同 E/I 膜时间常数。
- 突触时间过程。
- 可塑性。
- 空间拓扑。
- 外部刺激任务。
- 多次随机重复。
- 稳态期剔除。
因此它是教学原型,不是可以直接用于生物结论的完整模型。
名称只是建模目标,需要通过输入分解和统计验证。
平衡涉及总突触作用,不只是两个群体的放电率。
它决定随机分布,实际数量会波动。
应多种子重复,报告活动率、同步指标和状态稳定性。
循环网络存在反馈,参数变化可能导致状态突然从稳定转为爆发。
只保留 PoissonInput,测量外部驱动单独造成的活动。
观察是否出现过度同步或爆发,然后再加入抑制。
测试 -0.1、-0.25、-0.5,画出 E/I 平均率与同步程度。
比较 p=0.02、0.08、0.2。每次记录实际连接数,不能只记录 p。
对 20 个种子统计:
- E 平均率。
- I 平均率。
- 总连接数。
- 脉冲计数变异。
加入连接条件,比较自连接是否影响结果。
把突触事件改为更新 ge 和 gi,让它们按不同时间常数衰减,再驱动 v。这样更接近突触电流过程。
这个网络的最小因果结构是:
外部泊松输入启动活动
兴奋性循环连接放大活动
抑制性连接限制活动
漏衰减与 reset 消散状态
延迟塑造反馈时序
Monitor 从个体和群体层面观察结果
真正理解项目的标准不是“代码能运行”,而是你能在修改任何参数前说明:
- 哪个机制被改变。
- 预期网络向沉默、稳定还是爆发移动。
- 需要用什么数据验证。