返回博客

2026.09.13

一个真果蝇大脑对九个随机图:进化调出来的连线,排第七

我本来想证明进化调出来的神经连线比随机接线强。跑完十组,真大脑排第七,差值 -0.0069,p=0.85。这篇讲我怎么确认这个「输了」不能信——因为我尺子上的一格,比要量的东西还粗 2.8 倍。

连接组实验方法reservoir computing探针设计

十组跑完,准确率从高到低排下来,真果蝇大脑排第七:

shufw_s3     0.8056   ← 权重打乱的假图
shufw_s1     0.7917
fullrand_s3  0.7847   ← 完全随机接线
degpres_s3   0.7847
fullrand_s2  0.7778
shufw_s2     0.7639
connectome   0.7639   ← 真大脑,第 7 名
degpres_s2   0.7569
degpres_s1   0.7500
fullrand_s1  0.7222

真大脑跟九个假图合并起来比,差 -0.0069,p=0.85。一点优势都没有,方向还是负的。

我花了三天做这件事,本来想证明的是反面。而更难受的地方在于:这个「输了」我也不能拿去说事——我后来算了一下自己的测量精度,发现这台仪器根本分辨不出我想找的那个差距。

想直接拿判据的看第 2 章,那就是一个除法;想知道什么东西真的能动摇这个网络,看第 5 章。

1. 我想赌的那件事

先说清楚在测什么。果蝇的连接组,就是把一只果蝇的脑子切片、用电镜拍下来、把每个神经元和它的每一根连线都重建出来的那张图。公开的 FlyWire 雌性全脑版本是 13.9 万个神经元、5450 万个突触(Nature 2024)。我用的是论文配套的 630 版:12.74 万个神经元、1468.7 万条边、5279.4 万个突触,跑在自己机器上的 Brian2 里,每个神经元是个最简单的漏电积分发放模型。

有个很诱人的想法:这张图能不能当"水库计算"(reservoir computing)用?水库计算的套路是,你搞一个巨大的、乱七八糟的循环网络,完全不训练它,只把输入灌进去,然后在输出端训一个最简单的线性读出层。那个大网络的作用是把输入炸开到超高维,让原本分不开的东西变得线性可分。

关键在于:标准做法里那个大网络是随机生成的。而果蝇这张是进化调出来的。

所以问题很干净:同样的规模、同样的度分布,进化调过的连线,会不会比随机接线更适合当水库?

我还顺手量了个东西,让这个赌注看起来更值得下。真实连接组里,A→B 的同时 B→A 也存在的双向边占 26.55%。按它的连接密度(0.0905%)随便接,双向边只会有 0.09% 左右;我做的度分布匹配随机图实测是 0.56%。差 47 倍。

双向连接就是局部的回声回路,而回声正是水库存住"刚才发生过什么"的物理基础。所以这条听起来简直是实锤:进化留了一堆回声回路在里面,随机图没有,水库任务上它该赢。

搜了一圈,没找到有人公开做过这个对照。听起来早该有人做了的问题,有时候真没人做。

2. 尺子上一格有多粗:一个除法

这是全文最有用的一段,而且它只是个除法。

我第一版实验的配置是:6 个类别、每类 8 次重复 = 48 个样本,分层留出,每类留 3 个当测试点,一共 18 个测试点

分类准确率这东西是离散的。18 个测试点,你只可能答对 0 个、1 个……18 个。所以:

准确率的最小刻度 = 1 ÷ 测试点数
18 个测试点 → 1/18 = 0.0556

而我想找的效应有多大?水库文献里这类结构优势通常在几个百分点。我事先写死的判据是 差值 > 0.02 才算赢

0.0556 的刻度,去量 0.02 的东西。 尺子上一格比要量的东西还粗 2.8 倍。这种情况下你测出的任何"差异",都只是"多答对了一道题还是少答对了一道题",它跟连接组是不是更优毫无关系。

发现这一点的时候我差点直接加 seed 重跑。加 seed 没用——seed 加的是重复次数,不是测试点数。留出法里你测试集多大,分辨率就多粗,跟你跑多少遍无关。

