估计阅读时长: 6 分钟

Github开源地址:https://github.com/xieguigang/sciBASIC

本文是"果蝇赛博生命"三部曲的第一篇。我们不讲果蝇,也不讲贪吃蛇,只讲一件事:计算机是如何模仿你的大脑在"想事情"的。 放心,全文不需要任何机器学习背景,需要的只有高中数学,和一个愿意被比喻轰炸的开放心态。

一、你的大脑不会做浮点运算

先来一个可能颠覆认知的事实:你的大脑大约有 860 亿个神经元,它们彼此之间用一种非常"原始"的方式通信——发脉冲。

什么是脉冲?想象你家的门铃。平时它安安静静,门铃线里没有任何信号;你一按按钮,线上"叮"地传来一个短促的电信号,然后又归于沉寂。神经元之间的通信就是这样:

  • 平时:静默(线路上什么都没有);
  • 兴奋时:发出一个持续时间约 1 毫秒、幅度固定的尖峰电脉冲(学名"动作电位",昵称 spike);
  • 然后继续静默,直到下一次攒够了劲再发。

也就是说,大脑这个宇宙中已知最强大的信息处理系统,用的居然是一种"只说不说不说——突然喊一嗓子——继续闭嘴" 的通信协议。

更妙的是,这个脉冲的形状和幅度是固定的。神经元不会发一个"大的"脉冲来表达强烈情绪、发一个"小的"脉冲表达敷衍。它只有一招:要么喊,要么不喊。那信息藏在哪?藏在喊的时机和频率里——就像摩尔斯电码,每个嘀嗒声都一样长,但嘀嗒的节奏本身承载了全部信息。


二、深度学习不是大脑,但它假装自己是

你可能听说过深度学习、神经网络这些词。我们得先澄清一个误会:那些"神经网络"其实和生物大脑的关系,大约相当于热狗和狗的关系。

传统人工神经网络(ANN)里,每个"神经元"做的事情是:

$$
y = f!\left(\sum_{i} w_i x_i + b\right)
$$

翻译成人话:把输入 xi 各自乘上一个权重 wi,加起来,再套一个平滑函数 f(比如 sigmoid 或 ReLU),得到输出 y。注意关键点——这个输出 y 是一个连续的实数,比如 0.7382。它每时每刻都有值,随时随地在"说话",从不沉默。

而真实的神经元呢?它输出的是离散的、发生在特定时刻的事件——脉冲。0.7382 这个数字在生物神经元的世界里根本不存在,存在的只有"这个毫秒我喊了"和"这个毫秒我没喊"。

这就引出了我们的主角。


三、脉冲神经网络:让计算机学大脑"闭嘴"

脉冲神经网络(Spiking Neural Network, SNN) 是第三代神经网络模型。前两代——感知机和传统深度网络——都学的是"连续值传播";SNN 学的是大脑的本行:用离散脉冲在时间轴上传递信息。

3.1 神经元 = 一个会漏水的桶

理解 SNN 神经元,最好的比喻不是"门铃",而是一个底部有裂缝的水桶:

  1. 接水:上游神经元每次发脉冲,就相当于往你的桶里浇一瓢水(有时浇的是"负水",见下文抑制性突触);
  2. 漏水:桶壁上有裂缝,水位会随时间自己慢慢下降——如果你不持续接水,水会漏光。这叫"泄漏"(leak);
  3. 溢出发放:水位一旦超过桶口的警戒线(阈值 θ),神经元"啪"地发放一个脉冲,同时把桶里的水全部倒掉(重置),从头再来;
  4. 不应期(refractory):倒掉之后会短暂喘口气,不会立刻再发。

这就是著名的 LIF 模型(Leaky Integrate-and-Fire,泄漏-积分-发放),SNN 世界里最常用的神经元模型。用微分方程写出来其实相当朴素:

$$
\tau \frac{du}{dt} = -(u - u_{\text{rest}}) + R \, I(t)
$$

