4. ERP提取与基线校正:从原始脑电到干净波形
好,咱们进入正题。这一章讲的是怎么从乱糟糟的原始EEG里,把ERP信号给“揪”出来。
说白了,ERP信号就藏在背景脑电里。单次刺激诱发的ERP,幅度可能只有几微伏,而背景EEG动辄几十微伏。怎么把它提取出来?靠的就是分段、基线校正和叠加平均这三板斧。
核心逻辑一句话:把连续脑电切成小段,每段对齐到刺激发生时刻,然后做基线校正消除漂移,最后把几十上百段叠加平均,噪声互相抵消,ERP波形就浮现出来了。
4.1 Epoch分段原理:把连续信号切成小段
原始EEG是连续记录的,就像一卷长长的电影胶片。我们要做的,就是找到每个刺激出现的时刻(事件标记),然后以这个时刻为中心,切出一段固定长度的信号。
分段参数怎么定?
- 刺激前时间(pre-stimulus):通常是-200ms或-100ms。这段用来做基线校正。我个人习惯用-200ms,因为有些慢波成分需要更长的基线。
- 刺激后时间(post-stimulus):取决于你关心的ERP成分。P300一般在300-600ms出现,所以取800ms够用。如果是研究N400,可能需要1000ms以上。
- 总epoch长度:pre + post。比如[-200, 800]就是1000ms。
我的经验:分段时别太贪心。我曾经为了看一个晚期正成分,把epoch拉到2000ms,结果低频漂移严重,基线校正都救不回来。后来老老实实缩到1000ms,波形干净多了。
代码实现其实很简单,以MNE为例:
import mne
# 读取原始数据
raw = mne.io.read_raw_fif('sub-01_raw.fif', preload=True)
# 定义事件
events = mne.find_events(raw)
# 分段:刺激前200ms,刺激后800ms
epochs = mne.Epochs(raw, events, event_id={'target': 1, 'standard': 2},
tmin=-0.2, tmax=0.8, baseline=None,
preload=True)
print(epochs)
# 输出:
4.2 基线校正方法:把波形拉回零线
分段之后你会发现,每个epoch的起始点并不在零线上。有的偏正,有的偏负。这是因为EEG有低频漂移,或者皮肤电位在慢慢变化。
基线校正,就是把刺激前那段时间的平均值算出来,然后从整个epoch里减掉它。这样所有epoch就站在同一条起跑线上了。
两种常用方法:
| 方法 | 原理 | 适用场景 | 注意事项 |
|---|---|---|---|
| 均值基线 | 取基线窗口内所有点的平均值,从整个epoch减去 | 大多数标准ERP分析 | 基线窗口不能包含刺激后成分 |
| 线性基线 | 用基线窗口拟合一条直线,减去该直线趋势 | 有明显线性漂移的数据 | 可能过度校正,慎用 |
均值基线是最常用的。我做了这么多年ERP,90%的情况都用均值基线。线性基线只在数据有明显漂移时才用,而且我会先做高通滤波(0.1-0.5Hz)来去除漂移,而不是依赖线性基线校正。
代码示例:
# 均值基线校正(推荐)
epochs.apply_baseline(baseline=(-0.2, 0))
# 线性基线校正(MNE中需要手动实现)
import numpy as np
from scipy import stats
def linear_baseline_correction(epoch_data, baseline_idx):
"""对每个epoch做线性基线校正"""
corrected = np.zeros_like(epoch_data)
for i in range(epoch_data.shape[0]):
for ch in range(epoch_data.shape[1]):
# 提取基线段
baseline_segment = epoch_data[i, ch, baseline_idx[0]:baseline_idx[1]]
x = np.arange(len(baseline_segment))
# 线性拟合
slope, intercept, _, _, _ = stats.linregress(x, baseline_segment)
# 构建校正趋势
trend = slope * np.arange(epoch_data.shape[2]) + intercept
corrected[i, ch, :] = epoch_data[i, ch, :] - trend
return corrected
避坑指南:我曾经犯过一个低级错误——基线窗口选错了。有一次我把基线窗口设成了[-200, 100],结果100ms已经包含了早期成分(比如P50),基线校正直接把P50给减掉了。后来检查波形才发现不对劲。记住:基线窗口必须在刺激之前,不能包含任何刺激后成分。
4.3 Epoch叠加平均:让信号从噪声中浮现
这是ERP分析最核心的一步。原理很简单:
每个epoch = ERP信号 + 背景噪声
噪声是随机的,均值趋近于0。叠加N次后,信号增强N倍,噪声只增强√N倍。信噪比提升√N倍。
叠加多少次才够?
- 视觉ERP(如P100、N170):30-50次就能看到清晰波形
- 听觉ERP(如MMN、P300):50-100次比较稳妥
- 认知实验(如ERN、N400):80-150次,取决于效应大小
代码实现:
# 叠加平均
evoked_target = epochs['target'].average()
evoked_standard = epochs['standard'].average()
# 查看结果
print(evoked_target)
# 输出:
我的习惯:叠加平均前,我会先看一眼每个epoch的方差。如果某个epoch的方差特别大(比如是其他epoch的3倍以上),我会把它标记为异常,考虑剔除。这叫“方差拒绝法”,比单纯看幅值更靠谱。
4.4 ERP波形可视化:一眼看出成分
波形画出来,才能看出有没有ERP成分。我一般会画两种图:
- 总平均波形图:所有条件叠加后的波形,对比不同条件
- 地形图:特定时间点的头皮分布,看成分的脑区定位
代码示例:
import matplotlib.pyplot as plt
# 画波形图
fig, ax = plt.subplots(figsize=(10, 6))
evoked_target.plot(axes=ax, picks=['Cz'], show=False,
time_unit='ms', spatial_colors=False)
evoked_standard.plot(axes=ax, picks=['Cz'], show=False,
time_unit='ms', spatial_colors=False)
ax.legend(['Target', 'Standard'])
ax.set_title('ERP波形对比 - Cz电极')
ax.axvline(0, color='gray', linestyle='--', alpha=0.5)
ax.axhline(0, color='gray', linestyle='--', alpha=0.5)
plt.show()
# 画地形图
evoked_target.plot_topomap(times=[0.1, 0.2, 0.3, 0.4],
ch_type='eeg', time_unit='ms')
看波形时,我习惯先看三个东西:
- 基线是否平直:刺激前200ms应该是一条水平线,如果有趋势,说明基线校正没做好
- 早期成分是否清晰:P100、N170这些早期成分应该能在单个电极上看到
- 晚期成分的形态:P300应该是正向偏转,N400应该是负向偏转
4.5 单试次分析基础:不叠加,直接看单次
叠加平均虽然好用,但它抹掉了试次间的差异。有时候我们想知道:是不是每个试次都有ERP?还是只有部分试次有?
单试次分析,就是不叠加,直接看每个epoch的波形。当然,单次epoch的信噪比很低,波形可能很乱。但我们可以用一些方法:
- 滤波:先做低通滤波(比如30Hz),去掉高频噪声
- 单试次ERP估计:用回归或机器学习方法,从单次epoch中估计ERP成分
- 时频分析:看单次epoch的时频能量变化
代码示例:
# 查看单试次
epochs['target'].plot_image(picks=['Cz'],
vmin=-10, vmax=10,
colorbar=True)
# 单试次叠加图(每个试次一条线)
fig, ax = plt.subplots(figsize=(10, 6))
for i in range(10): # 只看前10个试次
epoch_data = epochs['target'][i].get_data(picks=['Cz'])[0]
ax.plot(epochs.times * 1000, epoch_data,
alpha=0.5, linewidth=0.5)
ax.set_xlabel('Time (ms)')
ax.set_ylabel('Amplitude (µV)')
ax.set_title('单试次ERP波形(前10个试次)')
ax.axvline(0, color='gray', linestyle='--')
plt.show()
单试次分析的价值:我做过一个实验,叠加平均后P300很漂亮。但单试次一看,发现只有60%的试次有P300,剩下的40%是平的。这说明被试可能在某些试次中走神了。如果只看叠加平均,你永远不知道这个信息。
嗯,这一章的内容就这些。分段、基线校正、叠加平均,这三步是ERP分析的基石。单试次分析是进阶玩法,但理解它有助于你更深入地理解ERP的本质——它不是一个固定的波形,而是一个统计现象。
公众号:蓝海资料掘金营,微信deep3321