正确的修法是换交叉验证的方式:改成留一法,每个样本轮流当一次测试点。6 类 × 24 次重复 = 144 个样本,就是 144 个测试点:

1/144 = 0.0069

比要量的 0.02 细 2.8 倍了。这才算有资格开测。

再往下算一层,就更没脾气了。要让一个比例差在统计上站得住,每组需要的样本量大致是:

n ≈ p(1-p) × (1.96 × √2 ÷ d)²

p 是准确率水平,d 是你想分辨的差值。代进去:p=0.76、d=0.02,每组要 3,464 个样本。我最后跑的是每组 144 个(真大脑)和每组 432 个(三个随机族各合并 3 个 seed)。

也就是说,即使连接组真的有 2 个百分点的优势,我这个规模也看不见。 单组标准误 0.0354,比效应还大。所以第 4 章那个"输了",严格说只能支持"没有大到 5 个百分点以上的优势",别的什么都推不出来。

这条判据可以直接搬走:做任何 A/B 之前,先把「你的指标最小能跳多少」算出来,跟「你想找的差多少」比一下。前者大于后者,这个实验就还没开始就死了。

3. 为什么 100% 的准确率是废数据

尺子够细了,还有第二个坑:题目得有区分度。

我设计的任务是,在 6 个不同的位置图案上分别刺激网络,然后看能不能从全脑放电模式反推出刚才刺激的是哪一个。第一轮跑出来,四组全是 1.000。满分。

满分意味着排不出名次。真大脑 100%,完全随机图也 100%,那这个实验什么都没测到。病因是我给的 6 个图案各点亮 300 个互不相交的位点——差异大到随便一个网络都能分开。

所以我做了个难度阶梯,三个旋钮一起拧:图案之间共享多少位点(overlap,越高越难分)、驱动强度(越低响应越弱越噪)、读窗多长(越短信息越少)。判据事先写死:准确率落在 (chance+0.1, 0.95) 之间才算有鉴别力,6 类的随机猜是 0.1667,所以窗口是 (0.267, 0.95)。

实测阶梯:

overlap 驱动 读窗 准确率 打乱标签 判定
0.00 250 200ms 1.000 0.211 天花板
0.70 250 200ms 1.000 0.200 天花板
0.90 250 200ms 1.000 0.233 天花板
0.90 60 200ms 1.000 0.189 天花板
0.95 60 100ms 0.833 0.211 有鉴别力
0.98 60 50ms 0.278 0.178 接近地板

六档里只有一档能用。overlap 从 0 拧到 0.9、驱动砍到四分之一,准确率纹丝不动还是满分,得拧到 0.95 才开始掉下来,再拧一档就直接砸到接近瞎猜。能用的窗口窄得吓人,而且是拧到第五档才撞上的。

那个"打乱标签"列是另一道防线:把标签随机打乱之后重跑,必须回到随机猜的水平。实测十组平均 0.159,随机猜是 0.1667,对得上。这条要是不对,说明我的分类器在偷看标签,整轮作废。

4. 十组,和那个没有的差距

难度定在 overlap=0.95、驱动 60、读窗 100ms,然后跑十组:真连接组一组,三个随机化家族各三个 seed。

三个家族分别是:shufw 把权重在边上打乱(图的形状不动,只换权重去哪)、degpres 保持每个神经元的进出度重新接线、fullrand 完全随机接线。

结果就是开头那张排名表。按家族合并做 Welch t 检验:

对照组 准确率 n 与连接组之差 p
connectome 0.7639 144
shufw 0.7870 432 -0.0231 0.57
degpres 0.7639 432 +0.0000 1.00
fullrand 0.7616 432 +0.0023 0.96

degpres 那行是 +0.0000。精确的零。真大脑和度分布匹配的随机图,在 144 个测试点上答对了一模一样多的题。

那个 47 倍的双向边优势,在这个任务上一点都没兑现。

我得诚实说清楚这个结果是什么:它不是"连接组当水库没用",它是"在这一个任务、这一个工作点、这个样本量下,我没看见差距"。 按第 2 章算的账,能被这个实验排除的只有"5 个百分点以上的优势"。2 个百分点的优势它压根看不见。

5. 真正能撼动这个网络的东西

