news 2026/9/6 20:06:19

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MATLAB实现二维连续吸引子神经网络:从活动斑模拟到参数调优

简介:面向具备一定编程基础、对连续吸引子神经网络感兴趣的科研人员和学生,资源系统讲解二维连续吸引子神经网络(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)),N=64时差距已经达到几百倍,N=128时如果不这样做内存直接爆炸,因为64×64×64×64的double矩阵要128MB,N=128则要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), dx'dy'
  • I_{\text{ext}}(x,y,t) ]

这里的 (r(x,y,t) = \max(u(x,y,t), 0)) 是神经元的发放率,通常用ReLU截断来模拟“只有膜电位越过阈值才放电”的生物特性。第一项 ( -u ) 是泄漏项,表示膜电位按指数衰减;第二项是递归输入,来自其他神经元的加权放电;第三项是外部输入,可以是我们人为加的高斯刺激或其他信号。

离散化直接用欧拉法:

[ u^{t+1} = u^{t} + \frac{dt}{\tau}\left( -u^{t} + W * r^{t} + I_{\text{ext}} \right) ]

只要步长 (dt) 远小于时间常数 (\tau),这个差分格式就足够稳定。实际中用 (dt=0.01)、(\tau=1) 是一个很稳的起点,后面调参时若出现振荡或发散,优先缩小dt。

2. 完整MATLAB代码与逐段讲解

2.1 参数初始化:先把模型的可调旋钮定好

这段代码是模型参数的定义。网格规模N决定空间分辨率,N越大能编码的位置越精细,但计算量也越大。我通常先跑N=64,验证结果后再上N=128。

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)。比如 (\tau=1) 时用dt=0.01,(\tau=5) 时建议把dt放大到0.05,这样既保证稳定又不会白白浪费算力。在位置追踪任务中,(\tau) 决定了系统的“惯性”:输入中心突然跳变时,活动斑质心会按指数方式趋近新位置,时间常数就是指数逼近的特征时间。

3.2 兴奋/抑制核的强度比

A/B的比值是整个模型最敏感的参数,它决定网络最终是否会产生稳定的活动斑。我做过一组典型扫描:

A/B 比值典型现象原因
远大于1活动斑过强,甚至出现全局振荡局部兴奋太强,抑制压不住
约2:1稳定的单活动斑兴奋-抑制平衡,吸引子状态稳定
接近1活动斑很弱,容易被噪声扰动正反馈刚好够,但不强
小于1网络全部静默,无法形成斑抑制占主导,任何局部活动都被压灭

这里建议以A=1.0、B=0.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 参数批量扫描的小技巧

参数扫描时,我习惯把模型主体封装成一个函数,输入是一组参数,输出是活动斑的质心轨迹、峰值时间序列和最终活动图。然后用一个两层循环批量跑不同参数组合,把所有结果保存成结构体数组。这样整理相图、画参数平面示意图都非常方便。如果参数组合数量大,还可以把外层循环改成parfor,MATLAB并行池一开,扫描效率能提升一个量级。

最后再分享一个我自己的使用习惯:做任何CANN实验前,先花10分钟跑一遍“无外部输入、从噪声初始化”的自组织测试。这能帮你快速确认当前参数下网络自身就能形成干净的单一活动斑,而不是靠外部输入硬撑出来的假象。很多看似诡异的结果,追根到底都是这一步没做好,后续分析全建立在不可靠的基础上。先把模型本身调老实了,再叠加各种输入,问题排查会省太多力气。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/6 20:05:06

互换性公差与测量基础核心解析:从习题答案到工程公差手感

简介:《互换性公差与测量基础(第四版)》配套习题答案以PDF形式整理,面向机械设计制造及其自动化、机电一体化等专业学生,以及备考阶段需要刷题自测的读者。答案覆盖教材第一至第十一章习题,包含互换性定义与…

作者头像 李华
网站建设 2026/9/6 20:04:50

数据治理整体规划汇报56页PPT实战拆解:从现状诊断到实施路径

简介:这是一份以数据治理整体规划为主题的PPT汇报材料,目标读者为企业信息化、数据管理及数字化转型相关岗位人员。内容围绕数据治理建设诉求、体系构建、交付成果、实施方法四个模块展开,借助DCMM数据管理能力成熟度模型,系统梳理…

作者头像 李华
网站建设 2026/9/6 20:04:24

Cap安装教程:macOS与Windows录屏软件一步上手

Cap安装教程:macOS与Windows录屏软件一步上手 【免费下载链接】Cap Open source Loom alternative. Beautiful, shareable screen recordings. 项目地址: https://gitcode.com/GitHub_Trending/cap1/Cap 你刚讲完一轮产品演示,想把关键几步操作录…

作者头像 李华
网站建设 2026/9/6 20:03:58

74HC138 3-8译码器全解析:从原理到设计报告实战

简介:基于74HC138芯片的3-8译码器设计报告,完整覆盖数字集成电路课程设计全流程,面向电子工程、微电子专业学生及硬件设计入门者。报告从功能分析与逻辑设计出发,明确驱动10个LSTTL电路、VDD3.3V下VOH3V、VOL0.3V,以及…

作者头像 李华
网站建设 2026/9/6 20:00:10

Buzz 转录错误排查:定位高频问题根因并修复的指南

Buzz 转录错误排查:定位高频问题根因并修复的指南 【免费下载链接】buzz Buzz transcribes and translates audio offline on your personal computer. Powered by OpenAIs Whisper. 项目地址: https://gitcode.com/GitHub_Trending/buz/buzz Buzz 是一款在本…

作者头像 李华
网站建设 2026/9/6 20:00:06

西门子MTP触摸屏U盘下载全流程:从博途导出到现场装载避坑指南

简介:面向工业自动化领域的电气工程师、技术支持与现场调试人员,这份资料围绕西门子Unified触摸屏(MTP)通过U盘下载程序的典型场景,提供了一份步骤清晰、可直接对照执行的操作文档。内容具体涵盖U盘FAT32格式化与容量不…

作者头像 李华