信息速览
一个心电算法在公开库上拿到九十九点几的准确率,和它在真实病房里能不能用,中间隔着一层很少被量化的东西:噪声。公开的心电基准库为了标注可靠,往往本身就是挑过的好记录——电极贴得牢、病人躺着配合、基线平稳。于是模型学到的不是"怎么认出心搏",而是"怎么在好信号里认出心搏"。可穿戴设备、Holter、床旁监护送来的信号从来不是这个样子:患者翻身、走路、出汗,电极在皮肤上微微错动,肌电叠在 QRS 上,基线在呼吸里慢慢漂。等到上线那天,被噪声打垮的是那些在干净数据上几乎不犯错的部分。
MIT-BIH 噪声压力测试数据库(MIT-BIH Noise Stress Test Database,简称 NSTDB)就是为这层东西准备的尺子。它做的不是"再采集一批更难的心电",而是把噪声本身做成一个可控变量:先用 Holter 记录仪在一名活动受试者身上、把电极放在看不见本人心电的肢体位置,录下三条纯噪声——基线漂移、电极运动伪迹、肌电伪迹;再用 nst 工具把电极运动噪声按校准好的量,加到 MIT-BIH 心律失常库里两条公认好判读的记录上,做成 24、18、12、6、0、−6 dB 六档信噪比。因为原记录是干净的、标注是已知的,加噪之后即便波形被搅到肉眼读不出,标准答案依然在那里。
它的价值与它的局限来自同一个设计:它只回答"你的检测器在噪声下会坏到什么程度",不回答"你的检测器在真实人群里准不准"。三条噪声来自同一个人、同一台记录仪、同一次佩戴;十二条心电只用了两个人的两条记录。它不是一份人群样本,是一套可控实验装置。一屏速览见下表。
一屏速览
| 维度 | 内容 |
|---|---|
| 全名 | MIT-BIH Noise Stress Test Database |
| 发布方 | PhysioNet;数据由 MIT 计算生理实验室(Laboratory for Computational Physiology)贡献 |
| 页面署名作者 | George Moody、Roger Mark |
| 首次发布 | 1999 年 8 月 3 日,版本 1.0.0(目前唯一版本) |
| 最近改动 | 官方版本列表只有 1.0.0,未见修订记录 |
| 记录数 | 15 条:12 条加噪心电 + 3 条纯噪声 |
| 每条通道数 | 2 |
| 采样率 | 360 Hz |
| 每条采样点 | 650000,即 650000÷360 ≈ 1805.6 秒,约 30 分 5.6 秒 |
| 总时长 | 15 条各约半小时,合计约 7.5 小时 |
| 噪声类型 | 基线漂移(记录 bw)、电极运动伪迹(记录 em)、肌电伪迹(记录 ma) |
| 信噪比档位 | 6 档:24、18、12、6、0、−6 dB,每条记录一个固定档位 |
| 标注 | 12 条心电记录各带一份 .atr,是 118、119 原参考标注的拷贝;噪声记录无标注 |
| 文件格式 | WFDB:.hea 头文件 / .dat 信号 / .atr 注释,另有 .xws 脚本 |
| 许可 | Open Data Commons Attribution License v1.0(ODC-BY 1.0),无需注册 |
| 典型用途 | 心律失常检测器噪声容忍度评测、去噪算法对比、加噪数据增强、QRS 检出器压力测试 |
§1 它要解决的具体麻烦
1.1 准确率是条件句,条件常被省略
任何一份"准确率 99%“的心电算法报告,都隐含着一句没写出来的条件:在什么信号上。这个条件之所以总被省略,是因为它很难量化。你可以说人群是门诊还是住院、年龄跨度多大、有没有起搏器,但你很难说"这批信号的噪声有多大”——噪声没有天然单位,同样的波形,一个人安静躺着和一个人边走边说话,录出来的东西不是一回事。
结果是评测的口径长期偏向"好信号"。一个 QRS 检出器在 MIT-BIH 心律失常库上跑出来的错误率,通常被当成它在"一般难度"上的表现;而这套库恰恰是当年为了做算法评测、从大量 Holter 里挑出来的一批,挑选标准之一就是能被当时的算法较好地分析。用它做基线,再拿它做上限,中间的落差就没人看了。
要补上这个落差,需要三样东西凑齐:一段已知正确答案的干净心电、一段真实的(不是合成的)噪声、以及一个能把噪声按可重复的量加进去的方法。第一样心电库早就有了,第二样和第三样是 NSTDB 补上的。
1.2 三条常见的错误期待
第一条,期待它是"一批更难的心电数据"。它不是数据集意义上的样本扩充,因为十二加噪记录全部来自同两条原始记录。用它训练模型,等于让模型背诵两个人的波形在不同噪声下的样子。它的正确用法是评测:固定模型、变噪声档位,看性能曲线怎么往下掉。
第二条,期待它的噪声是"合成出来的"。恰恰相反,bw、em、ma 三条是从真人身上录的真实噪声——一名活动受试者,用常规 Holter 记录仪和常规动态心电电极,电极特意放在四肢上那些看不到本人心电的位置,两路同时记录。这一点决定了它的噪声谱是真实的,而不是高斯白噪声或人为构造的漂移。
第三条,期待三条噪声记录是"三种纯净的噪声类型"。官方原话对 em 的描述是"以电极运动伪迹为主,同时也含有相当数量的基线漂移与肌电噪声",ma 是"以肌电为主,频谱与心电重叠但延伸到更高频率"。也就是说这三条是"以某种噪声为主"的实录,不是实验室里分离出的纯净分量。
1.3 它能给到的与给不到的
| 你的需求 | 它给的 | 够不够 |
|---|---|---|
| 评测检测器在不同噪声强度下的衰减曲线 | 6 档信噪比,同一条原始心电每档一份 | 够,这是它存在的理由 |
| 比较三类噪声各自的破坏力 | bw、em、ma 三条实录,可分别叠加 |
够,但只有 em 被官方用来生成成品记录 |
| 做去噪算法的输入输出对 | 干净原记录(mitdb 的 118、119)与加噪记录成对 | 够,且是真值对齐的 |
| 合成任意信噪比的训练集 | nst 工具 + 噪声记录,参数可自定 |
够,但需要装 WFDB 工具包 |
| 评测模型在真实人群上的泛化 | 只有 2 名心电受试者、1 名噪声受试者 | 不够,完全不能代表人群 |
| 多中心、多设备的域适应研究 | 单一实验室、单一记录仪 | 不够 |
| 评估长时程真实噪声的统计特性 | 三条噪声各半小时,且来自单次佩戴 | 不够,只够做短程实验 |
| 做节律分类或心搏分类的主训练库 | 12 条记录、2 个人 | 不够,会被立刻记全 |
| 评估非心电信号的噪声鲁棒性 | nst 可对任意 WFDB 记录加噪 |
够,官方工具不限定心电 |
1.4 你的处境与它能帮到的事
| 你的处境 | 它能帮你什么 | 下一步该做什么 |
|---|---|---|
| 你训好一个 QRS 检出器,想知道它在多大的噪声下开始漏搏 | 同一条心电的 6 档加噪版本,可逐档跑检出率 | 按记录名读档位,逐档跑同一次评测,把漏检数对 SNR 作图 |
| 你在做可穿戴单导联设备,出货前要交一份抗噪指标 | 提供可复现的加噪协议,指标能被第三方复算 | 用 §5.4 的 nst 命令复现,报告里写清档位与通道 |
| 你在写去噪论文,需要成对的有噪/干净信号 | 加噪记录与 mitdb 原记录逐采样点对齐 | 以原记录为真值算信噪比改善,注意增益与基线换算 |
| 你要给分类器做加噪增强,但嫌合成噪声不真实 | em 是真实电极运动伪迹 |
用 nst 直接叠加到你自己的干净数据上,别照抄固定档位 |
| 你在评审一篇只报了干净库成绩的论文 | 提供一个"应该补做的实验"模板 | 建议作者加跑 NSTDB 六档,报告衰减拐点 |
| 你在教学里讲"为什么心电算法会误判" | 六档同根记录,肉眼可见退化过程 | 取同一时间窗并排画 24 dB 与 −6 dB |
1.5 一句话判断
NSTDB 噪声压力测试库不是一个"更难的数据集",而是一把"可调刻度的尺子":把噪声从一堆说不清的干扰,变成一个有单位、可复现、能写进论文方法节的自变量。它能告诉你曲线在哪一档开始往下掉,但不会告诉你这条曲线在真实人群里的位置——后者要由规模库来回答,两者不能互相替代。
1.6 不适合谁:四条边界
不适合拿来训练。 十二条加噪记录只来自两条原始记录、两名受试者。任何有容量的模型都能在几轮之内把它们记下来,得到的"抗噪能力"是背出来的,不是学出来的。
不适合拿来估计真实世界噪声的强度。 三条噪声是单次佩戴、单个人的实录。真实场景里噪声强度随活动、电极、皮肤、导联类型大幅变化,本库不提供这种分布。
不适合拿来评测形态学诊断。 它只有两路信号(MLII 与 V1),没有十二导联,也没有任何 ST 段或形态学的定量标注。要做诊断级评测,得去有诊断标注的库。
不适合拿来做统计意义上的结论。 样本量是"两条记录 × 六档",这个设计足以显示趋势,不足以支撑带置信区间的断言。
§2 数据构成与规格
2.1 十五条记录分成两类
第一类三条是纯噪声:bw、em、ma。它们的头文件里没有患者信息,增益字段是 0,通道名就叫 noise1 与 noise2——也就是说它们不是"某个人的记录",而是三段可供叠加的干扰素材。
第二类十二条是成品:由 MIT-BIH 心律失常库的 118 与 119 两条记录,叠加 em 噪声生成,每条固定一个信噪比档位。它们的通道名沿用原记录的 MLII 与 V1,增益写作 200(1024),头文件末尾有一行注释标明生成来源与档位。
| 对比项 | 噪声记录(bw / em / ma) | 加噪心电记录(118e* / 119e*) |
|---|---|---|
| 条数 | 3 | 12 |
| 通道名 | noise1、noise2 |
MLII、V1 |
| 存储格式 | 212(每 3 字节放 2 个 12 位采样点) | 212(24/18/12/6 dB);16(0 dB 与 −6 dB) |
| 增益字段 | 0(未校准) |
200(1024) |
| 位分辨率 | 12 | 11 |
| ADC 零值 | 0 | 0 |
| 参考标注 | 无 | 有,.atr,拷贝自 118 / 119 |
| 头文件注释 | 无 | 一行 Created by 'nst' ... (SNR = X dB) |
单条 .dat 体积 |
约 1.9 MB | 约 1.9 MB(212)或约 2.5 MB(16) |
格式差异值得单独说一句。nstdb.doc 里写得很明确:0 dB 与 −6 dB 的记录用格式 16 存储,因为格式 212 强制的 12 位范围偶尔会被采样值突破。换句话说,噪声越大,加噪后的整数量程越大,就越挤不进 12 位。这个细节在读数据时是自动处理的(wfdb 按头文件解析),但在自己写解析器时会直接踩坑——同一个库里两种格式并存。
2.2 文件组成与目录清单
数据库采用 WFDB(Waveform Database)格式,每条记录对应同名的三个文件:.hea 纯文本头文件、.dat 二进制信号、.atr 二进制注释。归档目录里还能看到每个记录额外带一个 .xws(WAVEScript)文件,以及几个清单文件。
| 文件 / 目录 | 角色 | 备注 |
|---|---|---|
RECORDS |
15 条记录名清单 | 93 字节,一行一个记录名 |
ANNOTATORS |
注释文件角色说明 | 内容为 atr 对应「参考心搏、节律与信号质量标注」 |
118e*.hea / 119e*.hea |
加噪记录头文件 | 每条 170–177 字节 |
118e*.dat / 119e*.dat |
加噪记录信号 | 1.9 MB 或 2.5 MB |
118e*.atr / 119e*.atr |
参考标注 | 118 系列约 4.5 KB,119 系列约 4.7 KB |
bw.hea / em.hea / ma.hea |
噪声记录头文件 | 90–93 字节 |
bw.hea- / em.hea- / ma.hea- |
同名备份头文件 | 通道描述写作「BW noise, signal 0/1」 |
bw.dat / em.dat / ma.dat |
噪声信号 | 各约 1.9 MB |
*.xws |
WAVEScript 脚本 | 91 字节(心电记录)/ 80 字节(噪声记录) |
nstdbgen |
生成脚本(现行版) | 730 字节,12 行 nst 调用 |
nstdbgen- |
生成脚本(原始版) | 1.2 KB,含头文件与标注的重命名步骤 |
nstdb.doc / nstdb.txt |
说明文档 | 1.9 KB,1992 年 8 月 |
MD5SUMS / SHA1SUMS / SHA256SUMS |
校验和清单 | 用于核验下载完整性 |
DOI |
数字对象标识 | 内容为 doi:10.13026/C2HS3T |
old/ |
第一版记录 | 15 条(12 条加噪 + oldbw/oldem/oldma) |
ANNOTATORS 那一行值得留意:它把 .atr 的角色写成「参考心搏、节律与信号质量标注」,而不是单纯的心搏标注。这与它拷贝自 MIT-BIH 心律失常库原标注是吻合的——原标注本身就同时含这三类内容。
2.3 头文件字段字典
下表按 WFDB 头文件规范(header(5))逐字段说明。记录行四个字段,信号行九个字段,注释行以 # 开头。
| 字段 | 位置 | 本库取值 | 含义 | 使用注意 |
|---|---|---|---|---|
| 记录名 | 记录行第 1 字段 | 118e24、em 等 |
记录标识,即文件名前缀 | 名字里编码了来源记录与档位 |
| 信号条数 | 记录行第 2 字段 | 2 |
通道数 | 全部 15 条均为 2 |
| 采样率 | 记录行第 3 字段 | 360 |
每秒采样点数 | 与 MIT-BIH 心律失常库一致 |
| 采样点数 | 记录行第 4 字段 | 650000 |
信号长度 | 650000÷360 ≈ 1805.6 秒 |
| 信号文件名 | 信号行第 1 字段 | 118e24.dat |
信号存放位置 | 两通道共用同一个 .dat |
| 存储格式 | 信号行第 2 字段 | 212 或 16 |
编码方式 | 0 dB 与 −6 dB 用 16 |
| ADC 增益 | 信号行第 3 字段 | 200(1024) 或 0 |
每物理单位(默认毫伏)对应的整数量 | 括号里是基线值;0 表示未校准 |
| 基线 | 增益字段括号内 | 1024 |
0 物理单位对应的整数值 | WFDB 5.0 之前版本会忽略 |
| 位分辨率 | 信号行第 4 字段 | 11 或 12 |
ADC 位数 | 加噪记录 11,噪声记录 12 |
| ADC 零值 | 信号行第 5 字段 | 0 |
输入范围中点对应的整数值 | 与基线不同,别混 |
| 初始值 | 信号行第 6 字段 | 如 -167 |
首个采样点的整数值 | 用于断点续传与校验 |
| 校验和 | 信号行第 7 字段 | 如 -13451 |
采样点累加和 | 用于检测文件是否完整 |
| 块大小 | 信号行第 8 字段 | 0 |
每帧字节数 | 本库由库自动按格式计算 |
| 通道描述 | 信号行第 9 字段 | MLII、V1、noise1、noise2 |
解剖位置或角色 | 加噪记录沿用原记录导联名 |
| 生成说明 | 注释行 | Created by 'nst' from records 118 and em (SNR = 24 dB) |
出处与档位 | 只在 12 条加噪记录上出现 |
增益字段的写法是本库最容易读错的地方。按 header(5) 的定义,括号里那个数是基线(baseline),不是分辨率也不是零值;而紧跟其后的 11 才是位分辨率。三条噪声记录的增益是 0,规范明确规定:增益为零或缺失即表示信号幅度未校准,此时可按默认值 200 ADC 单位/物理单位处理——但那是"可以假设",不是"文件里写了"。
2.4 一条记录的完整解剖
以 118e24 为例,头文件全文如下:
118e24 2 360 650000
118e24.dat 212 200(1024) 11 0 -167 -13451 0 MLII
118e24.dat 212 200(1024) 11 0 -103 32392 0 V1
\# Created by `nst' from records 118 and em (SNR = 24 dB)
从记录行读起:2 个通道、360 Hz、650000 个采样点。650000 除以 360 约等于 1805.6 秒,比整半小时多出 5.6 秒——这是因为原始记录 118 本身就是这个长度,NSTDB 没有把它截断到整分钟。
两条信号行说明:数据放在 118e24.dat,格式 212,增益 200、基线 1024,位分辨率 11,ADC 零值 0,两个通道的初始值分别是 −167 与 −103,校验和不同,通道名是 MLII 与 V1。末行注释交代了生成来源:由 nst 用 118 与 em 生成,信噪比 24 dB。
噪声记录的头文件更短:
em 2 360 650000
em.dat 212 0 12 0 5 -5959 0 noise1
em.dat 212 0 12 0 -21 -26067 0 noise2
同样 2 通道、360 Hz、650000 点,但增益是 0、位分辨率是 12、通道名是 noise1 与 noise2,没有注释行。归档目录里还有一份 em.hea-,内容为 em.dat 212 0 12 0 5 -5959 0 EM noise, signal 0 之类,通道描述更具体——两份头文件数值一致,只是描述串不同。
作为对照,MIT-BIH 心律失常库里 118 的原头文件是:
118 2 360 650000
118.dat 212 200 11 1024 857 8669 0 MLII
118.dat 212 200 11 1024 921 -25621 0 V1
\# 69 M 1456 653 x2
\# Digoxin, Norpace
\# The PVCs are multiform.
对比可见三点:采样长度逐点相同(650000),通道名相同(MLII、V1),增益数值相同(200)。差异在基线的写法——原库把 1024 放在独立的 ADC 零值字段,NSTDB 把它写进增益字段的括号里,ADC 零值字段则置 0。两者表示的物理换算一致,但字段位置不同,手写解析器要按规范来。
2.5 读取与换算
import wfdb
#-- 远程直读加噪记录;pn_dir 指向 PhysioNet 上的库名
rec = wfdb.rdrecord('118e24', pn_dir='nstdb')
ann = wfdb.rdann('118e24', 'atr', pn_dir='nstdb')
print(rec.fs, rec.sig_len, rec.sig_name) #-- 360 650000 ['MLII', 'V1']
print(rec.p_signal.shape) #-- (650000, 2) 已按增益与基线换算成毫伏
#-- 读噪声记录;增益为 0,wfdb 会按默认增益处理,物理量不可当真
noise = wfdb.rdrecord('em', pn_dir='nstdb')
print(noise.units, noise.adc_gain) #-- 会反映头文件的未校准状态
上面这段的关键是 p_signal 与 d_signal 的区别:前者是按增益与基线换算过的浮点物理量,后者是文件里的原始整数。做跨库比较、算振幅相关的指标时一定要用 p_signal;做位深、量化噪声一类研究时才用 d_signal。
噪声记录的增益为 0,意味着它的整数值没有毫伏含义。这不影响它的用法——nst 在校准时是靠 sigamp 测量相对幅度,而不是靠头文件里的增益——但影响你的直觉:不要把 em 的整数值直接当毫伏读。
2.6 记录名即参数:命名规则与六档档位
记录名 RRReNN 里,RRR 是原始心电记录号,NN 是加噪时段的信噪比(dB),_6 表示 −6 dB。这套命名让目录本身就是一张实验设计表。
| 记录名 | 原始记录 | 噪声源 | 信噪比(dB) | 存储格式 |
|---|---|---|---|---|
118e24 |
118 | em | 24 | 212 |
118e18 |
118 | em | 18 | 212 |
118e12 |
118 | em | 12 | 212 |
118e06 |
118 | em | 6 | 212 |
118e00 |
118 | em | 0 | 16 |
118e_6 |
118 | em | −6 | 16 |
119e24 |
119 | em | 24 | 212 |
119e18 |
119 | em | 18 | 212 |
119e12 |
119 | em | 12 | 212 |
119e06 |
119 | em | 6 | 212 |
119e00 |
119 | em | 0 | 16 |
119e_6 |
119 | em | −6 | 16 |
bw |
无 | 实录 | 不适用 | 212 |
em |
无 | 实录 | 不适用 | 212 |
ma |
无 | 实录 | 不适用 | 212 |
注意档位之间的间隔是 6 dB,从 24 一路到 −6,跨度 30 dB。在功率比上这意味着最强档与最弱档相差三个数量级(每 6 dB 约等于幅度比 2 倍、功率比 4 倍),所以 −6 dB 那一档的噪声幅度大约是 24 dB 档的三十余倍。这就是为什么最吵的两条记录连存储格式都要换。
§3 它是谁的数据
3.1 贡献者与机构
PhysioNet 项目页署名的作者是 George Moody 与 Roger Mark,机构均为 MIT 计算生理实验室(MIT Laboratory for Computational Physiology)。页面指定的原始出版物是 1984 年 Computers in Cardiology 上的那篇会议论文:Moody GB, Muldrow WE, Mark RG,《A noise stress test for arrhythmia detectors》,第 11 卷 381–384 页。
随库发布的 nstdb.doc 署名是 G. Moody、1992 年 8 月,版权归 MIT。生成脚本 nstdbgen 的首行写着 1992 年 8 月 3 日创建、2002 年 11 月 8 日最后修订。也就是说,数据本体在 1992 年就成型了,1999 年 8 月 3 日是它作为独立项目挂上 PhysioNet 的日期——这两个年份含义不同,引用时要分清。
3.2 时间线
| 时间 | 事件 | 意义 |
|---|---|---|
| 1984 | 噪声压力测试方法在 Computers in Cardiology 发表 | 方法先于数据公开 |
| 约 1990 | 第一版随 MIT-BIH 心律失常库光盘发布 | 即 old/ 目录里的那批 |
| 1992-08 | 第二版记录生成(nstdb.doc、nstdbgen) |
现行版本的数据本体 |
| 2002-11 | 生成脚本最后修订 | 脚本适配当时的 WFDB 版本 |
| 1999-08-03 | 在 PhysioNet 上线,版本 1.0.0 | 首次作为独立项目公开 |
| 至今 | 只有 1.0.0 一个版本 | 无修订、无扩版 |
这张表里 1992 与 1999 的先后关系需要说明:数据生成于 1992 年,PhysioNet 上线日期是 1999 年。官方页面把 1999 年 8 月 3 日标为 Published 日期,它指的是平台发布日,不是采集日。
3.3 采集场景:把电极放在看不见心电的位置
三条噪声记录的采集方式,是这套数据里最巧妙的一步。官方描述是:用常规动态心电记录仪和常规电极,在一活动的受试者身上记录;电极放在四肢上那些看不到本人心电的位置;两路信号同时记录。
"看不到心电"这五个字是关键约束。常规 Holter 的电极位置是为了把心电采得大而清楚,如果直接用那些位置的信号,噪声里会混着一个大幅度的心电,没法当纯噪声用。于是把电极挪到心电投影很弱的位置,录到的就主要是电极—皮肤界面、肌肉、导线牵拉、呼吸和体位造成的扰动。
"活动"同样重要。基线漂移来自受试者或导线的运动,电极运动伪迹来自电极上间断的机械力,肌电来自肌肉收缩——三者都只在活动状态下才充分出现。躺着不动录半小时,得到的不会是这样的素材。
至于三条之间怎么区分:bw 那段以基线漂移为主,ma 那段以肌电为主,em 那段以电极运动伪迹为主(同时含相当数量的基线漂移与肌电)。这是靠挑选区间得到的——从原始录音里挑出以某类噪声为主的片段,拼成半小时。
3.4 三个层次:素材、工具、成品
理解这份数据要先分清三层,它们的身份完全不同。
| 层次 | 是什么 | 在哪 | 能不能自己再造 |
|---|---|---|---|
| 噪声素材 | bw、em、ma 三条实录 |
库内 | 不能,需要重新做人体采集 |
| 加噪工具 | WFDB 的 nst 与 sigamp |
WFDB 软件包 | 能,官方工具,参数开放 |
| 成品记录 | 12 条 118e* / 119e* |
库内 | 能,用 nstdbgen 可完整复现 |
第三层的"能复现"是这份数据最特别的性质。大部分数据集是"给你一份采集结果,你无法再生";而这里给了脚本,用当前版本的 WFDB 跑一遍就能得到同样的 12 条记录。这意味着它的可复现性不依赖存档,而依赖工具链——反过来说,如果未来 WFDB 的行为变了,复现结果也可能随之改变。
§4 它最独特的东西
4.1 把噪声变成自变量
多数公开心电库的噪声是"附带属性":这段记录碰巧比较吵,那段比较干净,使用者只能事后按信噪比分层,而分层本身又需要估计信噪比,估计方法各家不同。NSTDB 反过来做:先定档位,再按档位造数据。于是噪声从因变量变成自变量,实验设计从观察性变成干预性。
这个转向带来的直接好处是:性能曲线可以被读成"函数在 SNR 上的形状"。哪个档位开始明显掉分、掉分是渐变还是断崖、两路通道是不是同时掉,这些问题在有真实噪声但无档位的库上只能定性回答,在这里可以逐档测。
4.2 信噪比是怎么定出来的
nst 的档位不是随便标的一个数,它有一套写进文档的定义。按 WFDB 应用指南里 nst(1) 的说明,SNR = 10 log₁₀(S/N),其中 S 与 N 的测量方式如下:
| 步骤 | 做法 |
|---|---|
| 定 S(信号功率) | 用 sigamp 读参考标注,测前 300 个正常 QRS 的峰峰幅度,窗口是标注时刻前后各 50 ms |
| 剔除极值 | 去掉最大的 5% 和最小的 5%,取剩余 90% 的均值作为峰峰幅度估计 |
| 换算成功率 | 峰峰幅度平方后除以 8(文档说明:对正弦波是精确的,对本用途足够接近) |
| 定 N(噪声功率) | 把噪声记录前 300 秒切成 1 秒一段,每段算均值与相对均值的均方根差 n |
| 再剔除极值 | 同样去掉最大、最小各 5%,取剩余 90% 的均值作为 RMS 噪声幅度 |
| 求缩放系数 a | 解 SNR = 10 log₁₀(S/(N·a²)),对每一对信号分别求解 |
文档里解释了为什么不用"平均功率"这种朴素定义:平均平方幅度会与心率的平方成正比,与检测器定位 QRS 的能力关系不大;而不加权的噪声功率又会高估甚低频噪声的重要性,可实际上甚低频噪声对检测器通常并不麻烦。所以 S 挂在 QRS 幅度上,N 做频率加权——这样定出来的 dB 值才与直觉上的"信号质量"大致对得上。
加噪的时间协议同样有明确规定,而且两处文档说法一致:先是一段 5 分钟的无噪"学习期",之后以 2 分钟加噪、2 分钟干净交替,直到原始记录结束。学习期的用途很实际——检测器通常需要一点时间自适应,给它 5 分钟干净信号再开始加噪,测到的才是噪声的影响而不是冷启动的影响。
4.3 案例:同一条 118 从 24 dB 到 −6 dB
由于六档记录同源、同长度、逐采样点对齐,同一时间窗在不同档位上是可以直接并排看的。以 118 系列为例:
| 档位 | 记录名 | 头文件注释 | 肉眼可读性(官方描述) |
|---|---|---|---|
| 24 dB | 118e24 |
SNR = 24 dB | 几乎看不出加噪 |
| 18 dB | 118e18 |
SNR = 18 dB | 噪声可见但不干扰判读 |
| 12 dB | 118e12 |
SNR = 12 dB | 噪声明显 |
| 6 dB | 118e06 |
SNR = 6 dB | 判读开始困难 |
| 0 dB | 118e00 |
SNR = 0 dB | 波形被显著搅乱 |
| −6 dB | 118e_6 |
SNR = −6 dB | 官方原话:噪声让记录"在视觉上无法判读" |
最后一行引的是官方页面的原话——“即使噪声让记录在视觉上无法判读,正确的心搏标注依然是已知的,因为原始心电是干净的”。这句话点出了整套设计的核心:真值不来自对加噪记录的判读,而来自对干净原记录的判读。所以 −6 dB 那两条不是"没法用",恰恰是最能拉开检测器差距的两条。
4.4 标注为什么可信,以及可信到哪一步
12 条加噪记录各带一份 .atr 参考标注。它们的来源被文档写得很直白:全部是 118 与 119 原参考标注的拷贝。生成脚本 nstdbgen- 里能看到对应的重命名步骤——nst 输出的 atruth.118e24 被改名成 118e24.atr,atruth 这个前缀就是"annotation truth"的意思。
这带来两个后果,一好一坏。好的是标注质量等于 MIT-BIH 心律失常库原标注的质量,不需要为加噪记录重新标注,也不存在"标注者在噪声下误判"的问题。坏的是标注里不含任何噪声信息:.atr 里没有"这一段被加了噪声"的标记,加噪时段的边界要靠 §4.2 的时间协议自己推,或者用 nst 生成的协议注释文件(.ns*,脚本末尾被 rm 掉了,没有随库发布)。
也就是说,想在逐心搏的粒度上把"这个搏落在干净段还是加噪段"标出来,需要自己按 5 分钟 + 2 分钟交替的规则反推时间点。这个反推是确定性的,但官方没有直接给文件。
4.5 边界条件:三条噪声来自同一个人
这是最容易被忽略、也最该写进方法节的一条。bw、em、ma 是同一次佩戴、同一台记录仪、同一名活动受试者身上的实录。这意味着:
第一,三条噪声之间不独立。它们共享同一个人的运动模式、皮肤特性、导联布置,em 里含基线漂移与肌电这件事本身就是证据。把它们当成三个独立噪声源做"噪声类型 × 强度"的全因子实验,会高估结论的普适性。
第二,它不能代表噪声的人群分布。不同年龄、皮肤、体毛、电极胶、导联材质,噪声谱差别很大。本库给的是一个具体的、真实的样本,不是一个分布。
第三,第二版对这三条做过一次处理:nstdb.doc 说明,bw、em、ma 中频率低于 0.05 Hz 的甚长期基线漂移已被去除,未处理的原始版本保存在 old/ 目录里的 oldbw、oldem、oldma。如果你的研究恰恰关心甚低频漂移,那三条原始版本才是你要用的。
§5 怎么拿到
5.1 目录结构
nstdb/1.0.0/
├── RECORDS #-- 15 条记录名,一行一个
├── ANNOTATORS #-- 说明 .atr 的角色
├── DOI #-- doi:10.13026/C2HS3T
├── MD5SUMS / SHA1SUMS / SHA256SUMS
├── nstdbdoc #-- 说明文档(归档版文件名为 nstdb.doc)
├── nstdbgen #-- 现行生成脚本
├── 118e00.{hea,dat,atr,xws} #-- 以下 12 条为加噪心电记录
├── 118e06.{hea,dat,atr,xws}
├── ...
├── 119e_6.{hea,dat,atr,xws}
├── bw.{hea,dat,xws} #-- 以下 3 条为纯噪声记录
├── em.{hea,dat,xws}
├── ma.{hea,dat,xws}
└── old/ #-- 第一版:118_02 … 119_12、oldbw、oldem、oldma
根目录是扁平的,没有子目录分层,15 条记录的文件直接并列。old/ 是唯一的子目录,放着第一版。
5.2 批量下载
#-- 1. 取记录清单
curl -sL https://physionet.org/files/nstdb/1.0.0/RECORDS -o RECORDS
#-- 2. 按清单逐条下载三件套(加噪记录)
while read r; do
for ext in hea dat atr; do
curl -sL -o "${r}.${ext}" "https://physionet.org/files/nstdb/1.0.0/${r}.${ext}"
done
done < RECORDS
#-- 3. 用校验和清单核对
curl -sL https://physionet.org/files/nstdb/1.0.0/SHA256SUMS -o SHA256SUMS
sha256sum -c SHA256SUMS
第 2 步对 bw、em、ma 会请求不存在的 .atr 而拿到 404,这是正常的——噪声记录没有标注文件。可以先用清单把三条噪声剔出去再跑。
整库的体量很小:15 条记录,.dat 各 1.9 MB 或 2.5 MB,全部信号加起来三十兆上下,一次下完没有压力。这是它适合做快速复现基线的现实原因。
5.3 流式读取
如果只想跑几条,不必下载,用 wfdb 远程直读更省事:
import wfdb
import numpy as np
#-- 取记录清单
names = wfdb.get_record_list('nstdb')
print(len(names), names[:3]) #-- 15 条
#-- 读一对:干净原记录与 6 dB 加噪版本
clean = wfdb.rdrecord('118', pn_dir='mitdb')
noisy = wfdb.rdrecord('118e06', pn_dir='nstdb')
print(clean.p_signal.shape, noisy.p_signal.shape) #-- 形状相同,逐点对齐
#-- 取同一时间窗并排比较(第 600 秒起 10 秒)
lo, hi = int(600 * clean.fs), int(610 * clean.fs)
seg_c = clean.p_signal[lo:hi, 0]
seg_n = noisy.p_signal[lo:hi, 0]
rdrecord 会把增益与基线换算好,p_signal 直接是毫伏。注意 mitdb 与 nstdb 两个库的增益数值相同(都是 200),基线写法不同但物理含义一致,所以两边 p_signal 可以直接比。
5.4 自己造更多记录
这是本库区别于其他数据集的地方——官方给了配方。
#-- 用 nst 把 em 噪声按 10 dB 加到任意一条干净记录上
nst -i mitdb/100 nstdb/em -o 100e10 -s 10 -F 212
#-- 用简化脚本一次性复现库里的 12 条
sh nstdbgen
#-- 脚本内容就是 12 行 nst,形如:
#-- nst -i mitdb/118 nstdb/em -o 118e24 -s 24 -F 212
#-- nst -i mitdb/118 nstdb/em -o 118e00 -s 0
#-- nst -i mitdb/118 nstdb/em -o 118e_6 -s -6
几条 nst 的行为要预先知道:如果干净记录与噪声记录的采样率相差 10% 以上,它会先用 xform 重采样噪声记录,生成的中间文件命名规则是"原名去掉下划线后缀 + 下划线 + 新采样率",例如把 360 Hz 的 em 用在 250 Hz 的记录上会先生成 em_250;如果噪声记录比干净记录短,它会回卷从头继续取;加噪在协议注释文件里最后一个 NOTE 处或干净记录结束时停止,取先到者。
-F 参数决定输出格式,默认 16。库里 24/18/12/6 dB 那八条显式指定了 -F 212,0 与 −6 dB 那四条没指定、落到默认的 16,原因见 §2.1。
5.5 与 MIT-BIH 心律失常库的对齐
| 项目 | NSTDB 的 118e* / 119e* | MIT-BIH 心律失常库的 118 / 119 |
|---|---|---|
| 采样点数 | 650000 | 650000 |
| 采样率 | 360 Hz | 360 Hz |
| 通道名 | MLII、V1 | MLII、V1 |
| 增益 | 200(写作 200(1024)) |
200 |
| 位分辨率 | 11 | 11 |
| ADC 零值 / 基线 | 0 / 1024 | 1024 / 无括号基线字段 |
| 参考标注 | 原标注的拷贝 | 原标注 |
| 受试者信息 | 头文件中没有 | 118 为 69 岁男性;119 为 51 岁女性 |
最后一行值得单独强调:加噪记录的头文件里没有受试者年龄、性别、用药信息,那些只存在于原库。需要写人群描述的研究,要回到 MIT-BIH 心律失常库去引。
5.6 五个坑
| 坑 | 表现 | 怎么避 |
|---|---|---|
| 同一库里两种存储格式 | 0 dB 与 −6 dB 是格式 16,其余是 212 | 别写死解析器,按头文件走 |
| 噪声记录增益为 0 | 整数值没有毫伏含义 | 需要物理量时先确认校准状态,别直接当毫伏 |
| 基线字段在括号里 | 200(1024) 里的 1024 是基线,不是分辨率 |
按 header(5) 解析,别按位置猜 |
| 加噪段边界没有现成标注 | .atr 里没有"此处开始加噪" |
按 5 分钟学习期 + 2 分钟交替的规则反推 |
RECORDS 里有三条没标注 |
bw、em、ma 没有 .atr |
批量下载前先剔掉这三条,或容忍 404 |
§6 与库内条目的关系
6.1 关系图谱
| 库 | 与它的关系 | 组合用法 |
|---|---|---|
| MIT-BIH 心律失常库 | 母库,118 与 119 的来源,也是标注的来源 | 取干净原记录当真值,NSTDB 当加噪版本 |
| MIT-BIH 房颤库 | 同为长时程双通道,但噪声是真实的而非可控的 | 用 NSTDB 定档位,用房颤库看真实条件下的表现 |
| 运动伪迹类心电库 | 都关心伪迹,但那里伪迹是场景自带的 | 用 NSTDB 做可控对照,用真实伪迹库做生态验证 |
| 床旁监护波形库 | 真实环境下的多通道波形,噪声不可控 | 用 NSTDB 校准方法,再去真实波形上验证 |
| 合成心电库 | 都提供"非自然"信号,但合成的是波形而非噪声 | 合成波形叠真实噪声,可造出成对的训练样本 |
| 单导联房颤分类挑战赛 | 单导联场景对噪声最敏感 | 把 NSTDB 档位作为评测轴加进去 |
| 十二导联大库 | 导联维度互补,那里几乎没有噪声档位 | 从十二导联里抽单导联,再用 NSTDB 的方式加噪 |
6.2 检索路径
| 你想找什么 | 该往哪走 |
|---|---|
| 干净原记录与原始标注 | MIT-BIH 心律失常库(118、119 两条) |
| 长时程真实房颤 | MIT-BIH 房颤库、长期房颤库 |
| 真实运动伪迹场景下的心电 | 运动伪迹相关心电库 |
| 不可控但真实的床旁波形 | 床旁监护波形库 |
| 合成心电与真假判别 | 合成心电图库 |
| 大规模十二导联诊断标注 | 十二导联大库与各类挑战赛库 |
6.3 分工判据
| 问题 | 用 NSTDB | 用别的库 |
|---|---|---|
| 噪声强度要不要可控 | 要,档位固定可复现 | 不需要,看真实表现 |
| 要不要成对真值 | 要,干净与加噪逐点对齐 | 不需要 |
| 样本量重要吗 | 不重要,看趋势 | 重要,要统计结论 |
| 人群代表性重要吗 | 不重要 | 重要 |
| 关心的是检测器还是诊断 | 检测器(QRS、节律) | 诊断(形态、ST) |
一句话概括分工:凡是要把"噪声"当自变量写进方法节的,用它;凡是要把"人群"当自变量写进方法节的,用别的。
§7 质量评估与局限性
7.0 前置校正:先说清楚它不是什么
评估这份数据的质量,先要排除一个错位的期待:它不是一份临床数据集,没有患者、没有诊断、没有结局。它的质量指标应该是"实验装置"的指标——可控性、可复现性、真值可靠性——而不是"样本"的指标——代表性、多样性、标注一致性。按后一套指标评它,它会显得很差;按前一套评,它是同类里做得最扎实的。
7.1 五维评分
| 维度 | 评价 | 依据 |
|---|---|---|
| 可控性 | 高 | 6 个固定档位,档位定义写进工具文档 |
| 可复现性 | 高 | 生成脚本随库发布,用现行 WFDB 可重跑 |
| 真值可靠性 | 高(就"心搏标注"而言) | 标注拷贝自干净原记录,不受噪声影响 |
| 真实性 | 中高(噪声真实;场景是构造的) | 噪声取自活动受试者实录,但叠加方式是人工的 |
| 代表性 | 低 | 2 名心电受试者、1 名噪声受试者、单一设备 |
第三维需要限定:真值可靠指的是"这条记录里第 N 个心搏是什么类型"可靠,不包括"哪一段被加了噪声"——后者没有随库提供。
7.2 标注的两层
| 层次 | 内容 | 是否随库提供 |
|---|---|---|
| 心搏层 | 位置与类型,拷贝自 118 / 119 原标注 | 是,.atr |
| 节律层 | 原标注中的节律变换标记 | 是,随 .atr 一同拷贝(官方 ANNOTATORS 写明含节律标注) |
| 信号质量层 | 原标注中的信号质量标记 | 是,随 .atr 一同拷贝 |
| 加噪协议层 | 每段加噪的起止时刻与缩放系数 | 否,协议文件在生成后被删除 |
最后一行是本库最实用的一个缺口。nst 在运行过程中会生成协议注释文件,但 nstdbgen 与 nstdbgen- 两个脚本的末尾都有删除步骤(分别是 rm nstdb/em.ns* 与 rm nsa*),所以协议没有随库发布。要做"分段"级别的分析,得自己按时间协议反推,或者自己重跑一次 nst 并保留协议文件。
7.3 可枚举的偏差
| 偏差来源 | 具体表现 | 影响方向 |
|---|---|---|
| 噪声来源单一 | 三条噪声同一次佩戴、同一个人 | 噪声谱的多样性不足 |
| 心电来源单一 | 只用 118、119 两条 | 波形形态多样性不足,且这两条是"好判读"的 |
只叠加 em |
成品记录全部用电极运动伪迹,bw 与 ma 未用于生成 |
无法直接比较三类噪声的破坏力 |
| 原始记录被刻意挑选 | 官方文档说选它们是因为"本身不吵、多数检测器能无错分析" | 基线成绩会偏乐观,衰减幅度可能偏小 |
| 甚低频漂移已去除 | 第二版去掉了 0.05 Hz 以下的长期漂移 | 关心极低频漂移的实验要改用 old/ 版本 |
| 两通道成对叠加 | 两路信号分别配一路噪声,缩放系数各自独立 | 不能假设两路的等效噪声强度相同 |
| 加噪是加性的 | 输出 = 干净 + a×噪声 + b,不含乘性衰减或削波 | 真实接触不良常带非线性效应,本库不覆盖 |
第五行容易被忽略:如果你要研究的是"电极慢慢脱落导致的超低频漂移",第二版的 bw 已经不适合了,去 old/ 里取 oldbw(注意格式是 16,不是 212)。
7.4 外部验证:它在文献里被怎么用
从公开文献看,它的用法高度一致——当"噪声源",而不是当"数据集"。典型写法是:取 bw、em、ma 中的一段,按目标信噪比叠加到自己手里的干净心电上,再去评测去噪或分类算法。这种用法在 2017 年前后的小波去噪类论文里已经定型,此后在深度学习去噪、可穿戴信号处理一类工作里被大量沿用。
这个用法有一个值得注意的后果:文献里报告的"加噪信噪比"与库里记录名的档位,往往不是同一个定义。 库里的档位是 nst 按 §4.2 那套 QRS 幅度 + 频率加权噪声功率算出来的;而很多论文里的"5 dB 噪声"是按整段信号的平均功率或方差比算的。两者数值不可直接比。跨论文比较性能曲线时,先确认对方用的是哪种定义。
另一个后果是,它作为"评测集"的身份远弱于它作为"噪声源"的身份。搜 NSTDB 出来的论文,绝大多数只是在"数据"一节里提一句"噪声取自 NSTDB",真正按六档跑完整评测曲线的并不多。想找可比的基准成绩,可参照的公开结果比想象中少。
7.5 它为何能持续
它没有更新、没有扩版、只有 15 条记录,却在二十多年后仍被引用,原因有三。
第一,它提供的东西无法被"更大数据"替代。更大的心电库带来的是人群多样性,不是噪声可控性;而噪声可控性恰恰是算法评测里最缺、也最难自己造的一环。
第二,它绑定在 WFDB 工具链上。nst、sigamp、xform 都是 WFDB 的一部分,任何人只要装了工具包就能复现并扩展这套实验。工具与数据互相加固,使得它不会被新的文件格式淘汰。
第三,方法学上的定义足够清楚。档位怎么算、协议怎么排、格式为什么换,都写进了文档。这意味着后来者引用它时不需要猜,也不需要重新发明定义——这在评测类资源里是罕见的。
§8 生态位与历史
8.1 沿革:两个版本,一次重做
| 版本 | 位置 | 记录名 | 档位 | 状态 |
|---|---|---|---|---|
| 第一版 | old/ |
118_02…118_12、119_02…119_12 |
名义 02–12,实际未按文档标定 | 仅为完整性保留 |
| 第一版噪声 | old/ |
oldbw、oldem、oldma |
不适用 | 未去除甚低频漂移 |
| 第二版 | 根目录 | 118e24…118e_6、119e24…119e_6 |
24、18、12、6、0、−6 dB | 现行版本 |
第一版的问题被文档写得毫不含糊:那 12 条记录的信噪比"并不像第一版光盘 readme.doc 里说的那样标定过"——既不符合现行定义,也不符合当年声称的定义。文档随后给出了按现行定义重算的结果,例如 118_02 的两路分别是 19.79 dB 与 14.38 dB,119_12 是 4.74 dB 与 −1.77 dB。注意这里每条记录的两路数值相差约 5 dB,说明第一版并没有做到逐通道独立校准。
文档还记了一个具体的失误:第一版光盘上的 118_10 漏掉了第二路信号,归档版里已补回(原表在该格旁标了星号说明)。
这就是为什么要分两个版本:第二版不是"加了更多数据",而是"按一套写清楚的定义重做了一遍"。用第一版复现旧实验的历史结果可以,拿它做新实验不合适。
8.2 与挑战赛的关系
PhysioNet/CinC 系列挑战赛里,心电相关的几届都大量涉及信号质量问题:单导联房颤分类那一届面对的是手持设备采集的短片段,多模态心拍定位那一届面对的是多来源信号的同步,睡眠与呼吸类挑战赛面对的是长时程信号里的运动伪迹。这些赛题的共同难点与本库的主题高度重合。
但要说清一点:挑战赛提供的是真实采集的噪声,本库提供的是可控叠加的噪声。挑战赛的成绩告诉你"在真实条件下能到几分",本库的成绩告诉你"在多大噪声下开始崩"。两者互补,不能互换——用本库训练出来的抗噪能力去打挑战赛,往往不如直接用挑战赛数据训练,因为真实噪声的分布与 em 这一段实录并不相同。
8.3 生态位
| 角色 | 大规模训练库 | 可控评测装置 |
|---|---|---|
| 典型形态 | 上千条记录、多中心、带诊断标签 | 十几条记录、参数化生成、带档位 |
| 回答的问题 | 在真实人群上准不准 | 在多大的噪声下开始坏 |
| 失败模式 | 过拟合、标签噪声 | 样本太少、场景失真 |
| 代表 | 十二导联大库、挑战赛库 | 本库 |
本库坐在右边一列,而且几乎是那一列里唯一的成员。这不是因为它做得完美,而是因为"可控噪声"这件事在公开数据生态里长期没人做——采集噪声素材没有学术回报,而做数据集的人更愿意采集患者。
8.4 谁在用
从公开文献的用法看,使用者主要是四类:做信号去噪的(把它当真实噪声源)、做可穿戴设备的(把它当抗噪评测协议)、做检测器评测的(按六档跑衰减曲线)、做数据增强的(用 em 给自己的干净数据加噪)。第一类的数量远多于第三类——也就是说,它被当作"零件"使用的频率,高于被当作"基准"使用的频率。
§9 使用指引
9.1 三种角色的路径
| 角色 | 第一天 | 第一周 | 注意事项 |
|---|---|---|---|
| 算法研究者 | 读官方页与 nstdb.doc,跑通 §2.5 的读取 |
在 118 与 119 两个系列上各跑六档,画衰减曲线 | 分通道报结果,别只报平均 |
| 设备工程师 | 用 §5.4 的 nst 给自己设备的数据加噪 |
定出货要过的档位门槛,写成内部测试项 | 报告里写清用的是哪种 SNR 定义 |
| 教学与临床工程 | 并排画同一时间窗的 24 dB 与 −6 dB | 讲清"真值来自干净原记录"这个设计 | 说明噪声只来自一名受试者 |
9.2 一条最短的可用流程
#-- 1. 取清单,把三条噪声挑出来单独处理
curl -sL https://physionet.org/files/nstdb/1.0.0/RECORDS -o RECORDS
grep -E 'e[0-9_]' RECORDS > ecg_records.txt #-- 12 条加噪心电
grep -vE 'e[0-9_]' RECORDS > noise_records.txt #-- bw / em / ma
#-- 2. 只下一对:干净原记录与 6 dB 版本(用 wfdb 流式读则跳过)
for r in 118e06; do
for ext in hea dat atr; do
curl -sL -o "${r}.${ext}" "https://physionet.org/files/nstdb/1.0.0/${r}.${ext}"
done
done
import wfdb
import numpy as np
#-- 3. 干净与加噪逐点对齐,直接算残差
clean = wfdb.rdrecord('118', pn_dir='mitdb')
noisy = wfdb.rdrecord('118e06', pn_dir='nstdb')
resid = noisy.p_signal - clean.p_signal
print(resid.shape, float(np.std(resid[:, 0])), float(np.std(resid[:, 1])))
这段代码的作用是确认"噪声确实是加进去的、且两路独立缩放"。它不产出结论,只用来在动手前验证对齐关系是否成立——这是很多加噪实验 silently 出错的地方。
9.3 引用方式
| 引用对象 | 内容 |
|---|---|
| 数据集 | MIT-BIH Noise Stress Test Database, version 1.0.0. PhysioNet. 1999. |
| 原始方法论文 | Moody GB, Muldrow WE, Mark RG. A noise stress test for arrhythmia detectors. Computers in Cardiology 1984; 11:381-384. |
| DOI | 10.13026/C2HS3T |
| 平台 | PhysioNet 平台综述论文(2026 年发表于 Nature Health),按官方页面 Cite 按钮生成 |
论文里建议额外写明三件事:用了哪几条记录与哪些档位、信噪比是按 nst 的定义还是自己算的、以及是否用了 old/ 目录里的第一版。这三件不写清,结果就不可比。
§10 AI 使用声明
| 项目 | 声明 |
|---|---|
| 文本生成 | 本文由 AI 辅助撰写,编辑把关结构与事实 |
| 数字来源 | 规模、结构、边界三类数字来自 PhysioNet 官方页面、随库发布的 nstdb.doc 与 RECORDS、以及 WFDB 应用指南中 nst(1) 与 header(5) 的说明 |
| 文件核验 | RECORDS、ANNOTATORS、nstdb.txt、nstdbgen、nstdbgen-、118e24.hea、118e00.hea、em.hea、bw.hea-、以及归档目录清单经直接访问确认;MIT-BIH 心律失常库 118.hea、119.hea 一并核对 |
| 不一致说明 | 官方页面把原始论文第二作者写作 Muldrow WE,而 1990 年 MIT-BIH 心律失常库光盘论文的同条参考文献写作 Muldrow, W.K.,两者首字母不同,本文按官方页面写法引用;官方页面称每条记录为「半小时」,头文件实为 650000 采样点 ÷ 360 Hz ≈ 1805.6 秒 |
| 论文信息 | 1984 年原始会议论文仅按官方页面给出的题录引用,未读全文;外部用法参考了公开文献摘要 |
| 未核验内容 | 各记录的具体心搏条数、加噪协议文件的逐段起止时刻(协议文件未随库发布)、三条噪声记录各自的功率谱构成、old/ 目录 15 条记录的逐条头文件 |
| 图像 | 无配图;封面为生成式提示词,不含真实心电图 |
| 免责 | 本文不构成临床建议;数据使用须遵守 ODC-BY 1.0 署名要求;本库为算法评测资源,不可用于任何临床诊断用途 |
常见误读(避坑清单)
| 说法 | 实际 | 证据 |
|---|---|---|
| 「它是 12 条记录的数据库」 | 15 条,另有 bw、em、ma 三条噪声记录 |
RECORDS 清单 15 行;官方摘要也写明 12+3 |
| 「噪声是合成出来的」 | 三条噪声是活动受试者的 Holter 实录 | 官方页面:用常规记录仪、电极、导联采集 |
| 「三条噪声是三种纯净类型」 | 是以某类为主的实录,em 里含相当数量的基线漂移与肌电 |
nst(1) 文档对三条的描述 |
| 「每条正好半小时」 | 650000 采样点 ÷ 360 Hz ≈ 1805.6 秒,多出约 5.6 秒 | 全部 15 条头文件第 4 字段均为 650000 |
| 「所有记录的存储格式一样」 | 0 dB 与 −6 dB 用格式 16,其余用 212 | nstdb.doc:12 位范围偶尔被突破 |
| 「噪声记录有毫伏含义」 | 增益字段为 0,表示未校准 | header(5):增益为零即幅度未校准 |
「200(1024) 里的 1024 是分辨率」 |
是基线值;分辨率是紧跟其后的 11 | header(5) 字段定义 |
| 「它是 250 Hz」 | 360 Hz,与 MIT-BIH 心律失常库一致 | 头文件记录行第 3 字段 |
| 「用了它就能说明模型抗噪」 | 只能说明在这三段实录噪声、这两条记录上抗噪 | 噪声来自单名受试者,心电来自两条记录 |
| 「加噪段有现成标记」 | 没有,协议文件在生成后被删除 | nstdbgen 末行 rm nstdb/em.ns* |
| 「第一版和第二版可以混用」 | 第一版档位未按定义标定,且含未去除的甚低频漂移 | oldnstdb.txt 与 nstdb.txt |
| 「它适合训练抗噪模型」 | 12 条记录、2 个人,会立刻被记全 | 官方记录名清单仅 12 条加噪记录 |
FAQ
Q1:NSTDB 到底有多少条记录?
十五条。RECORDS 清单里是 12 条加噪心电(118e24、118e18、118e12、118e06、118e00、118e_6 与对应的 119e*)加 3 条纯噪声(bw、em、ma)。官方摘要的表述是「12 条半小时心电记录与 3 条半小时噪声记录」,两者一致。只说 12 条的人通常是把噪声记录当成了附属文件,而它们是正式记录,有自己的头文件与信号文件。
Q2:为什么只有 em 被用来生成成品记录?
官方给的理由是电极运动伪迹对心律失常检测器最麻烦——它能逼真地模仿异位心搏的形态,而不像基线漂移那样可以用简单滤波器去掉。nst(1) 文档里写得更直接:正因为电极运动伪迹最麻烦,nstdb 目录里其余记录才全部由 em 的噪声与干净心电混合而成。想比较三类噪声的破坏力,得自己用 nst 分别叠加。
Q3:六档信噪比是怎么算出来的?
按 nst 的定义:S 由前 300 个正常心搏的 QRS 峰峰幅度(标注点前后各 50 ms 窗口内测量)去掉最大最小各 5% 后取均值、平方再除以 8 得到;N 由噪声记录前 300 秒切成 1 秒段、每段算相对均值的均方根差、同样去掉极端 5% 后取均值、再平方得到。然后对每一对信号解 SNR = 10 log₁₀(S/(N·a²)) 求出缩放系数。这套定义与很多论文里按整段功率比算的"dB"不是一回事,跨论文比较前要先确认口径。
Q4:噪声是叠加在哪一段时间的?
有固定协议:开头 5 分钟是无噪的学习期,之后以 2 分钟加噪、2 分钟干净交替,直到原始记录结束。这个协议是 nst 在未指定协议文件时自动生成的标准协议,两个版本的生成脚本都没有指定 -p,所以 12 条记录用的都是它。协议文件本身没有随库发布,需要逐段边界时要自己按这个规则反推。
Q5:我能用它训练模型吗?
不建议做主训练。12 条加噪记录全部来自 MIT-BIH 心律失常库的 118 与 119 两条、两名受试者,模型几轮之内就能把它们记全,得到的"抗噪能力"是背出来的。它适合的位置是评测与增强:评测时固定模型、变档位;增强时把 em 噪声用 nst 叠到你自己的干净数据上,档位自己定,不要照抄库里那六档。
Q6:为什么 0 dB 和 −6 dB 的记录体积更大?
因为它们用格式 16 存储。nstdb.doc 说明:这两档的采样值偶尔会超出格式 212 强制的 12 位范围,所以改用每个采样点占 2 字节的格式 16。目录清单里对应地表现为 1.9 MB 与 2.5 MB 两种体积。
Q7:第一版还能用吗?
只在一种情况下该用:你要复现某个当年基于第一版做的实验。除此之外用第二版。第一版的信噪比既不符合现行定义、也不符合当年声称的定义,文档里重算出来的数值两路相差约 5 dB;另外第二版从三条噪声里去除了 0.05 Hz 以下的甚长期基线漂移,未处理的原始版本在 old/ 里的 oldbw、oldem、oldma。如果你恰恰要研究甚低频漂移,那三条原始版本才是目标。
Q8:它的许可允许商业使用吗?
ODC-BY 1.0 允许,包括商业用途,条件是署名。引用时要写清数据集名称、版本与 DOI(10.13026/C2HS3T),并按官方要求同时引用 1984 年的原始方法论文。具体条款以官方许可全文为准。
Q9:它和 MIT-BIH 心律失常库是什么关系?
是派生关系。12 条加噪记录的信号来自后者的 118 与 119,参考标注也是后者原标注的拷贝,采样点数、采样率、通道名、增益全部一致。差异只有两处:基线的写法(NSTDB 写进增益字段的括号里,ADC 零值置 0),以及头文件里没有受试者年龄、性别、用药信息——那些要回原库查。
Q10:体量有多大?能一次下完吗?
信号部分三十兆上下,全库加上注释与清单也不大,可以一次下完。官方是按文件目录发布,没有整库压缩包;用 wget 递归、curl 按 RECORDS 循环、或者 wfdb 流式直读都可以。下完建议用 SHA256SUMS 核一遍。
术语表
| 术语 | 解释 |
|---|---|
| 噪声压力测试 | 把校准好的噪声加到干净信号上,用来评测分析程序抗噪能力的方法 |
| 信噪比(SNR) | 信号功率与噪声功率之比,以分贝表示;本库按 nst 的定义计算 |
| 基线漂移 | 低频的信号缓慢起伏,多由受试者或导线运动引起 |
| 电极运动伪迹 | 电极受间断机械力产生的扰动,可模仿异位心搏,最难滤除 |
| 肌电伪迹 | 肌肉收缩产生的高频干扰,频谱与心电重叠并延伸到更高频率 |
| 学习期 | nst 标准协议开头 5 分钟的无噪时段,供检测器自适应 |
| WFDB | PhysioNet 的波形数据库格式与工具包,含头文件、信号、注释三类文件 |
.hea |
纯文本头文件,声明采样率、通道数、增益、基线等 |
.dat |
二进制信号文件 |
.atr |
二进制注释文件,存心搏位置与类型 |
| 格式 212 | WFDB 的一种编码:每 3 字节存放 2 个 12 位采样点 |
| 格式 16 | WFDB 的一种编码:每个采样点占 2 字节,范围大于 12 位 |
| ADC 增益 | 每一物理单位(默认毫伏)对应的整数量,换算物理量时使用 |
| 基线 | 0 物理单位对应的整数值,写在增益字段的括号内 |
| ADC 零值 | 输入范围中点对应的整数值,与基线是不同的字段 |
| 位分辨率 | 模数转换器的位数,影响量程与量化噪声 |
| 校验和 | 采样点累加和,用于检测信号文件是否完整 |
nst |
WFDB 工具,按指定信噪比把噪声记录的噪声叠加到干净记录上 |
sigamp |
WFDB 工具,测量信号与噪声幅度,供 nst 标定使用 |
xform |
WFDB 工具,用于重采样;nst 在采样率相差 10% 以上时调用它 |
| 协议注释文件 | 记录加噪起止时刻与缩放系数的注释文件,本库未随发布 |
| Holter | 便携式长时程心电监护,受试者随身携带记录仪活动 |
| ODC-BY | 开放数据共享署名许可(Open Data Commons Attribution License) |
| PhysioNet | 由 MIT 等机构维护的生物医学信号数据平台 |
附录 A:核心数字核对表
| 项 | 值 | 出处 |
|---|---|---|
| 记录总数 | 15 条 | RECORDS;官方摘要(12+3) |
| 加噪心电记录数 | 12 条 | RECORDS;官方摘要 |
| 纯噪声记录数 | 3 条(bw、em、ma) |
RECORDS;官方数据描述段 |
| 每条通道数 | 2 | 15 条头文件记录行第 2 字段 |
| 采样率 | 360 Hz | 15 条头文件记录行第 3 字段 |
| 每条采样点数 | 650000 | 15 条头文件记录行第 4 字段 |
| 每条时长 | 650000÷360 ≈ 1805.6 秒 | 由头文件字段换算 |
| 总时长 | 15 条各约半小时,合计约 7.5 小时 | 由官方「半小时」表述与条数换算 |
| 信噪比档位 | 24、18、12、6、0、−6 dB,共 6 档 | 官方页面表格;nstdb.txt |
| 心电记录增益 | 200(1024),即 200 ADC 单位/毫伏、基线 1024 |
12 条加噪记录头文件信号行 |
| 噪声记录增益 | 0(未校准) | bw.hea、em.hea、ma.hea |
| 位分辨率 | 加噪记录 11;噪声记录 12 | 头文件信号行第 4 字段 |
| 存储格式 | 24/18/12/6 dB 用 212;0/−6 dB 用 16 | nstdb.doc;头文件信号行第 2 字段 |
| 通道名 | 加噪记录 MLII、V1;噪声记录 noise1、noise2 | 头文件信号行末字段 |
| 单条信号体积 | 约 1.9 MB(212)/约 2.5 MB(16) | 归档目录清单 |
| 参考标注体积 | 118 系列约 4.5 KB;119 系列约 4.7 KB | 归档目录清单 |
| 标注来源 | 118 与 119 原参考标注的拷贝 | nstdb.txt;nstdbgen- 的 atruth.* 重命名步骤 |
| 注释文件角色 | 参考心搏、节律与信号质量标注 | ANNOTATORS |
| 学习期长度 | 5 分钟无噪 | 官方页面;nst(1) 文档 |
| 交替周期 | 2 分钟加噪 + 2 分钟干净 | 官方页面;nst(1) 文档 |
| 第一版记录数 | 15 条(12 条加噪 + oldbw/oldem/oldma) |
old/ 目录清单 |
| 第一版重算档位示例 | 118_02 两路 19.79 dB 与 14.38 dB |
oldnstdb.txt;nst(1) 文档 |
| 甚低频处理 | 已去除 0.05 Hz 以下长期漂移 | nstdb.txt |
| 许可 | ODC-BY 1.0,无需注册 | 官方页面 License 段 |
| 版本与发布日 | 1.0.0,1999 年 8 月 3 日 | 官方页面版本列表 |
| DOI | 10.13026/C2HS3T | 官方页面;库内 DOI 文件 |
| 原始论文 | Computers in Cardiology 1984; 11:381-384 | 官方页面 Citation 段 |
| 数据本体生成时间 | 1992 年 8 月 | nstdb.doc 署名;nstdbgen 首行 |
附录 B:完整参考文献
| 编号 | 文献 | 链接 | 用途 |
|---|---|---|---|
| 1 | MIT-BIH Noise Stress Test Database v1.0.0 | https://physionet.org/content/nstdb/1.0.0/ | 摘要、数据描述、许可、版本、引用规范 |
| 2 | 随库文档 nstdb.doc / nstdb.txt |
归档目录内 nstdb.txt |
记录构成、格式差异、第一版说明 |
| 3 | 生成脚本 nstdbgen / nstdbgen- |
归档目录内同名文件 | 12 条记录的生成命令与重命名步骤 |
| 4 | WFDB 应用指南 nst(1) |
https://archive.physionet.org/physiotools/wag/nst-1.htm | 信噪比定义、标准协议、噪声记录描述 |
| 5 | WFDB 应用指南 header(5) |
https://archive.physionet.org/physiotools/wag/header-5.htm | 头文件字段含义、增益与基线定义 |
| 6 | Moody GB, Muldrow WE, Mark RG(1984) | Computers in Cardiology 11:381-384 | 原始方法论文 |
| 7 | PhysioNet 平台综述(2026,Nature Health) | https://doi.org/10.1038/s44360-026-00096-z | 托管模式与引用规范 |
| 8 | MIT-BIH 心律失常库(母库) | https://physionet.org/content/mitdb/ | 118、119 原记录与标注 |
相关数据集导航
以下为站内 AI-Ready 数据集百科中与本词条共享多个主题标签的相关数据集,按相关度降序排列:
- mit-bih-arrhythmia—共享标签:生理信号 / 心电信号 / 算法评测
- macecgdb—共享标签:生理信号 / 心电信号 / 噪声与伪迹
- apnea-ecg—共享标签:生理信号 / 心电信号 / 公开数据集
- physionet-cinc-2017—共享标签:心电信号 / 算法评测 / 公开数据集
- cinc-2011—共享标签:生理信号 / 心电信号 / 算法评测
- barcelona-sicu-signals—共享标签:生理信号 / 波形 / 公开数据集
- deepfake-ecg—共享标签:心电信号 / 合成数据 / 算法评测
- ptb-xl—共享标签:生理信号 / 心电信号 / 公开数据集
- mit-bih-afdb—共享标签:生理信号 / 心电信号 / 长时程
- cinc-2014—共享标签:生理信号 / 心电信号 / 算法评测
- ecg-image-database—共享标签:心电信号 / 公开数据集
- georgia-12-lead-ecg-challenge—共享标签:心电信号 / 算法评测 / 公开数据集
- ecgrdvq—共享标签:生理信号 / 心电信号 / 公开数据集
- kingston-icu-af—共享标签:生理信号 / 心电信号 / 波形
导航说明:本章节由全站统一标签体系自动计算生成(标签重合度算法),双向可达;点击链接可跳转至对应数据集词条。