null result 容易给人一个错觉:这网络对什么都不敏感,所以怎么改都一样。不对。我另一组消融实验里,它敏感得很,只是敏感的点跟我预想的不一样。

拿一个确定的读出神经元(论文里那个控制伸吻的运动神经元,基线 84.6 Hz)当探针,两种扰动各做三个 seed:

翻转 20% 边的兴奋/抑制符号 →  0.6 /  2.8 / 61.6 Hz
随机砍掉 20% 的边          → 47.2 / 34.8 / 80.8 Hz

同样是动 20% 的边,翻符号能把这个神经元的输出打到基线的 1% 和 3%,砍边什么事都没有。

这里我还栽了一跤,值得单独说。我最初写的判据是"发放率 == 0 才算被打哑",按这条,翻符号 20% 的结果是 0/3 打哑——因为 0.6 和 2.8 都不是零。可 0.6 Hz 是基线的 0.7%,这个神经元在功能上已经死透了。判据定成"等于零",就把"还剩百分之一"判成了健康。 正确的阈值是小于基线的 10%。

这一格一格看还有更清楚的形状:

翻 1%   →  81.8 / 78.4 / 93.0 Hz   几乎无感
翻 5%   →  83.0 / 61.2 / 85.2 Hz   还行
翻 10%  →  74.2 / 58.8 / 110.4 Hz  有一个比基线还高
翻 20%  →   0.6 /  2.8 / 61.6 Hz   塌方

10% 是悬崖边。 10% 以下随便翻都无所谓,有一次还蹦到 110 Hz 高过基线;从 10 跨到 20,直接塌。

为什么这件事重要:连接组里的连线和突触数量是量出来的,电镜照片上数得清清楚楚。而每条边是兴奋还是抑制,是靠一个分类器预测出来的神经递质类型推的(Eckstein 等 2024)。也就是说,整张图里唯一不是测量结果的那个字段,恰好是扰动它最致命的那个字段。 大家嘴上说的"连接组是打了折的权重",那个折扣正好打在最要命的地方。

还有个配套发现,对任何想拿连接组接机器人的人都有用:翻 20% 符号时,全脑还剩 82.5% 的神经元在放电,但那个读出神经元只剩 1% 到 3%。你在全局指标上完全看不出问题,接在下行神经元上的那只手已经不动了。读出端比群体脆得多。

6. 怎么判断一个「连接组仿真」的 demo 是真是假

这半年这类 demo 挺多的——把果蝇大脑接上虚拟身体,让它走路、躲影子、理毛。有一篇 eLife 的 reviewed preprint(2026-08-17,《The digital sphinx: Can a worm brain control a fly body?》)把这事一次性拆穿了:作者拿线虫的连接组去控制果蝇的身体,中间用强化学习训了一层映射。

结果是高度逼真的果蝇步态。摘要原话:

The resulting digital sphinx produces highly realistic fly walking—yet it is biologically meaningless. ……behavioral fidelity is achievable without biological fidelity, making such models easy to overinterpret.

行为像,不代表里面那个东西对。所以看任何一个连接组 demo,只需问一句:中间那层接口,训过没有? 训过,那走得多好看都只证明接口层学会了,跟连接组没关系。

几个真实的分层(我逐个翻了它们自己的 README 和博客,没看二手转述)。有个刷屏的桌面果蝇,实际只是 668 个神经元的子图,占全脑的 0.5%,README 自己写了两条:逃跑反应时间并非活体测量值;跨个体的接口突触在数据里根本不存在,属于建模出来的。有个更严肃的全脑+身体项目,自述视觉激活"somewhat decorative,不实质影响行为输出"。

每一层自己都承认了简化,是二手转述把限制全删了。 遇到"XX 仿真了 YY"这类说法,直接翻一手 README 的 limitations 段,作者通常比转述者诚实一个数量级。

同一个形状在图论指标上也成立。我算过从 21 个输入神经元出发的图上可达集:全脑 99.4% 可达。而同一个刺激真跑仿真,实际放电的只有 0.33%。差 301 倍。

图上可达 ÷ 仿真实际放电 = 99.4% ÷ 0.33% ≈ 301