其中 u 是膜电位(桶里的水位),τ 是膜时间常数(决定水漏得多快),I(t) 是外部注入的电流(浇进来的水),R 是电阻。

在计算机里做仿真时,我们把它离散化——不连续追踪水位,而是每过一个时间步(比如 1 毫秒)看一眼。离散化后的更新公式清爽得令人发指:

$$
u[t] = \beta \, u[t-1] + W \, s[t-1] + I_{\text{ext}}[t]
$$

拆开看:

  • u[t]:当前时间步的膜电位(水位);
  • β:泄漏系数,取值 0 到 1。β = 0.9 意味着每一步桶里只剩 90% 的水——数值越小漏得越快,神经元越"健忘";
  • W s[t−1]:上游邻居们上一拍发没发脉冲(s 是 0 或 1),乘上各自突触的权重 W,汇总浇进来。W > 0 是兴奋性突触(浇水),W < 0 是抑制性突触(往桶里掺沙子,让水位往下压);
  • Iext[t]:外界注入的电流(在果蝇项目里,它就是"电刺激"或"游戏画面"的化身,这个伏笔我们第三篇再收)。

然后是发放判定,一句话:

$$
s[t] = \begin{cases} 1, & u[t] \geq \theta \ 0, & u[t] < \theta \end{cases}
\qquad\text{发放后重置:} u[t] \leftarrow 0
$$

水位碰到阈值线 θ(比如 1.0),发放脉冲,桶清空,重新开始攒水。这个"清空"操作叫重置(reset),它让每次脉冲都成为一个干净利落的事件,而不是黏黏糊糊的连续值。

3.2 用伪代码把一拍流程过一遍

每一时间步 t:
    新水位 u = 泄漏系数 β × 上一步水位
    新水位 u = u + Σ(每个邻居的脉冲 × 突触权重)   # 浇水
    新水位 u = u + 外部注入电流 I[t]              # 实验员或游戏画面浇的水

    如果 u ≥ 阈值 θ:
        本神经元发放脉冲 s = 1
        u = 0            # 倒掉桶里的水,从头再来
    否则:
        s = 0

    把 s 沿着突触传给下游邻居
    t = t + 1

就这么简单。860 亿个这样的小水桶彼此浇水,就构成了……你。正在读这篇文章、并且可能已经皱起眉头的你。


四、信息在哪里?——编码的艺术

既然脉冲只有"有/无"两种状态,信息必然藏在统计规律里。主要有三种编码方式:

4.1 频率编码(Rate Coding)

最直白的一种:刺激越强,发放越频繁。一个每秒发 100 个脉冲的神经元,显然在传递比每秒发 5 个脉冲的邻居更"着急"的信号。

比喻:餐厅服务员催你结账。如果他每 30 秒路过你桌一次,那只是礼貌性巡逻;如果他在 10 秒内出现了 8 次,你最好现在就扫码付款。

数学上,神经元的发放率定义为单位时间内的脉冲数:

$$
r = \frac{\text{脉冲总数}}{\text{神经元数} \times \text{时间步数}}
$$

仿真结束后统计这个量,我们就能知道"哪些神经元在激动,激动到什么程度"。

4.2 时间编码(Temporal Coding)

频率编码有个浪费——它把信息摊在一段时间窗口里取平均。但生物神经系统反应快得惊人:苍蝇从看到拍子到起飞只要几十毫秒,等平均都来不及。所以真实大脑大概率还使用了精确到几毫秒的发放时机来传递信息。这部分水很深,本文按下不表(主要是怕表也按不住)。

4.3 恒流直接注入(Direct Current Injection)

这是仿真里最"作弊"但最实用的方式:不做统计编码,直接给目标神经元每一步都注入一份恒定电流。刺激强度 0.8,就每步浇 0.8 单位的水。好处是完全确定、可复现——同样的输入永远得到同样的结果,这对科学实验至关重要(你不能指望一篇论文写"结果大约是这样,看运气")。

五、SNN 和深度学习,到底谁更像大脑?

