资讯动态

MATLAB实现二维连续吸引子神经网络:从活动斑模拟到参数调优

发布时间:2026/9/6 20:06:21 来源:尧图企业网站定制
简介面向具备一定编程基础、对连续吸引子神经网络感兴趣的科研人员和学生资源系统讲解二维连续吸引子神经网络2D-CANN的仿真实现与动态特性分析。内容覆盖50×50神经元网络的循环连接设计、基于电导的膜电位计算、阈值线性发放率转换以及高斯型兴奋性连接与全局均匀抑制的实现方式Python代码采用类封装形式包含参数初始化、连接权重生成、电导计算、膜电位更新等模块。通过完整代码演示读者可深入探索兴奋性连接幅度、抑制强度、外部输入强度等参数对活动斑大小的影响并观察外部输入位置改变时活动斑的迁移过程理解移动速度的非均匀性现象及其形成原因。资源仅含一个PDF文档大小456KB内含详细代码注释和逐步分析便于读者结合理论调试修改获得更丰富的实验结果。目前已有一百余人学习下载适合作为理解CANN工作原理及空间定位动态行为的实用资料。 做空间记忆和路径积分类仿真时二维连续吸引子神经网络2D-CANN是我一直在用的一个基础框架。它能在二维神经元平面上自发形成局部高活动区也就是所谓的“活动斑”activity bump并通过侧向连接让这个斑稳定下来、随外部输入平滑移动。这种特性让CANN天然适合用来编码连续空间位置神经科学里的位置细胞、网格细胞模型里经常能见到它的影子做机器人导航、连续状态记忆的人也常拿它当底层模块。这篇博文我会从模型方程出发把MATLAB实现完整拆开讲清楚包含可直接复现的全部代码和逐行解释并重点分析时间常数、兴奋/抑制强度、核宽度、外部输入幅度这几个关键参数对活动斑形态和动态行为的影响。适合三类人看一是刚接触计算神经科学、想搭一个可运行的CANN模型的同学二是想用连续吸引子做二维状态编码的工程人员三是需要用MATLAB快速验证理论结果的科研党。下面直接进入正题。1. 模型设计与实现思路1.1 二维连续吸引子神经网络在做什么先从物理图像说起。一个二维CANN网络可以想象成一块二维的神经元矩阵每个神经元有自己的膜电位 (u(x,y))。神经元之间通过递归连接互相影响连接强度只取决于两个神经元之间的相对位置即具有平移不变性。这种连接权重通常取墨西哥帽Mexican Hat形状相邻神经元互相兴奋稍远一点的神经元互相抑制更远的又回到零。这个结构是活动斑能够形成的关键——局部兴奋撑起一个活动高峰周围抑制则确保不会全网络疯涨最终整个网络收敛到一个局部、稳定、有界的活动分布。有了这个结构网络就能完成一件非常酷的事把连续空间坐标“写”进群体活动里。比如你在二维平面上某个位置给一个输入刺激网络会在这个位置形成一个活动斑当你移动刺激活动斑会跟着走当刺激撤掉在合适的参数下这个斑还能在原位保持下来相当于把位置记住了。这就是连续吸引子流形的核心思想网络状态流形上有一整片中性稳定的平衡点每个平衡点对应一个空间位置。1.2 为什么能用二维卷积实现很多初学者第一次看到CANN的方程会想这不就是一个大矩阵迭代吗确实如果把N×N个神经元展开成一维向量连接权重就是一个N²×N²的大矩阵乘一次就是万亿次运算。但注意到权重只依赖神经元之间的位移也就是具有平移不变性数学上这就是标准的二维卷积运算。所以实现时可以绕开巨型矩阵直接利用卷积定理[ \sum_{x,y} W(x-x,y-y), r(x,y) \mathcal{F}^{-1}\left{ \mathcal{F}{W} \cdot \mathcal{F}{r} \right} ]在MATLAB里这对应ifft2(fft2(r).*fft2(ifftshift(W)))。这样做有几个直接好处第一时间复杂度从 (O(N^4)) 降到 (O(N^2 \log N))N64时差距已经达到几百倍N128时如果不这样做内存直接爆炸因为64×64×64×64的double矩阵要128MBN128则要2GB以上第二代码量大幅减少逻辑更清晰第三W只需要保存一个N×N大小的卷积核后续做参数扫描时内存压力很小。1.3 从连续微分方程到可迭代的差分格式CANN的连续时间动力学方程很简洁[ \tau \frac{du(x,y,t)}{dt} -u(x,y,t)\iint W(x-x,y-y), r(x,y,t), dxdyI_{\text{ext}}(x,y,t) ]这里的 (r(x,y,t) \max(u(x,y,t), 0)) 是神经元的发放率通常用ReLU截断来模拟“只有膜电位越过阈值才放电”的生物特性。第一项 ( -u ) 是泄漏项表示膜电位按指数衰减第二项是递归输入来自其他神经元的加权放电第三项是外部输入可以是我们人为加的高斯刺激或其他信号。离散化直接用欧拉法[ u^{t1} u^{t} \frac{dt}{\tau}\left( -u^{t} W * r^{t} I_{\text{ext}} \right) ]只要步长 (dt) 远小于时间常数 (\tau)这个差分格式就足够稳定。实际中用 (dt0.01)、(\tau1) 是一个很稳的起点后面调参时若出现振荡或发散优先缩小dt。2. 完整MATLAB代码与逐段讲解2.1 参数初始化先把模型的可调旋钮定好这段代码是模型参数的定义。网格规模N决定空间分辨率N越大能编码的位置越精细但计算量也越大。我通常先跑N64验证结果后再上N128。clear; close all; clc; % 网络规模 N 64; % 二维网格边长神经元总数 N*N x linspace(-1, 1, N); % 空间坐标范围归一化到[-1,1] [Y, X] meshgrid(x, x); % 时间参数 tau 1.0; % 膜电位时间常数 dt 0.01; % 欧拉法步长 T 50; % 总仿真时间 % 递归连接核参数墨西哥帽 A 1.0; a 0.5; % 兴奋核幅度、宽度 B 0.5; b 1.0; % 抑制核幅度、宽度 W A*exp(-(X.^2 Y.^2)/(2*a^2)) ... - B*exp(-(X.^2 Y.^2)/(2*b^2)); % 将连接核直流分量清零避免全局暴发且有助于活动斑自持 W W - mean(W(:)); % 外部输入参数 I0 0.8; % 输入强度 sigmaI 0.15; % 输入高斯宽度 cx0 -0.3; cy0 -0.2; % 初始刺激中心位置 % 初始状态 u 0.01 * randn(N, N); % 小随机噪声启动 r max(u, 0);这里的核心是墨西哥帽权重 (W)。兴奋核的宽度a决定活动斑主体有多宽抑制核的宽度b决定周围抑制的范围强度比A/B则直接决定网络会不会产生斑、斑的稳定性如何。做完之后减掉均值是很有用的技巧相当于把连接核的零频分量归零这样既不会出现全网络整体兴奋的失控状态又能在局部维持住活动斑。很多教科书代码不写这一行结果一跑就遇到要么全亮要么全灭的问题。2.2 通过FFT把卷积核准备好这里必须强调一个坑直接用fft2(W)是不对的。MATLAB的FFT默认原点在数组的左上角而我们定义的W峰值在网格中心必须先用ifftshift把中心移动到左上角再做FFT这样卷积结果才和空间坐标对齐。否则你辛辛苦苦算出来的活动斑会整体平移半个网格甚至直接跑到边界对面去。% 将W变换到频域后续每次迭代直接用 Wh fft2(ifftshift(W));这段逻辑虽然只有一行但它是整个FFT卷积实现正确性的命门。我见过不少同学在这行上踩坑要么忘了ifftshift要么用成fftshift结果活动斑的位置怎么都对不上。2.3 主循环欧拉法更新神经元活动主循环是整个仿真的引擎。每一小步都做三件事用当前发放率r和频域核Wh做卷积得到递归输入用欧拉法更新膜电位u用ReLU计算新的发放率r。% 记录活动斑质心位置 pos_record zeros(round(T/dt), 2); iter 0; for t 0:dt:T iter iter 1; % 递归输入卷积 逆变换 conv_u real(ifft2(fft2(r) .* Wh)); conv_u max(conv_u, 0); % 有时数值误差会产生负值截断一下 % 外部输入构造一个高斯刺激 Iext I0 * exp(-((X-cx0).^2 (Y-cy0).^2)/(2*sigmaI^2)); % 欧拉法更新 u u (dt/tau) * (-u conv_u Iext); r max(u, 0); % 记录活动斑质心 s sum(r(:)); if s 0 pos_record(iter, 1) sum(sum(r .* X)) / s; pos_record(iter, 2) sum(sum(r .* Y)) / s; end % 每隔一段时间画一次图 if mod(iter, 200) 0 figure(1); surf(X, Y, r, EdgeColor, none); view(2); colormap(jet); colorbar; axis tight; caxis([0 max(r(:))]); title(sprintf(t%.1f, t)); drawnow; end end这个循环里我习惯顺手记录活动斑的“质心”也就是以发放率为权重的空间平均位置。这个量在后面的参数影响分析和动态分析里非常有用可以直接量化活动斑跟随输入的精度和延迟。画图部分每200步刷新一次既能看到演化过程又不会因为频繁drawnow把运行速度拖垮。2.4 结果可视化看活动斑长什么样仿真结束后我一般会输出三个东西最终活动分布俯视图、活动斑峰值和质心的变化曲线、以及最终的连接核形状。这些可以帮我们快速判断网络是否真的形成了稳定单斑。% 最终活动分布 figure(2); surf(X, Y, r, EdgeColor, none); view(2); colormap(hot); colorbar; axis tight; caxis([0 max(r(:))]); title(Final activity bump); % 活动斑质心位置变化 tt 0:dt:T; figure(3); plot(tt, pos_record(:,1), b, LineWidth, 1.5); hold on; plot(tt, pos_record(:,2), r, LineWidth, 1.5); xlabel(Time); ylabel(Bump centroid); legend(x,y); grid on;运行这段代码正常情况下你会看到随机小噪声很快被组织成一个高斯帽状的活动斑质心稳定在输入中心附近。3. 关键参数影响分析3.1 时间常数 tau直接决定动态响应速度时间常数 (\tau) 是控制网络动态响应速度的旋钮。(\tau) 越小膜电位跟随输入越快活动斑形成越快移动时对刺激的追踪也越灵敏(\tau) 越大系统响应越迟缓活动斑像是“拖着”一个尾巴在追输入位置。从微分方程看(\tau) 只出现在一阶导数项前面相当于控制了系统时间尺度的比例因子。实际仿真时(\tau) 还会和步长 dt 耦合dt必须远小于(\tau)否则欧拉法会发散。我常用的搭配是 (dt \tau/100)。比如 (\tau1) 时用dt0.01(\tau5) 时建议把dt放大到0.05这样既保证稳定又不会白白浪费算力。在位置追踪任务中(\tau) 决定了系统的“惯性”输入中心突然跳变时活动斑质心会按指数方式趋近新位置时间常数就是指数逼近的特征时间。3.2 兴奋/抑制核的强度比A/B的比值是整个模型最敏感的参数它决定网络最终是否会产生稳定的活动斑。我做过一组典型扫描A/B 比值典型现象原因远大于1活动斑过强甚至出现全局振荡局部兴奋太强抑制压不住约2:1稳定的单活动斑兴奋-抑制平衡吸引子状态稳定接近1活动斑很弱容易被噪声扰动正反馈刚好够但不强小于1网络全部静默无法形成斑抑制占主导任何局部活动都被压灭这里建议以A1.0、B0.5为起点做小范围扫描。调试时若发现运行结果不对先别急着调其他参数把A/B比值拉回到2:1附近再看。经验上CANN的活动斑稳定性对这个比值异常敏感微调5%都可能让结果从“稳定单斑”变成“双斑”或“全灭”。3.3 核宽度 a 和 b决定活动斑的尺寸与空间范围兴奋核宽度a决定了活动斑的半径下限a越大活动斑越宽、峰值越低抑制核宽度b决定了周围抑制的作用范围。正常情况下应保持 b a也就是兴奋局部化、抑制全局化的墨西哥帽结构否则会出现奇怪的行为。一个值得注意的现象是当b过小时抑制范围太窄无法压制离活动斑稍远的区域网络容易出现在多个位置同时长出斑的情况当b过大时抑制范围太广活动斑周围的抑制作用过强可能导致斑的“肩膀”被削平边界变得很陡甚至因为数值原因出现轻微振荡。实际调参时我习惯先固定 b/a ≈ 2再逐步加宽观察活动斑形态变化。活动斑宽度与a的平方根大致相关想精细控制斑的编码精度优先调a而不是A。3.4 外部输入幅度阈值效应与输入强度轴外部输入强度I0也存在一个明显的阈值现象。I0太低时局部输入不足以克服递归抑制和泄漏项网络无法激活活动斑根本形成不了I0越过阈值后活动斑突然出现且峰值随输入强度快速上升当I0继续增加到某个更高的值可能会在输入中心附近引发局部振荡。更微妙的是外部输入的宽度sigmaI也会影响行为。输入比活动斑窄时网络的活动斑主要由递归连接决定输入只是“点火”作用输入比活动斑宽时活动斑形态更像输入形状的复制递归连接的作用被稀释。使用这个模型时搞清楚你的目的是“用输入驱动网络状态”还是“用网络状态保持输入”会直接影响你该选哪一套参数。4. 活动斑动态观察4.1 从噪声到稳定活动斑的自组织过程最基础也最直观的实验是从一个随机小噪声初始状态出发观察网络如何自组织出一个规则的活动斑。整个过程可以分为三个阶段最初几十毫秒内噪声被墨西哥帽核的空间滤波作用“整理”局部高活动区域迅速生长随后兴奋-抑制竞争把活动逐步收拢最后形成一个形状稳定、位置固定的高斯状活动斑。这一步看似简单却直接验证模型是否处于正确的参数区间。如果噪声散掉、没有任何聚集说明抑制太强或输入不够如果噪声长成多个分散的斑说明侧抑制范围不足或兴奋过强。这个过程可以当成模型的“体检”每次改完参数先跑一遍初始自发组织确认能形成干净的单斑再去做更复杂的动态实验。4.2 位置追踪连续吸引子的核心能力我加了一个移动输入的实验让外部输入的中心按一条L形轨迹移动比如先沿x方向、再沿y方向看活动斑会不会跟着走。这是CANN最吸引人的特性——活动斑在二维平面上的位置就是对空间坐标的神经编码输入移动到哪斑就跟到哪。运行结果通常显示在输入移动较慢时活动斑质心几乎无延迟地紧跟输入中心输入移动加快后质心轨迹会落后一段距离这个滞后量大致由时间常数 (\tau) 决定。这个性质在工程上极其重要如果你想用CANN做连续运动轨迹的编码或预测时间常数必须和输入变化速度匹配否则预测会有不可忽略的相位延迟。4.3 多输入与合并行为最后一个有意思的实验是给两个高斯输入观察活动斑的竞争行为。两个输入靠得很近时由于递归兴奋的“融合”作用两个刺激最终合并成一个活动斑相当于把两个位置信息压缩成一个两个输入离得远时抑制连接会相互压制最终往往只有一个斑存活这是典型的赢者通吃winner-take-all现象。这个行为在视觉注意、目标选择、决策等任务里非常关键。CANN不会把多峰信息全部保留而是倾向于收敛到流形上的单一状态。如果你需要编码多个位置比如多目标同时追踪得考虑并行多模块方案或者改用其他类型的吸引子网络。模拟时可以通过调整抑制核宽度b来控制两个刺激的融合距离阈值距离阈值大致正比于b。5. 常见问题与调参避坑5.1 仿真发散或出现NaN最常见的原因是dt过大。欧拉法是显式格式稳定性条件要求 (dt/\tau) 足够小同时卷积核的幅值不能太大。我建议先用 (dt \tau/100) 起步若仍发散把兴奋核A降到0.8左右再试。还有一种隐蔽原因fft2(r) .* Wh中Wh的虚部累积误差导致逆变换出现负值和NaN所以每次卷积后我都习惯用real()加上max(...,0)做双重保险。5.2 活动消失或者全网络暴发活动斑消失通常意味着抑制过强或者输入不够建议把A/B比值调大或者提高I0。全网络暴发则相反通常是抑制不足把B稍微调大一点。这里有个快捷判断方法看W减均值后的最大值。如果最大值为正但很小说明网络增益普遍不足活动很难维持如果最大值超过1.5倍抑制强度很容易出现暴发。手动调参时可以打印这个数作为参考指标。5.3 FFT卷积的边界伪影FFT卷积隐含周期边界条件这既是优点也是坑。活动斑靠近边界时一部分会被“绕”到对面去看起来像斑被撕开了。对于空间记忆这类任务周期边界有时反而是合理假设比如方向调谐模型但如果你的任务是开放空间、边界不可穿越可以考虑改用conv2(W, r, same)实现零填充边界代价是每次迭代的耗时从O(N²logN)变成O(N²·M²)核边长M不算大时依然可接受。另一种更干净的方案是把网格扩大一倍让活动斑远离边界仿真结束后再裁剪。5.4 参数批量扫描的小技巧参数扫描时我习惯把模型主体封装成一个函数输入是一组参数输出是活动斑的质心轨迹、峰值时间序列和最终活动图。然后用一个两层循环批量跑不同参数组合把所有结果保存成结构体数组。这样整理相图、画参数平面示意图都非常方便。如果参数组合数量大还可以把外层循环改成parforMATLAB并行池一开扫描效率能提升一个量级。最后再分享一个我自己的使用习惯做任何CANN实验前先花10分钟跑一遍“无外部输入、从噪声初始化”的自组织测试。这能帮你快速确认当前参数下网络自身就能形成干净的单一活动斑而不是靠外部输入硬撑出来的假象。很多看似诡异的结果追根到底都是这一步没做好后续分析全建立在不可靠的基础上。先把模型本身调老实了再叠加各种输入问题排查会省太多力气。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价