纯图分析只能证明"不可能",不能预测"会不会"。 下次看到"这个脑区跟那个脑区之间有通路",先问它是图上算的还是跑出来的。

顺带一个更具体的翻车:我一度写下"论文里的通路是 A→B→C→读出神经元",后来去查才发现,那个说法的出处是另一个项目的 README,不是论文原文,而我管它叫"论文通路"。实测两个版本的数据集里,那最后一跳都是零条直连边。真正的主驱动是一个二手描述里从来没出现过的神经元。

7. 这个实验还有哪些地方不能信

上面每个数字都是自己跑出来的,但它们各自的可信度差很多,得分开说。

排名表和 p 值的效力只够排除大效应。 前面算过,每组 144 个点只能分辨 5 个百分点以上的差距。这一整篇最硬的结论也就到"没有大优势"为止。

只在一个工作点上测过。 难度阶梯扫了 6 档,但四组对照只在选中的那一档跑。换个 overlap、换个读窗,结论有没有可能翻,我不知道。

每个随机族只有 3 个 seed。 组间准确率在 0.7222 到 0.8056 之间飘,跨度 8 个百分点,明显大于任何组间差。3 个 seed 估不准这个方差。

那个分类任务可能根本不需要记忆。 这是我最不放心的一条。水库的价值在于把过去的输入也留在当前状态里,而"认出刚才刺激的是哪个图案"可能只靠当前瞬间的响应就够了。如果是这样,那我测的是这个网络的瞬时可分性,跟"进化调出来的回声回路"半点关系都没有——第 1 章那个赌注,可能从头到尾就没被真正测过。

更早一轮的记忆容量测量整轮作废,但方向是负的。 我先测过一轮真正的记忆容量指标,真连接组是 0.000,而权重打乱的假图是 0.447 到 0.515。看着像真大脑惨败,但那一轮所有组的当前输入相关性都是 0.98 到 0.99,等于整个网络只是输入的回声——网络在饱和态,每个神经元每秒放电约 55 次,所有组的记忆都被压成零,测量无效。病根是我连着两次拿"活跃神经元比例"当工作点判据,而活跃度只数"有没有放过电",数不出"放得多疯"。这一轮不能当证据用,但它也没给连接组加分。

正则化参数的选择用了全部数据。 代码里留一法外层是干净的,但选正则化强度的内层用了全体样本。这对所有组一视同仁,不会造成组间偏差,但会让所有组的绝对准确率略微偏高。

这几处补完之前,我不会把这个结论说死。

8. 下次再做这种对照,按这个顺序来

  1. 先算指标的最小刻度。 1 ÷ 测试点数。它比你要找的效应粗,就别开跑了,先改实验设计。
  2. 再算需要的样本量。 n ≈ p(1-p)(1.96√2/d)²。算出来跑不起,就老实把要找的效应调大,或者承认这个实验只能排除大效应。
  3. 先只在实验组上扫难度阶梯。 准确率落进 (chance+0.1, 0.95) 才开测。满分和瞎猜都排不出名次,跑了也白跑。
  4. 每轮都跑打乱标签的对照。 它必须回到随机猜的水平。不回去,说明分类器在偷看,整轮作废。
  5. 判据里的阈值别写"等于零"。 写"小于基线的百分之几"。0.6 Hz 和 0 Hz 在统计上不同,在功能上是一回事。
  6. 全局指标正常不代表读出端正常。 全脑 82.5% 还在放电的时候,你真正关心的那个神经元可能只剩 1%。盯着你实际要读的那个东西。
  7. 引用任何"论文说"之前,去翻论文原文。 我把一个 README 里的说法叫成"论文通路",实测那条通路的最后一跳根本不存在。
  8. 先证明你那个工作点是有效的,再解读结果。 网络饱和的时候,所有组的记忆都是零,那不是结论,那是测量失败。

至于连接组当水库到底行不行,我现在能说的只有一句:在我这个精度下看不出来。想看出来得每组跑三千多个样本,那大概是十几个小时的事。等我先把那个"任务到底需不需要记忆"想清楚再说,不然跑三千个也只是把一个没测对的东西测得更精确。