来一张诚实对比表:

维度 传统深度网络(ANN) 脉冲神经网络(SNN) 生物大脑
信号形式 连续实数 离散脉冲(0/1 事件) 离散脉冲
时间 无时间概念,一层层算完就完 信号沿时间步演化 持续奔流的时间
稀疏性 每个神经元每层都输出值 大部分神经元大部分时间沉默 高度稀疏
能耗 训练一次大模型够一个小城用一年 事件驱动,极其省电 约 20 瓦(一个灯泡)
学习方式 反向传播(误差往回传) 尚无公认答案(这是难题) 突触可塑性,机制未完全解明

SNN 有个天然的优点值得单独一说:事件驱动的稀疏计算。在任一时刻,只有少数神经元在发放,绝大多数在闭嘴养膘。计算机仿真时,只需要处理"发过脉冲的神经元"及其下游,计算量和能耗都大幅下降。这也是为什么很多低功耗"神经形态芯片"(如 Intel 的 Loihi)都采用 SNN 范式。

而 SNN 最大的痛点是学习:深度学习靠反向传播调整权重,但反向传播要求信号平滑可导,而脉冲是个硬邦邦的阶跃事件,导数几乎处处为零,梯度传回去就断了。学界有各种近似方案(代理梯度等),此处不展开。好在这个痛点对我们不重要——因为我们的果蝇项目压根不需要训练网络,权重是直接从真实大脑的连接数据里"抄"来的。怎么抄?这是第二篇的故事了。


六、小结:三个带走的概念

  1. 脉冲:神经元唯一的语言,信息藏在发放的时机与频率里;
  2. LIF 模型:神经元 = 会漏水的桶。水位够了就发放并清空,公式只有一行 u[t] = β·u[t−1] + W·s[t−1] + I[t];
  3. 编码方式:频率编码最常用,恒流注入最利于仿真复现。

下一篇,我们要拜访一个真的大脑——一位被电子显微镜切成上万片、被全球志愿者逐一描边的果蝇小姐。她的全脑接线图已经公开下载,文件名 FAFB-v783,主角登场,不见不散。


系列目录:

谢桂纲

Attachments

Sort by:DefaultDateName

No responses yet

Leave a Reply

Your email address will not be published. Required fields are marked *

博客文章
September 2026
S M T W T F S
 12345
6789101112
13141516171819
20212223242526
27282930  
  1. […] 我们在基于前面所论述的《通过diamond软件进行blastp搜索》对大规模的基因组数据进行了代谢酶的EC number的注释以及按照文章《基因组功能注释(EC Number)的向量化嵌入》的方法,得到了一个比较大的基因组代谢酶TF-IDF嵌入丰度矩阵后,如果将这里所得到的嵌入结果矩阵中的基因组,基于Family层级的物种分类分组看作为单细胞转录数据中的细胞分群结果,能否基于单细胞数据分析方法来分析和可视化我的基因组功能嵌入的结果矩阵呢? […]

  2. […] 我们在基于前面所论述的《通过diamond软件进行blastp搜索》对大规模的基因组数据进行了代谢酶的EC number的注释以及按照文章《基因组功能注释(EC Number)的向量化嵌入》的方法,得到了一个比较大的基因组代谢酶TF-IDF嵌入丰度矩阵后,如果将这里所得到的嵌入结果矩阵中的基因组,基于Family层级的物种分类分组看作为单细胞转录数据中的细胞分群结果,能否基于单细胞数据分析方法来分析和可视化我的基因组功能嵌入的结果矩阵呢? […]

  3. […] 在前面的一篇《基因组功能注释(EC Number)的向量化嵌入》博客文章中,针对所注释得到的微生物基因组代谢信息,进行基于TF-IDF的向量化嵌入之后。为了可视化向量化嵌入的效果,通过UMAP进行降维,然后基于降维的结果进行散点图可视化。通过散点图可视化可以发现向量化的嵌入结果可以比较好的将不同物种分类来源的微生物基因组区分开来。 […]