神经网络为何自带“分工”?模组化机制与实验解读
神经网络内部并不是一团浆糊。这句话是我们这篇论文最想传达的第一直觉。过去几年里我训练过不少网络从最普通的全连接前馈网络、卷积神经网络到带记忆的LSTM再到一些混合结构比如小波Elman网络每次训练完之后我都喜欢把权重矩阵拉出来看一看。看得多了就会发现一个很普遍的现象网络并没有把信息均匀地摊在每个神经元上而是自然而然地长出了一块一块的分工区域——某些神经元专精一类特征某些连接通路承担一个子任务彼此之间耦合很少像公司里按项目组划分的部门。这种结构我们叫它模组化。这次我们把围绕这个现象的一系列实验和理论分析整理成论文发表在Nature Machine Intelligence上。文章要回答的问题就是标题那句话神经网络为什么会呈现模组化模组化到底是训练过程中顺带的副产品还是任务本身逼出来的必然选择搞清楚这个问题往小了说能帮我们设计更省参数的模型往大了说关系到我们对深度学习黑箱的理解。这篇文章适合正在训练神经网络、被结构不可解释困扰的人也适合对神经科学和人工智能交叉感兴趣的朋友。我会把论文背后那些没写进正文的思考、实验设计时的取舍、以及复现这类实验最容易踩的坑一起倒出来。1. 神经网络模组化我们到底在讨论什么1.1 从一次意外的实验说起事情起因于一个很不起眼的实验。当时我在做一个多人脸识别图像分类任务模型用的是很普通的卷积神经网络输入是一张112×112的彩色人脸图像经过若干卷积层、池化层之后最后接全连接层输出一个高维向量再用这个向量去分类或者做相似度比对。训练完之后我习惯性地把最后一个卷积层的特征图做了可视化发现了一件有意思的事网络内部出现了明确分工有些通道专门响应眼睛区域有些通道专门响应鼻子轮廓还有几个通道几乎只在出现下颌线的时候激活。这不是我第一次见到这种现象但那次特别干净。于是我开始较真这种模组化是网络结构本身带来的还是因为我用了特定的数据增强如果换成随机标签模组化还会出现吗实验结果很有意思——把标签打乱网络照样能拟合训练集但内部结构基本是均匀铺开的看不见清晰的模块。这说明模组化不是网络结构的必然产物而是数据中某种结构在倒逼网络做出的一种组织方式。1.2 模组化的三层含义随着实验越做越多我意识到模组化这个词在神经网络里至少包含三个不同层级每层含义不一样测量方式也不一样。第一层是单元级模组化。单个神经元对某类特征有稳定响应比如人脸图像场景里的眼睛神经元嘴角神经元或者语音任务里的音高单元。这是最早被发现的现象十几年前的可视化工作里就有大量例子。第二层是通路级模组化。一组神经元之间有较强的互相连接构成了一条功能通路这条通路整体负责一个子任务比如检测左侧脸轮廓或是否戴眼镜。通路内部的连接权重普遍高于通路之间我们可以用连接矩阵看出来。第三层是网络级模组化。整个网络可以划分成几个大的子网络子网络之间接口很窄信息通过少数几个瓶颈神经元传递。典型的例子是迁移学习里的特征提取器与分类头把分类头换掉特征提取器还能继续用这就是一种宏观层面的模组化。层级研究对象典型表现常用观测手段单元级单个神经元对特定特征稳定响应特征可视化、最大化激活图像通路级神经元群体形成功能通路、内部强连接连接矩阵、逐层激活相关性网络级子网络之间低耦合、窄接口、可独立替换模块度、互信息、干预实验理解这三层区别很重要因为我们论文里说的模组化主要指第二层和第三层。单元级模组化虽然直观但容易出现单神经元迷信的误判——一个神经元单独看着很专一换一个输入分布它就变脸了。通路和网络层面的模组化要稳定得多也更适合作为设计神经网络的参考。2. 为什么会模组化三个关键驱动因素2.1 任务本身自带块结构模组化最根本的驱动力我认为是任务本身的结构。现实世界里的大多数任务都不是均匀的人脸有五官、语音有音素、文本有词法句法、自动驾驶的场景有道路和障碍物。这些天然存在的块会在训练过程中通过反向传播传递到网络结构里。我们在论文里做了一个特别直观的验证构造一个合成任务输入向量分成三段每段分别由三个不同的子函数决定标签子函数之间完全没有信息交换。训练一个标准的BP神经网络结构图对应的三层网络输入层、隐藏层、输出层去拟合这个任务然后切网络看结构。结果是隐藏层自动被切成了三个功能簇每个簇对应一个输入段簇内连接紧密、簇间连接稀疏。换句话说网络只是把数据里原本就存在的块结构抄了一遍。反过来如果构造一个完全纠缠的任务让每个输出都由所有输入维度的组合决定网络最终几乎不会有清晰的模块化结构。这说明了一个很重要的结论模组化不是网络的偏好而是一种对任务结构的学习。任务有块网络就会长块任务没有块网络就退化成一张均匀的网。2.2 稀疏性与连接成本的隐形压力第二个驱动因素可能不那么直观但实验里反复出现网络在训练过程中自发地倾向于减少连接成本。深度学习的损失函数里通常没有显式的连接稀疏惩罚尤其是纯交叉熵训练时网络其实可以随意使用所有连接。可实际上绝大多数训练好的网络里连接权重的分布是高度不均的大量连接趋近于零少数连接承担大部分信息传递。为什么会这样我的理解是这与反向传播的机制有关。梯度在回传时一个参数如果长期对损失函数没有贡献它的梯度会逐渐变小更新幅度随之变小最终被冻结在初始值附近。而恰好初始值很小于是这些连接等效于被淘汰了。这个过程不需要任何显式正则化它是由梯度信号本身的稀疏性驱动的。也就是说网络天生就有偷懒倾向能用少数连接解决的就不额外铺张。这种隐形的成本压力直接促进了模组化。当一个子任务只需要一组神经元就能解决的时候其他神经元和这条通路之间的连接因为梯度很小而逐渐衰减于是通路之间的耦合越来越弱模块边界越来越清晰。我们在实验里做过一个对比给同样的任务加上L1稀疏正则模组化会明显加速出现但即使不加正则只要训练时间足够长网络还是会自发走到模组化状态。正则只是助推器不是发动机。2.3 梯度信息传播的路径依赖第三个驱动因素和架构细节有关尤其是反馈信号如何流动。这里不得不提反向传播的路径依赖效应。在一个多层的LSTM里信息要穿越很多时间步梯度要穿越很多层如果路径上每个连接都均匀地传递梯度那么信号会被稀释得非常厉害。 LSTM的门控结构本身就在做一件模组化的事输入门决定哪些信息能写入记忆细胞遗忘门决定哪些信息要丢弃输出门决定哪些信息要被读到下一层。这几个门天然地把记忆写入记忆保持记忆读取分成三个子模块训练只会加强这种分工而不会打散它。前馈网络和卷积网络也有类似的路径依赖。卷积神经网络本身就在强加一种局部性每个卷积核只看一个小窗口通过滑动窗口的方式让网络自动形成对局部特征的分层组合。人脸识别图像进入神经网络到输出高维度向量的过程本质上就是一条从低级边缘检测、到五官部件、再到整体人脸语义的逐步抽象路径。这条路径上每一层都承担着明确的抽象职责模组化是被架构注释好的。我们在论文里还测试了小波Elman网络这类混合结构——把信号处理里的小波变换作为前端的特征提取器再接一个带反馈的Elman网络做时序建模。有趣的是即便前端特征提取本身已经很模组化后端Elman网络还是会在这个基础上再长出一套自己的时序模块。这说明架构设计可以引导模组化的出现位置但无法阻止网络在自由参数里继续做组织化。3. 如何在实验里抓住模组化3.1 模块度指标从网络科学借来的尺子要研究模组化第一步得先能定量测量它。模组化不是一个非黑即白的性质而是一个程度问题。我们沿用了一个网络科学领域的经典指标——模块度Modularity把神经网络的权重矩阵看成一张有权图神经元是节点连接权重是边。模块度的核心思想是如果一张图能被划分成若干社区社区内部连边密度显著高于随机图那么这张图就有模块结构。计算公式不复杂本质是拿实际连接密度减去随机期望连接密度得到一个取值通常在-1到1之间的值越高说明模块化越明显。我们把它直接套用在神经网络的连接矩阵上再用社区发现算法把神经元分成若干组然后算出这个分数。这套方法用起来有几个细节需要注意。第一个是符号问题神经网络的权重有正有负而模块度经典定义基于无符号加权图。我们尝试过三种处理方式取绝对值、保留符号、正负分开算实测下来取绝对值最稳定因为负权重在抑制性连接里同样承担功能如果只看正权重会漏掉不少抑制模块。第二个是阈值问题权重矩阵里大量趋近于零的连接会稀释社区结构一般会把低于某个阈值的连接直接去掉再算。阈值怎么选需要做敏感性分析我们论文里用的是保留前20%权重连接的标准。3.2 实验设计与数据来源有了指标之后实验设计就是关键。我们不想只在一个任务上讲故事那样说服力太弱。整个论文的实验体系分三条线第一条线是合成任务。前面提到的那种输入分段的构造任务好处是可以精确控制任务的真值模块数量。我们让它生成三模块、五模块甚至八模块的结构然后把网络学出来的模块数和真值模块数对比。这条线的优势是干净结论可靠。第二条线是真实图像任务。以人脸识别图像进入神经网络到输出高维度向量的整个过程为典型场景用公开的人脸数据集训练卷积神经网络然后在每层做模块度分析。这条线验证了合成任务里的结论在真实复杂度下依然成立而且还能看到层级化的模组化浅层模块对应局部纹理深层模块对应语义部件。第三条线是时序任务。用LSTM和小波Elman网络做长期依赖建模看门控结构如何诱导模组化。这条线的结果非常有意思我们发现LSTM的四个门网络之间出现了清晰的模块划分而且对记忆细胞写入的干扰几乎不影响门控模块的输出说明不同模块之间确实处于低耦合状态。三条线互相印证比单独做任何一个都更有说服力。这也是我们论文能顺利走到Nature Machine Intelligence的一个重要原因——结论不是基于某个特定网络的偶然现象而是跨架构、跨任务类型的共性规律。3.3 干预实验剪枝与冻结的因果验证相关性的实验做得再漂亮也免不了被质疑因果关系。 你怎么知道模组化是网络功能良好的原因而不是结果 所以我们在论文里加入了干预实验。思路很简单跟做基因功能研究的思路一样把某个模块破坏掉看网络会掉多少性能如果掉得非常多说明这个模块确实负责某个关键功能。设计很直接。第一组是剪枝实验我们在训练好的网络里把某个社区检测出的模块内部的连接先保留把模块间连接清零结果发现网络性能几乎不掉甚至有些任务上还略有提升——因为去掉了冗余的跨模块信息传递。反过来把模块内部的连接清零网络性能立刻崩溃说明模块内部承载了主要功能。第二组是冻结实验。我们训练一个小型网络作为教师模块然后把它冻结后插入到学生网络的对应位置只训练其他部分。如果模组化真的意味着模块可以独立工作那这种冷插拔应该能成功。实验结果验证了这个推测在任务结构匹配的情况下冻结模块插入后学生网络经过少量训练就能恢复大部分性能。这个结果对工程上做模块化设计很有意义意味着我们可以像搭积木一样把预训练模块组合成新网络而不是每次都从头训。4. 核心发现模组化不是装饰是功能4.1 人脸识别图像到高维向量的模组化实例我拿人脸识别这个场景具体拆解一下。输入一张对齐好的人脸图像经过几个卷积模块后输出一个几百维甚至上千维的特征向量后续做人脸比对的时候就算两个向量的余弦距离。传统上大家都把这个向量当成一个整体但我们的实验表明这个向量并不是各向同性的它在中间层就已经分裂成了多个语义段。具体来说我们在人脸数据上训练好一个卷积神经网络之后把最后一个池化层之前的特征图按通道做了聚类。结果相当惊人通道被清晰地分成几组一组对应眼睛区域、一组对应鼻子到人中区域、一组对应下颌和脸颊轮廓甚至还有一组专门对应发际线。每一组通道在最后池化后对应到高维向量的某几个维度也就是说最终输出的那个人脸向量其实是好几块语义指纹拼接起来的。这个发现直接改变了我对向量嵌入的看法。以前我总认为高维向量里的维度是纠缠在一起的现在我知道至少在某些任务里向量内部是有结构可寻的。这也解释了为什么人脸识别系统在局部遮挡时表现还不错——遮挡只破坏了描述眼睛的模块其他模块照常输出向量在整体上依然保留大部分身份信息。模组化在这里不是锦上添花而是鲁棒性的来源之一。4.2 不同架构网络表现出的共性模组化模式我们对比了几类主流网络共性比差异更值得关注。全连接的前馈神经网络在输入特征分块的任务里会自发形成模块卷积神经网络通过卷积核的局部连接天然建立空间模块LSTM的门控结构建立时间维度的模块小波Elman网络则是信号处理模块与循环模块的嵌套。网络类型模组化的主要表现形式出现位置驱动因素全连接前馈网络神经元聚成特征簇隐藏层输入特征本身的块结构卷积神经网络通道按语义分工卷积层特征图局部连接与图像自然结构LSTM门控子网络各司其职记忆细胞附近门结构强制信息分流小波Elman网络前端特征模块与后端时序模块整个网络串联显式模块结构与隐式分工叠加这个对比表看起来简单背后却有一个很关键的观察不管架构怎么变模组化的涌现规律都满足两条基本法则。第一条一个模块内部的连接密度和互信息显著高于模块之间第二条模块之间的连接数量少且往往承担信息汇总的枢纽功能。打个比方模块内部像是一个车间里的流水线模块之间像车间之间的传送带传送带数量少、位置固定、运输内容压缩过。4.3 模组化与泛化、鲁棒性、可迁移性的关系既然模组化是网络自发学到的一种组织形态那它必然要回答一个问题这种形态到底进化出了什么优势让网络在训练过程中持续选择它我们在论文里做了一个比较系统的相关性分析。先说泛化能力。用同一批网络在不同的数据子集上训练然后比较模块度和测试集准确率的关系。正相关关系非常稳定在相同参数量下模块度更高的大网络通常泛化误差更低。这背后的机理不难理解模块化等价于压缩了有效假设空间一个被组织成少数子模块的网络能产生的函数组合数量远小于全连接网络这天然抑制了过拟合。再来看鲁棒性。我们在测试时对输入加噪声、对部分神经元做遮挡攻击模块度高的网络表现明显更稳。原因和前面人脸识别的例子一致模块化的信息表编码是分布式的一个模块受损其他模块照常工作。可迁移性上的优势就更加直接了当我们把任务从源域换到相近但是不完全相同的目标域时模块度高的网络里大部分模块不需要调整只需要更换少数接口连接就能快速适应新任务。这也是为什么迁移学习里冻结底层、微调顶层这种范式那么有效因为底层模块天然就具有跨任务复用性。5. 实操经验复现这类实验的避坑指南5.1 模块度计算时最容易踩的坑如果你也想在自己的模型上算一算模块度我先给你提个醒第一版结果大概率是错的。我自己就返工过好几轮。第一个坑是社区发现算法的随机性。大多数社区发现算法都有随机初始化比如经典的路易斯算法每次运行得到的分组结果可能不一样。千万不能只跑一次就记下模块度至少要跑十次取一个稳定的分布或者设好随机种子。我们在论文里报告所有模块度数值时都同时给出多次运行的标准差。第二个坑是权重绝对值化导致的失真。我之前提到过要取绝对值再算模块度但如果你只是无脑取绝对值可能会把一个强负相关也当成强连接。更稳的做法是分别计算正权重图模块度和负权重图模块度然后加权组合。这样能保留抑制关系在模块结构里的作用。第三坑是层级问题。神经网络的连接矩阵如果直接整体算模块度经常得到的是巨型模块掩盖了内部的层次细节。建议分层计算把每一层的网络单独拿出来做社区发现然后看相邻层的模块如何对应。人脸识别网络里的层级模组化就是这样一层一层看出来的。常见错误现象处理方式社区发现随机性未控制模块度结果波动大多次运行取分布固定随机种子负权重处理不当抑制性连接被误判为不连接正负图分别计算后加权全局计算模块度层次结构被掩盖逐层计算并做跨层对应分析5.2 怎么选择任务和模型结构如果你只是想在自己的项目里观察模组化别一上来就用超大规模模型。我的经验是先用一个小规模全连接网络在合成数据上验证现象再逐步加大规模。合成数据的优势是你确切知道真值模块数可以直接对比网络学出来的模块数和真值是否一致。这比在真实数据集上面对一堆不可控因素要友好得多。模型结构上一个容易出效果的搭配是卷积神经网络配合人脸或者物体识别数据因为图像的自然结构会强烈诱导空间模组化基本上一看特征图就能感受到。LSTM适合观察时间维度的模组化但实验周期会长很多。如果你手头只有普通CPU建议从全连接网络和合成数据开始一两个小时就能出结果足够你把整套分析流程跑通。5.3 训练策略对模组化的影响训练策略的影响比我预想的大得多。最明显的因素是训练时长模组化是逐步涌现的早期网络处于均匀混沌状态训练到中期开始出现模块雏形到最后阶段才稳定下来。如果你想早点看到清晰的模块可以适当加大学习率但是配好学习率衰减让损失函数快速进入平坦区域再慢慢收敛。Batch size也有影响。小batch size带来的梯度噪声反而有助于模组化因为噪声扰动能帮助网络跳出那些均匀但脆弱的局部极小值。但噪声太大也不行会直接把刚形成的模块结构打散。我们实验里发现batch size设在32到64之间时模块度指标最稳定。数据增强是另一个隐藏变量。加入随机的裁剪、翻转、颜色扰动之后网络被逼着学习更本质的特征模块边界反而更清晰。这跟很多人的直觉相反——数据增强不是让网络特征更模糊了而是让它更聚焦于稳定的结构。当然过度增强会导致训练不收敛这里也需要自己权衡。5.4 复现实验过程中的高性价比工具链最后分享一个顺手的工具链。分析连接矩阵和计算模块度我建议用Python生态网络分析用networkx做社区发现科学计算用numpy/scipy可视化用matplotlib。训练模型直接用你熟悉的深度学习框架pytorch或tensorflow都行关键在于把权重矩阵导出来的时候注意一下格式问题——很多框架的权重存储顺序和网络结构的对应关系不一致要仔细核对每一层的shape不然算出来的连接矩阵张冠李戴后面全部白做。另外一个非常实用的技巧是把权重矩阵的绝对值做成热力图直接看。虽然模块度指标很重要但在探索阶段一张直观的热力图能帮你快速判断结构大致形态。我经常先看热力图、再跑定量分析两者结合起来效率最高。6. 写在最后关于模组化的几个还没回答的问题论文收稿那天我们团队内部开了一个小型讨论会大家各自聊了聊接下来最想做的方向。我印象最深的一个问题是模组化的边界到底由什么决定我们在实验里能通过调整任务结构来诱导网络形成不同模块数但真实任务里模块的粗细粒度应该怎么设定人脸任务里是眼睛一个模块、鼻子一个模块更优还是整个面部作为一个模块更优这个问题目前没有答案我倾向于认为它跟任务难度和计算资源之间的权衡有关但还缺少系统的理论支撑。另一个我觉得很有应用潜力的方向是把模组化指标当成网络架构搜索的反馈信号。现在的自动架构搜索主要靠验证集准确率来反馈本质上是个黑箱优化但如果我们把模块度当成一个辅助奖励项应该能引导搜索算法找到内部结构更清晰、可解释性更强的网络。我在小规模实验里偷偷试过这个想法效果是好的搜索到的结构模块度更高准确率也没有掉。我自己在这个项目里体会到最深的一点是模组化不是一个只能拿来发论文的概念它对日常工程实践有很直接的指导意义。训练一个分类网络的时候如果你发现中间层模块度一直低得离谱那大概率是你的任务设计或者数据预处理有问题如果你发现某个模块在多个任务里反复出现那不妨把它单独抽出来做成一个小插件下次遇到类似任务直接复用。神经网络没有那么不可捉摸它们只是在一个巨大的参数空间里用我们人类也能理解的方式重新组织了信息。