JOVANA
Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

实时解码流水线

一股实时的大脑电压信号如何在每秒钟内多次变成可用的命令。我们沿着从原始信号到动作的四阶段流水线走一遍,看看**实时**这一要求为何改变了每一个设计抉择,并读一段简短的流水线伪代码。

原始信号进,命令出

解码的核心,是一种反复运行的转换:一段原始电压进去,一个离散的命令出来。把它想象成一条工厂流水线。传送带永不停歇——新鲜的大脑信号不断到来——而在末端,一件成品(一次光标移动、一个字母、一次机械手抓握)滚落下来。这条流水线的任务,就是让传送带平稳运转,每秒数十次地把杂乱的电信号变成干净的决策。

输入是你的传感器所传来的任何东西——来自头皮的脑电图(EEG,electroencephalography)、来自皮层表面的皮层脑电图(ECoG,electrocorticography),或来自皮层内电极阵列的尖峰放电。输出则是现实世界中的一个动作。两者之间的一切就是流水线,而从业者的功力,正体现在每一阶段如何搭建、以及整体运行有多快。

四个阶段

几乎每一个解码器,无论简单还是花哨,都是这四个阶段依次排列的某种版本。掌握它们一次,你就能读懂遇到的任何流水线。

  1. 预处理 / 清洗。取原始信号流的一小段窗口并加以整理:用带通滤波器保留有用的频率,并剔除或去除像眨眼和工频噪声这样的伪迹。垃圾进、垃圾出——这一阶段为后续环节兜底。
  2. 提取特征。把清洗后的窗口浓缩成寥寥几个承载意图的数字——特征,比如μ节律中的频带功率,或某个空间滤波器的输出。你是在丢掉一切无关的东西,只留下信号。
  3. 分类成一个选择。把特征喂给一个分类器——它早先在校准时已训练好——由它将特征映射到为数不多的几个意图之一(向左还是向右、点击还是静息、这个字母还是那个字母)。
  4. 发出命令。把那个选择变成一个动作——移动光标、敲下字母、驱动假肢——并把它发送出去。结果反馈给用户,从而闭合回路。

在线与离线

运行解码器有两个世界。离线分析是从容的:你有一份录制好、存在磁盘上的数据集,可以反复回放、偷看未来、试上一百个模型、消磨整个下午。在线(实时)解码则毫无这份从容。信号是实时到来的,用户在等待,回路必须在时机溜走之前闭合。

正是这一条约束——端到端地跟上实时信号——塑造了一切。你只能用过去、绝不能用未来,所以非因果滤波器被排除在外。从窗口到命令的整体延迟通常必须落在大约 100 毫秒以内才感觉跟手,这就限制了你的特征和模型能有多重。而且它必须无人值守地运行,所以流水线得优雅地处理坏样本,而不是直接崩溃。

一段流水线伪代码

下面就是把整条流水线写成的一个小循环。先讲直觉:我们抓取信号最新的一片,把它清洗干净,挤出特征,问训练好的分类器它意味着什么,然后发出命令——接着马上再来一圈。请留意,前面那四个阶段,在循环里恰好各占一行。

# Real-time decoding loop. Runs as long as the BCI is on.
while bci_is_running:
    window = stream.read(samples=250)      # newest 1 s @ 250 Hz (past only)
    if has_artifact(window):
        continue                           # skip bad chunk, don't crash
    clean = bandpass(window, low=8, high=30)   # keep mu/beta band (8-30 Hz)
    feats = band_power(clean)              # extract features: power per channel
    intent = classifier.predict(feats)     # classify -> e.g. 'left' / 'right'
    send_command(intent)                   # issue command; user sees feedback
    # loop repeats every step -> a fresh decision many times per second
一个最简在线解码循环:读取一个只含过去的窗口,清洗,提取频带功率特征,分类,然后发出命令——如此持续反复。