信息速览
去趋势波动分析(Detrended Fluctuation Analysis,DFA)会给任何一条足够长的序列算出一个标度指数。问题在于,真实的生理信号从不告诉你它自己的指数是多少。心跳间期、步态间期、脑电幅度,你只能拿到一个估计值,而这个估计值对不对没有任何外部参照——趋势会把它整体抬高,截断会在某个尺度上压出一个折点,尖峰会在局部制造一段假的标度区间。这不是纯理论的担心:同一段心率序列,去趋势的阶数换一换,双对数图上的直线斜率就能差出可观的一截,而两条曲线各自都拟合得很好看。
TNS 趋势与非平稳基准集就是为了让这个"没有真值"的困境有解而做的。它由波士顿大学高分子研究中心与哈佛医学院的统计物理小组生成,2003 年 3 月放到 PhysioNet 上,一共 28 条合成序列,每条是一个单列的 ASCII 数字文件。它的关键设计只有一句:每条序列的相关指数在生成时就定死了,并且写进文件名里;随后在这个已知噪声上叠加人为的线性趋势、正弦趋势、幂律趋势,或者截断、尖峰、局部标准差跳变、局部相关指数混合。你把 DFA 跑上去,得到的指数与文件名里那个数之间的差,就是方法本身在这个条件下的偏差。
这决定了它的价值是"负"的:它不提供可以喂给模型的数据量,它提供可以证伪的尺子。28 条序列里没有一条来自任何人,也没有一个采样率——它衡量的是算法,不是生理。一屏速览见下表。
| 维度 | 内容 |
|---|---|
| 全名 | Surrogate Data with Correlations, Trends, and Nonstationarities |
| 发布方 | PhysioNet;序列由 Plamen Ch. Ivanov、Zhi Chen、Kun Hu 生成并贡献 |
| 首次发布 | 2003 年 3 月 7 日,版本 1.0.0 |
| 最近改动 | 2019 年 2 月 20 日更新 SHA256SUMS.txt;信号文件时间戳为 2002 年 10 月 15 日 |
| 序列条数 | 28 条:6 条平稳相关、7 条带趋势、15 条带非平稳性 |
| 受试者/患者数 | 0;全部为合成序列,不涉及人或动物 |
| 单条长度 | 2^17 = 131072 点(24 条);2^18 = 262144 点(第三组局部标准差类 4 条) |
| 通道与采样率 | 单列,无导联概念;无采样率,时间轴为整数下标 |
| 文件格式 | 单列 ASCII 文本,每行一个十进制数,gzip 压缩为 .txt.gz |
| 数据总量 | 官方页面标注未压缩合计 18.1 MB,整包 ZIP 为 18.3 MB |
| 真值来源 | 相关指数 alpha 与长度 Nmax 编码在文件名里;趋势与非平稳参数列在官方页面 |
| 许可 | Open Data Commons Attribution License v1.0(ODC-BY 1.0),开放访问,无需注册 |
| DOI | 10.13026/C2KK54,指向版本 1.0.0 |
| 配套论文 | Phys Rev E 64:011114(2001,趋势);Phys Rev E 65:041107(2002,非平稳性) |
| 典型用途 | 标度估计方法的误差标定、趋势与非平稳性影响的量化、方法学教学与结果复现 |
§1 它要解决的具体麻烦
1.1 一个没有真值的估计量
长程相关性的研究里有一个结构性尴尬。DFA 这类方法的输出是一个数——标度指数 alpha,它刻画序列的涨落如何随观察尺度增长。方法本身很成熟:积分、分盒、每盒去趋势、算均方根涨落、在双对数坐标上拟合直线,斜率就是 alpha。整套流程在任何一条够长的序列上都能跑通,也总能给出一条看起来相当直的线。
麻烦在于输出无法校验。真实的心率序列、步态序列、脑电序列,你不知道它的 alpha 真值是多少,所以你无法区分三种情况:估计值是对的;估计值被某种趋势抬高了;估计值因为序列里有截断或尖峰而只在某个尺度区间内成立。三种情况在图上长得几乎一样,都是一条直线,只是斜率不同。这不是精度不够的问题,是缺一把尺子。
真实数据补不上这把尺子,原因是干扰项无法被关掉。趋势不是可以勾选的选项:一段二十小时的心率记录里,昼夜节律、体位改变、药物起效都会各自贡献一条缓慢变化的曲线,你没有办法只要"没有趋势的同一段心率"。截断也一样,导联脱落、设备换电池、患者上厕所都会在记录里留下缺口,而缺口出现的位置与长度不受控制。所以想量化这些因素的影响,唯一可控的做法是自己造数据,把每一个干扰项的强度设成参数。
唯一能补上这把尺子的做法,是造一批 alpha 已知的序列,然后人为地往里加那些会干扰估计的因素,看估计值偏离多少。这就是 TNS 的全部动机。它的设计里没有病人、没有设备、没有采集协议,因为这些都会引入未知的真值——恰恰是要排除的东西。
1.2 三条常见的错误期待
第一条,把它当成生理数据库来找"受试者"。官方页面通篇没有出现受试者、患者、年龄、性别。它不是从人身上录的,是从生成算法里出来的。带着"找一批心跳序列"的期待打开它,会立刻发现既没有采样率也没有单位。
第二条,把它当成训练集。28 条序列、每条一个参数组合,任何一个模型都能在几轮之内把它记全。它的用途是标定,不是训练。真正该跑的实验是把你的估计算法喂进去,把输出与文件名里的设定值做差。
第三条,以为文件名里的 alpha 一定能被 DFA 还原。官方页面直接否掉了这个期待,并且给出了一条重要的修正:对反相关信号,DFA 在小尺度上会高估标度指数。正确做法是先对原信号积分再跑 DFA,并且用 F(n)/n 对 n 的关系而不是 F(n) 对 n 的关系去取斜率。这条提示写在官方页面的数据描述段里,来自配套的第二篇论文。
1.3 它能给到的与给不到的
| 你的需求 | 它给的 | 够不够 |
|---|---|---|
| 标定 DFA 在平稳相关信号上的偏差 | 6 条 alpha 从 0.1 到 1.5 的平稳序列 | 够,覆盖反相关到强正相关 |
| 量化线性趋势把指数拉偏多少 | 3 条同 alpha、斜率 2^-16 到 2^-8 的线性趋势序列 | 够,斜率跨 256 倍 |
| 量化周期趋势的影响 | 2 条正弦趋势序列,周期同为 128 | 够做对照,周期取值只有一种 |
| 量化幂律趋势的影响 | 2 条幂律趋势序列,幂次 0.4 与 -0.7 | 够做对照,只有两个幂次 |
| 量化截断造成的偏差 | 4 条截断序列,概率 0.05 与 0.50、宽度 20 | 够做对照,宽度只有一种 |
| 量化尖峰造成的偏差 | 4 条尖峰序列,含"仅尖峰"版本 | 够,可分离尖峰项本身 |
| 量化局部方差跳变的影响 | 4 条序列,sigma 1 与 4,占比 0.05 与 0.95 | 够做对照,只有一组 sigma 对 |
| 量化局部相关混合的影响 | 3 条序列,含两个分量与合成信号 | 够,且提供分量便于叠加检验 |
| 训练一个标度指数的预测模型 | 无 | 不够,28 条样本不支撑训练 |
| 研究真实生理信号的生理机制 | 无 | 不够,序列是合成的,没有生理语义 |
| 做多中心或跨人群泛化 | 无 | 不涉及,没有人群维度 |
| 研究非线性动力学或混沌 | 无 | 不涉及,官方页面未给出生成机制 |
1.4 你的处境与它能帮到的事
| 你的处境 | 它能帮你什么 | 下一步该做什么 |
|---|---|---|
| 你写了一个 DFA 实现,不知道对不对 | 用 6 条平稳序列做自检,输出应逼近文件名里的 alpha | 先跑 alpha=0.5 那条,它最接近无相关;再跑 0.1 与 1.5 两端 |
| 你在比较几种去趋势阶数 | 同一条带趋势序列上分别用一阶、二阶去趋势,看指数差多少 | 用 trlina2 与 trpow1,两者代表不同类型的趋势 |
| 你在处理有缺失段的长记录 | 4 条截断序列给出"切掉再拼接"这一常见预处理会造成什么后果 | 用 p=0.50 的两条看极端情况的偏离方向 |
| 你的数据里有运动伪迹或电尖峰 | 尖峰组提供"仅尖峰"文件,可把尖峰项单独取出做叠加实验 | 用 sp02p05a1sp 与 sp08p05a10sp 做纯尖峰项 |
| 你要在论文里证明预处理步骤是必要的 | 可给出"未预处理时偏差 X、预处理后偏差 Y"的对照 | 全程固定盒长范围与拟合区间,否则对照不成立 |
| 你在教时间序列分析 | 28 条序列能演示趋势、截断、尖峰各自造成的特征形态 | 配合官方页面的参数说明讲,学生能自行复现 |
| 你想复现 2001 或 2002 年那两篇论文的图 | 序列即论文所用数据,参数一一对应 | 注意论文用的是当年的盒长与拟合口径,需按论文设定 |
1.5 一句话判断
它不适合当"训练集",而适合当"量具":在已知真值的序列上,把一个只能输出数字的估计方法,变成一个有误差条的估计方法。
1.6 不适合谁:四条边界
不适合拿来做统计泛化。 28 条序列,每条一种参数组合,没有重复、没有随机种子、没有误差条。任何"在 TNS 上平均偏差为多少"的表述都需要先说明这是对 28 个特定条件的枚举,不是抽样。
不适合拿来推断生理机制。 序列不含任何生理语义。用它得出的结论只能关于算法——某个估计方法在某种扰动下偏多少——不能关于心脏、步态或大脑。
不适合拿来做跨方法的大规模基准评测。 它只有三组扰动类型,每组的参数取值也很稀疏(周期只有 128,宽度只有 20,sigma 只有 1 与 4)。想系统扫描参数空间,得自己按官方页面给出的公式重新生成。
不适合在没读官方页面那句提示的情况下跑反相关序列。 alpha 为 0.1 与 0.2 的两条是反相关,官方页面明确说明 DFA 在小尺度上会高估。直接套常规流程得到的指数会偏大,而这个偏大很容易被误读成"方法失效"或"数据有问题"。
§2 数据构成与规格
2.1 三组七小类的分组结构
官方页面把内容分成三组,文件目录里实际列出 28 个 .txt.gz。三组之间不是并列的"难度递增",而是分别对应三类不同的失效来源。
| 组 | 小类 | 条数 | 要暴露的问题 |
|---|---|---|---|
| 第一组 | 平稳相关信号 | 6 | 方法在干净条件下的基线偏差 |
| 第二组 a | 线性趋势 | 3 | 趋势的"表观标度"与噪声标度竞争产生交叠点 |
| 第二组 b | 正弦趋势 | 2 | 周期项在特定尺度上制造假标度区间 |
| 第二组 c | 幂律趋势 | 2 | 幂次的正负决定交叠点朝哪边移动 |
| 第三组 a | 截断段 | 4 | 拼接式预处理带来的不连续 |
| 第三组 b | 尖峰 | 4 | 离群点污染标度,且与幅值强相关 |
| 第三组 c | 局部标准差不同 | 4 | 分段异方差制造局部标度差异 |
| 第三组 d | 局部相关指数不同 | 3 | 两段不同 alpha 的混合信号 |
七小类加起来 6+3+2+2+4+4+4+3,等于 28。第二组三小类合计 7 条,第三组四小类合计 15 条,与官方页面的 6、7、15 完全对上。
2.2 完整文件字典
第一组,六条平稳相关信号,长度均为 2^17:
| 文件名 | alpha | Nmax | 相关性质 |
|---|---|---|---|
| noise0117.txt.gz | 0.1 | 2^17 | 反相关 |
| noise0217.txt.gz | 0.2 | 2^17 | 反相关 |
| noise0517.txt.gz | 0.5 | 2^17 | 无长程相关(白噪声类) |
| noise0817.txt.gz | 0.8 | 2^17 | 正相关 |
| noise0917.txt.gz | 0.9 | 2^17 | 正相关 |
| noise1517.txt.gz | 1.5 | 2^17 | 强正相关 |
第二组,七条带趋势的信号,长度均为 2^17:
| 文件名 | 小类 | alpha | 趋势参数 |
|---|---|---|---|
| trlina1.txt.gz | 线性 | 0.1 | 斜率 Al = 2^-16 / 下标 |
| trlina2.txt.gz | 线性 | 0.1 | 斜率 Al = 2^-12 / 下标 |
| trlina3.txt.gz | 线性 | 0.1 | 斜率 Al = 2^-8 / 下标 |
| trsin1.txt.gz | 正弦 | 0.9 | 幅值 As = 2,周期 T = 128 |
| trsin2.txt.gz | 正弦 | 0.1 | 幅值 As = 2,周期 T = 128 |
| trpow1.txt.gz | 幂律 | 0.9 | 幂次 lambda = 0.4,幅值 Ap = 1000 / Nmax^lambda |
| trpow2.txt.gz | 幂律 | 1.5 | 幂次 lambda = -0.7,幅值 Ap = 0.01 / Nmax^lambda |
第三组,十五条带非平稳性的信号:
| 文件名 | 小类 | 关键参数 | Nmax |
|---|---|---|---|
| cut0117w20p95.txt.gz | 截断 | alpha = 0.1,截断概率 p = 0.05,宽度 W = 20 | 2^17 |
| cut0117w20p50.txt.gz | 截断 | alpha = 0.1,截断概率 p = 0.50,宽度 W = 20 | 2^17 |
| cut0917w20p95.txt.gz | 截断 | alpha = 0.9,截断概率 p = 0.05,宽度 W = 20 | 2^17 |
| cut0917w20p50.txt.gz | 截断 | alpha = 0.9,截断概率 p = 0.50,宽度 W = 20 | 2^17 |
| sp02p05a1.txt.gz | 尖峰 | 尖峰概率 p = 0.05,幅值 Asp = 1 | 2^17 |
| sp02p05a1sp.txt.gz | 尖峰 | 仅尖峰项,概率 p = 0.05,幅值 Asp = 1 | 2^17 |
| sp08p05a10.txt.gz | 尖峰 | 尖峰概率 p = 0.05,幅值 Asp = 10 | 2^17 |
| sp08p05a10sp.txt.gz | 尖峰 | 仅尖峰项,概率 p = 0.05,幅值 Asp = 10 | 2^17 |
| d2h4pd050118s.txt.gz | 局部标准差 | alpha = 0.1,sigma1 = 1,sigma2 = 4,p = 0.05 | 2^18 |
| d2h4pd950118s.txt.gz | 局部标准差 | alpha = 0.1,sigma1 = 1,sigma2 = 4,p = 0.95 | 2^18 |
| d2h4pd050918s.txt.gz | 局部标准差 | alpha = 0.9,sigma1 = 1,sigma2 = 4,p = 0.05 | 2^18 |
| d2h4pd950918s.txt.gz | 局部标准差 | alpha = 0.9,sigma1 = 1,sigma2 = 4,p = 0.95 | 2^18 |
| cut010917p90w20_sum.txt.gz | 局部相关 | 混合信号,alpha1 = 0.1 占 90%,alpha2 = 0.9 占 10%,W = 20 | 2^17 |
| cut010917p90w20_comp1.txt.gz | 局部相关 | 仅分量一,alpha1 = 0.1,W = 20 | 2^17 |
| cut010917p90w20_comp2.txt.gz | 局部相关 | 仅分量二,alpha2 = 0.9,W = 20 | 2^17 |
需要提醒两处官方页面的笔误。第一处,页面把第二条截断序列写成 ut0117w20p50.txt.gz,文件目录里的实际文件名是 cut0117w20p50.txt.gz,缺了一个 c。第二处,页面在第三组 c 小类里只明确写出前三条的参数,第四条的参数行被截断,按命名规则与目录中的文件名可确认为 d2h4pd950918s.txt.gz。这两处都以文件目录为准。
2.3 文件名的编码规则
文件名不是随意起的,它是一套紧凑的参数编码。拆开看:noise0117 是 noise + 01 + 17,表示 alpha = 0.1、Nmax = 2^17;noise1517 则是 alpha = 1.5、Nmax = 2^17。这里的规律是 alpha 取一位小数后去掉小数点,所以 1.5 写成 15。
| 片段 | 出现位置 | 含义 | 例子 |
|---|---|---|---|
noise |
第一组 | 平稳相关噪声 | noise0517 |
trlin |
第二组 a | 线性趋势 | trlina3 |
trsin |
第二组 b | 正弦趋势 | trsin1 |
trpow |
第二组 c | 幂律趋势 | trpow2 |
cut |
第三组 a、d | 截断或分段拼接 | cut0917w20p95 |
sp |
第三组 b | 尖峰 | sp08p05a10 |
d2h4p |
第三组 c | 两段不同标准差 | d2h4pd950118s |
| 两位数字 | 紧跟类型名 | alpha 的十分之一 | 01 → 0.1,15 → 1.5 |
17 / 18 |
长度位 | Nmax = 2^17 或 2^18 | 0117 → alpha 0.1、2^17 |
w20 |
第三组 a、d | 段宽度 W = 20 | cut0117w20p95 |
p95 / p50 |
第三组 a | 保留概率 0.95 / 0.50,对应截断概率 0.05 / 0.50 | cut0917w20p50 |
p05 |
第三组 b | 尖峰概率 0.05 | sp02p05a1 |
a1 / a10 |
第三组 b | 尖峰幅值 1 / 10 | sp08p05a10 |
sp 后缀 |
第三组 b | 仅含尖峰项,不含底噪 | sp02p05a1sp |
p90 |
第三组 d | 第一分量占比 90% | cut010917p90w20_sum |
_sum / _comp1 / _comp2 |
第三组 d | 合成信号 / 分量一 / 分量二 | cut010917p90w20_comp2 |
第三组 c 的命名最绕:d2h4pd050118s 可以拆成 d2h4p(两段,标准差 2 倍关系里取 4)、d05(占比概率 0.05)、01(alpha = 0.1)、18(2^18)、s(序列)。这一组是唯一使用 2^18 长度的组,文件目录里这四个文件的压缩体积约为其余文件的两倍,与长度翻倍一致。
2.4 一条序列的完整解剖
每个文件解出来之后是一列十进制数,一行一个,行数等于 Nmax。没有表头、没有时间戳、没有单位、没有第二列。官方页面只用一句话交代了格式:每个数据文件含一列 ASCII 数据;因为文件较大,以 gzip 压缩文本提供。
数值本身没有单位,这一点要反复强调。文件里的一列数字既不是毫伏也不是毫秒,只是生成算法吐出来的无量纲量。因此任何"这条序列的幅度是多大"的问题都没有答案,能问的只有相对量——同一条序列内部各段的标准差之比、不同序列之间的方差之比。这也意味着把某条序列的数值直接当作某种生理量的模拟值去解释是不成立的:它没有量纲,不能与任何真测量量对照。
这里有一个必须讲清楚的显示问题。官方页面把长度写成 Nmax = 217,第三组 c 写成 Nmax = 218。这是上标在网页渲染时丢失的结果,原式是 2 的 17 次方与 2 的 18 次方,即 131072 与 262144。四条证据支持这个读法:一是同页面在别处把幅值写成 2-16 与 2-8 的形式,说明负号与上标在该页面上同样会退化;二是 2^17 与 2^18 是这类标度研究的典型长度,与"最大盒长取 Nmax/10"的建议配套;三是目录里第三组 c 四个文件的压缩体积约为同组其余文件的两倍,与长度翻倍一致;四是把 noise0117.txt.gz 下载解压后按非空行计数得到 131072 行,d2h4pd050118s.txt.gz 得到 262144 行,与 2^17、2^18 完全吻合。每个数值独占一行,行内带填充空格,行宽不固定。
读取方式如下:
import gzip, io, urllib.request
import numpy as np
def load_tns(fname):
#-- 官方文件目录路径,fname 形如 noise0117.txt.gz
url = 'https://physionet.org/files/tns/1.0.0/tns/' + fname
raw = gzip.decompress(urllib.request.urlopen(url).read())
x = np.loadtxt(io.BytesIO(raw))
return x
x = load_tns('noise0517.txt.gz')
print(x.shape, x.dtype, x[:3])
2.5 与同类资源的字段差异
| 对比项 | TNS | 典型生理波形库 | 典型生理间期库 |
|---|---|---|---|
| 数据来源 | 生成算法 | 采集设备 | 采集设备加标注 |
| 受试者 | 无 | 有,带编号 | 有,带编号 |
| 时间轴 | 整数下标 | 采样率换算的秒 | 事件时刻 |
| 物理单位 | 无 | 毫伏、微伏等 | 毫秒 |
| 通道数 | 1 | 一到十二或更多 | 一到两列 |
| 真值标签 | 有(在文件名里) | 部分有(标注) | 部分有(标注) |
| 文件数 | 28 | 数十到数千 | 数十到数百 |
| 压缩 | gzip 文本 | 多为二进制加头文件 | 多为二进制加头文件 |
| 许可 | ODC-BY 1.0 | 多为 ODC-BY 或 CC | 多为 ODC-BY 或 CC |
差别最要紧的一行是"真值标签"。生理库的标注是对观测的人工判断,本身有误差;TNS 的 alpha 是生成参数,是定义层面的真值。这一行决定了它只能用于方法标定,不能用于生理推断。
2.6 参数的物理含义
| 参数 | 官方写法 | 含义 | 取值范围(本数据集内) |
|---|---|---|---|
| alpha | alpha | 相关指数,度量序列中相关的程度 | 0.1、0.2、0.5、0.8、0.9、1.5 |
| Nmax | Nmax | 序列总点数 | 2^17、2^18 |
| Al | slope of linear trend | 线性趋势斜率,单位为每个下标 | 2^-16、2^-12、2^-8 |
| As | Amplitude of trend | 正弦趋势幅值 | 2 |
| T | period | 正弦趋势周期 | 128 |
| lambda | power | 幂律趋势的幂次 | 0.4、-0.7 |
| Ap | Amplitude | 幂律趋势幅值系数 | 1000、0.01 |
| p(截断) | seg. cutout probability | 被切掉部分的概率 | 0.05、0.50 |
| W | Width | 被切掉段的宽度 | 20 |
| p(尖峰) | spikes probability | 尖峰出现概率 | 0.05 |
| Asp | Amplitude | 尖峰幅值 | 1、10 |
| sigma1 / sigma2 | local standard deviation | 两段的局部标准差 | 1、4 |
| p(局部) | probability | 取 sigma2 或 alpha2 的概率 | 0.05、0.95 |
| alpha1 / alpha2 | local correlations | 两段的局部相关指数 | 0.1、0.9,占比 90% / 10% |
alpha 的取值区间本身就是一条重要信息。0.5 以下为反相关,0.5 相当于无长程相关,0.5 以上为正相关,1.5 已经接近布朗运动的强相关端。六条平稳序列把这条轴从 0.1 拉到 1.5,其中 0.1 与 0.2 两条正是官方页面特别提示"会被高估"的反相关情形。
§3 它是谁的数据
3.1 贡献者
官方页面的贡献者一栏写明:这些数据由 Plamen Ch. Ivanov、Zhi Chen 和 Kun Hu 贡献,他们用这些数据完成了两篇论文。三位作者的署名单位出现在论文页上:波士顿大学高分子研究中心与物理系,以及哈佛医学院贝斯以色列女执事医疗中心。第一篇论文还有两位合著者,分别是西班牙马拉加大学应用物理二系的 Pedro Carpena 与波士顿大学的 H. Eugene Stanley。
这个作者组合解释了数据集的气质:统计物理背景的课题组,关心的是标度律与临界现象中的通用性质,生理信号只是他们拿来验证方法的一类载体。这也解释了为什么数据集里没有临床变量——它的目标读者是做标度分析的人,不是做临床预测的人。
3.2 时间线
| 时间 | 事件 | 出处 |
|---|---|---|
| 2001 年 | 第一篇论文发表,讨论趋势对 DFA 的影响 | Phys Rev E 64:011114 |
| 2002 年 | 第二篇论文发表,讨论非平稳性对 DFA 的影响 | Phys Rev E 65:041107 |
| 2002 年 10 月 15 日 | 28 个数据文件的时间戳 | 文件目录 |
| 2003 年 3 月 7 日 | 版本 1.0.0 在 PhysioNet 发布 | 官方页面版本历史 |
| 2019 年 2 月 20 日 | SHA256SUMS.txt 更新 | 文件目录 |
数据先于发布。两篇论文在 2001 与 2002 年发表,文件时间戳停在 2002 年 10 月,正式发布是 2003 年 3 月——顺序是"论文先出、数据后补",这在 PhysioNet 上是常见做法:论文里报告的结果需要可复现,作者就把用过的序列交出来。
3.3 生成场景
官方页面对生成方式的交代相当克制,只说每组序列对应的参数,以及"这些信号的详细描述见原始文章"。它没有说明用的是哪种相关噪声生成算法、用的是什么伪随机数发生器、种子是多少。这意味着两件事:一是序列本身不可由第三方精确重建,只能下载;二是任何"换一个种子再生成一批"的做法都需要自己实现生成器,官方没有提供代码。
从参数设计反推,能确定的只有这些:序列是先按设定的 alpha 生成一段平稳相关噪声,再按官方列出的参数叠加趋势或非平稳扰动。例外是第三组 b 的两个 sp 后缀文件——它们只含尖峰项本身,不含底层噪声,官方页面明确标注为 “spikes signal only”。这个设计很实用:拿到纯尖峰项之后,可以自己叠加到任意一条平稳序列上,做尖峰浓度与幅值的组合实验。
3.4 来源层次
| 层次 | 内容 | 可信度 | 说明 |
|---|---|---|---|
| 第一层 | 官方页面写明的文件清单与参数 | 高 | 直接来自项目主页的数据描述段 |
| 第二层 | 文件目录里的文件名与体积 | 高 | 可逐一访问核对 |
| 第三层 | 两篇配套论文及其网页版摘要 | 高 | 论文页随数据集一起托管 |
| 第四层 | 生成算法与随机种子 | 无 | 官方页面未提供,不可推断 |
| 第五层 | 各序列的实际标度估计值 | 无 | 官方页面未给出,需自行按统一口径计算 |
第五层这一栏要特别说一句。官方页面没有给出"用 DFA 跑这些序列会得到多少"的参考表,所以本数据集本身不提供期望输出。这既是它的优点(不会被参考值锚定),也是使用门槛(必须自己实现方法)。
§4 它最独特的东西
4.1 稀缺性:真值已知的标度基准很少
生理信号研究里,绝大多数数据集给的是观测值加标注,标注本身是人工判断,误差未知。要评价一个标度估计方法,你需要的恰恰相反:一个真值确定、扰动也确定的序列。这类"方法学基准"在公开数据平台上数量很少,因为它们既不能支撑训练,也不能支撑临床结论,对以数据量为导向的项目毫无吸引力。
TNS 把这件事做到了一个很节制的程度:不做参数扫描,只做七个小类的典型条件;不追求序列条数,只保证每组条件都能对上一个明确的失效机制。28 条这个规模是刻意的选择——它足够覆盖三类失效,又不至于让人误以为可以做统计。
判断一个条件"典型不典型",要看它是否对应现实中真的会遇到的情形。截断对应的正是论文摘要里点明的那件事:实验记录中断后把几段拼起来,或者把不可靠的噪声段删掉再把剩下的部分接上——这两种做法在数据准备阶段极为常见,而它们对后续标度分析的影响却很少被量化。尖峰对应的是伪迹:心电里的电极接触瞬变、加速度计里的碰撞、脑电里的眼动与肌电爆发。局部标准差不同对应的是分段异质性:一段记录里患者先静卧后活动,两段的涨落幅度本就不在一个量级。局部相关指数不同对应的则是更棘手的情况——同一段记录里存在两种动力学状态交替,这在节律切换、睡眠分期、发作间期都可能出现。四类非平稳性都不是为了凑数而设计的,每一类都能在真实记录里找到对应物。
4.2 三类失效的对照
| 失效来源 | 对应文件 | 机制(据论文摘要) | 在双对数图上的表现 |
|---|---|---|---|
| 趋势 | 第二组 7 条 | 噪声的标度与趋势的"表观标度"竞争 | 出现交叠点,两侧斜率不同 |
| 截断 | 第三组 a 4 条 | 切掉再拼接破坏连续性 | 随截断比例与段大小出现交叠 |
| 尖峰 | 第三组 b 4 条 | 离群点污染涨落 | 随浓度与幅值出现交叠 |
| 局部异方差 | 第三组 c 4 条 | 分段的局部标准差不同 | 随两段比例出现交叠 |
| 局部相关混合 | 第三组 d 3 条 | 两段 alpha 不同 | 出现两个标度区间 |
第一篇论文的摘要把趋势情形的机制讲得很具体:交叠来自噪声标度与趋势表观标度之间的竞争;交叠位置本身也服从标度律,即交叠位置对趋势参数有长程幂律依赖;如果噪声与趋势互不相关,DFA 结果可以用"分别跑噪声与趋势再叠加"的规则精确预测;一旦这个叠加规则不成立,就说明噪声与趋势不独立,此时去掉趋势会改变噪声本身的相关性质。这四条合起来给出了一套可操作的判据:先看叠加规则成不成立,再决定能不能直接去趋势。
4.3 三个可以直接用的对照案例
案例一:趋势斜率如何移动交叠点。 trlina1、trlina2、trlina3 三条序列的 alpha 都是 0.1,只有线性趋势斜率不同,分别是 2^-16、2^-12、2^-8,相邻两档差 16 倍。固定其他一切条件,只动这一个参数,就能读出交叠点位置随斜率移动的规律。这是本数据集里最干净的单变量对照。
案例二:尖峰项能否被分离出来。 sp02p05a1 与 sp02p05a1sp 是一对:前者是带尖峰的完整信号,后者是同一批尖峰单独成列。把后者从前者的效应里减出来,可以判断尖峰造成的偏差有多少来自尖峰本身、有多少来自尖峰与底噪的相互作用。幅值 1 与幅值 10 另有一对,可以做幅值扫描。
案例三:局部相关混合的分量拆解。 cut010917p90w20_sum 是 alpha 0.1 占九成、alpha 0.9 占一成的混合信号,_comp1 与 _comp2 是两个纯分量。三个文件放在一起,可以直接检验"混合信号的标度是否等于两个分量标度的加权组合"——若不相等,差出来的部分就是混合带来的非线性效应。
4.4 参数覆盖的粒度
| 维度 | 取值 | 粒度评价 |
|---|---|---|
| alpha | 0.1、0.2、0.5、0.8、0.9、1.5 | 六点,两端到中间都有,够画趋势 |
| 线性趋势斜率 | 2^-16、2^-12、2^-8 | 三点,跨 256 倍,跨度够但间距粗 |
| 正弦周期 | 128 | 单点,只能说明"存在周期项时如何" |
| 幂次 lambda | 0.4、-0.7 | 两点,一正一负,构成方向对照 |
| 截断概率 | 0.05、0.50 | 两点,一个轻微一个极端 |
| 截断宽度 | 20 | 单点 |
| 尖峰浓度 | 0.05 | 单点 |
| 尖峰幅值 | 1、10 | 两点,相差十倍 |
| 局部标准差对 | 1 与 4 | 单点 |
| 局部相关占比 | 90% / 10% | 单点 |
这张表是评估"能不能用它回答你的问题"的第一道筛子。多数维度只有一到两个取值,因此它适合回答定性问题——这类扰动会不会造成偏差、偏差朝哪个方向——不适合回答定量问题——偏差随参数变化的精确函数形式。后者需要按官方页面给出的公式自行生成序列。
4.5 边界条件
三条边界写在官方页面或论文页上,直接影响能不能得到可解释的结果。
第一条,最大盒长。官方页面转述第二篇论文的建议:为了让 F(n) 的估计更准确,使用的最大盒长 n 取 Nmax/10。对 2^17 的序列,就是 13107。盒长上限设得更大,末端盒子数量太少,均方根涨落的估计不稳。
第二条,反相关序列的处理。alpha 小于 0.5 时,DFA 在小尺度上会高估真实相关强度。修正办法是先把原信号积分,再用 F(n)/n 对 n 的关系取斜率,而不是用 F(n) 对 n。跑 alpha = 0.1 与 0.2 两条时不遵守这条,得到的偏差里会混进一个方法缺陷,无法归因到数据。
第三条,序列长度固定。24 条是 2^17,4 条是 2^18,没有别的长度。想研究长度对估计的影响(这是标度分析里的经典问题),这 28 条只能提供两个点,且这两点还绑着一个混杂因素:长度更长的那四条恰好全部属于局部标准差类。于是"长度变化造成的差异"与"异方差造成的差异"在数据集中无法分离,想单独研究长度效应必须自己生成序列。
§5 怎么拿到
5.1 目录结构
| 路径 | 内容 |
|---|---|
/files/tns/1.0.0/ |
版本根,含 SHA256SUMS.txt |
/files/tns/1.0.0/tns/ |
28 个 .txt.gz 数据文件 |
/files/tns/1.0.0/tns/paper1/ |
第一篇论文的网页版与图片 |
/files/tns/1.0.0/tns/paper2/ |
第二篇论文的网页版与图片 |
/files/tns/1.0.0/tns/index.shtml |
旧版说明页 |
数据文件全部平铺在一个目录里,没有子目录、没有按组分类。分组只能靠文件名前缀判断。两个 paper 目录是论文的早期网页版,内容比期刊版略简,但摘要完整,且随数据集一起托管,取用方便。
5.2 批量下载
#-- 递归取整个版本目录;-np 保证不爬到上级目录
wget -r -N -c -np https://physionet.org/files/tns/1.0.0/
#-- 官方页面给出的 AWS 命令行方式,免签名
aws s3 sync --no-sign-request s3://physionet-open/tns/1.0.0/ DESTINATION
#-- 校验:下载后用官方清单比对
cd tns/1.0.0 && sha256sum -c SHA256SUMS.txt
官方页面同时给出整包 ZIP(18.3 MB)与未压缩合计(18.1 MB)两个数字。需要注意这两个数字不是同一个口径:ZIP 是压缩后的包体积,18.1 MB 是全部文件解出来后的总量。
5.3 流式读取
不需要先落盘,可以直接从 URL 解压读取:
import gzip, io, urllib.request
import numpy as np
BASE = 'https://physionet.org/files/tns/1.0.0/tns/'
def load(fname):
#-- 一行一个数,无表头;gzip 直接在内存里解
raw = gzip.decompress(urllib.request.urlopen(BASE + fname).read())
return np.loadtxt(io.BytesIO(raw))
x = load('noise1517.txt.gz')
print(len(x), x.mean(), x.std())
28 个文件全量不到 20 MB 未压缩,一次读完毫无压力。麻烦只在网络:逐文件请求会有 28 次往返,做批量实验时建议先 wget 到本地。
5.4 转成通用的表结构
合成序列进表格意义不大,真正要转的是"参数表"——把文件名里编码的 alpha、Nmax 与扰动参数解析成列,作为实验设计的自变量:
import re
import pandas as pd
#-- 文件名 -> 参数(只解析官方页面明确写出的字段)
def parse(fname):
f = fname.replace('.txt.gz', '')
d = {'file': f, 'alpha': None, 'nmax': None, 'kind': None}
m = re.match(r'noise(\d\d)(\d\d)$', f)
if m:
d.update(kind='stationary', alpha=int(m.group(1)) / 10,
nmax=2 ** int(m.group(2)))
return d
for pat, kind in [(r'trlin', 'linear_trend'), (r'trsin', 'sinusoid_trend'),
(r'trpow', 'powerlaw_trend'), (r'sp', 'spikes'),
(r'd2h4p', 'local_sigma'), (r'cut', 'cutout')]:
if f.startswith(pat):
d['kind'] = kind
return d
rows = [parse(n) for n in ['noise0117.txt.gz', 'noise1517.txt.gz',
'trlina3.txt.gz', 'sp08p05a10sp.txt.gz']]
print(pd.DataFrame(rows))
这段代码只处理六条平稳序列的完整解析,其余只标出小类。把参数列解析全需要逐组写规则,工作量不大但容易漏——更稳妥的做法是直接按官方页面的清单手抄一张 28 行的参数表,把文件名作为主键。
5.5 一个最小可用的 DFA 与参数映射
import numpy as np
def dfa(x, scales=None, order=1):
#-- 第一步:减去均值后积分,得到"轮廓"序列
y = np.cumsum(x - np.mean(x))
N = len(y)
if scales is None:
#-- 官方页面建议最大盒长取 Nmax/10;此处取到该上限
hi = N // 10
scales = np.unique(np.logspace(np.log10(8), np.log10(hi), 20).astype(int))
scales = scales[(scales >= 8) & (scales <= hi)]
fn = []
t = np.arange(max(scales))
for n in scales:
m = (N // n) * n
seg = y[:m].reshape(-1, n).T #-- 每列一个盒
tt = t[:n]
#-- 每盒做多项式去趋势,order=1 即线性去趋势
A = np.vstack([tt ** k for k in range(order, -1, -1)]).T
coef, *_ = np.linalg.lstsq(A, seg, rcond=None)
res = seg - A @ coef
fn.append(np.sqrt(np.mean(res ** 2, axis=0)))
f = np.array([v.mean() for v in fn])
slope = np.polyfit(np.log(scales), np.log(f), 1)[0]
return slope, scales, f
x = load('noise0917.txt.gz') #-- 文件名里的 alpha = 0.9
s, sc, f = dfa(x)
print('估计指数 %.3f 设定值 0.9 偏差 %+.3f' % (s, s - 0.9))
把 28 条都跑一遍、每条都减去文件名里的设定值,得到的就是你的实现在这 28 个条件下的偏差表。这份表才是这个数据集真正的产物。要注意的是它与盒长范围、去趋势阶数、拟合区间三者都有关,换任何一项都要重跑整套,不能只换一条。
5.6 五个最容易出错的地方
| 位置 | 错误写法 | 后果 | 正确做法 |
|---|---|---|---|
| 读文件 | 按纯文本打开 .txt.gz | 解出乱码或直接报错 | 先 gzip 解压再解析 |
| 长度理解 | 把 Nmax = 217 当成二百一十七 |
盒长与拟合区间全部设错 | 读作 2^17 = 131072 |
| 反相关序列 | 直接跑常规 DFA 取斜率 | 小尺度高估,偏差归因错误 | 先积分,用 F(n)/n 对 n 取斜率 |
| 盒长上限 | 盒长一路取到 N/2 | 末端盒数太少,涨落估计不稳 | 最大盒长取 Nmax/10 |
| 文件名 | 照抄官方页面的 ut0117w20p50 |
下载 404 | 实际文件名是 cut0117w20p50 |
§6 与库内条目的关系
6.1 关系图谱
| 条目 | 主题 | 与 TNS 的关系 |
|---|---|---|
| fantasia | 健康年轻与老年受试者的心跳间期与呼吸信号 | 真实数据的对标对象:TNS 标定的方法最终用在它这类数据上 |
| physiozoo | 心率变异性与活动信号的哺乳动物数据集与工具 | 工具侧对照:分析管线一致,TNS 提供方法误差的参照 |
| nsrdb | 正常窦性心律的长时程心电 | 应用侧:标度分析常见的真实材料 |
| nsr2db | 正常窦性心律 RR 间期序列 | 应用侧:间期序列是标度分析的典型输入 |
| chfdb | 充血性心力衰竭患者的心电 | 应用侧:病理状态下的相关性改变是标度研究常见课题 |
| chf2db | 充血性心力衰竭患者的长时程心电 | 同上,覆盖更长 |
| mit-bih-afdb | 心房颤动长时程心电 | 应用侧:节律紊乱对标度估计的干扰与 TNS 的尖峰类扰动呼应 |
| gaitdb | 步态与神经退行性疾病相关信号 | 应用侧:步态间期也是标度分析的常见对象 |
| tremordb | 震颤患者的加速度与表面肌电 | 应用侧:震颤本身即一种周期性成分,与正弦趋势类对照 |
| tappy | 帕金森病相关的键盘敲击与运动信号 | 应用侧:运动序列的非平稳性常见于真实记录 |
这张表读起来像"一堆真实库围着一个合成库",这正是它的位置:真实库是被测量的对象,TNS 是测量工具的校准块。两者不构成竞争关系。
把关系倒过来看更有用。假设你要在 fantasia 那类真实心跳间期序列上报告一个标度指数,审稿人会问三个问题:你的实现有没有偏?你的预处理改变了结果没有?序列里那些明显的非平稳段被怎么处理的?前两个问题靠 TNS 就能给出量化的答案——在已知 alpha 的序列上跑一遍,偏差是多少就写多少,去趋势前后差多少就写多少。第三个问题 TNS 也能帮上忙:截断组与尖峰组给出的正是"这类非平稳段会怎样影响结果"的参照。所以它与真实库的关系不是并列,而是前置——先把尺子校准,再去量东西。
反过来说,只做真实库上的分析而不做任何标定,报告出来的指数就只是一个数字,读者无法判断它离真值有多远。这正是标度分析文献里结论难以互相比较的根因之一:不同研究组用不同的盒长范围、不同的去趋势阶数、不同的预处理流程,各自得到一个很漂亮的双对数直线,而彼此的斜率并不可比。
6.2 检索路径
| 你要找的东西 | 检索词 | 会落到哪里 |
|---|---|---|
| 标度指数的估计方法 | DFA、detrended fluctuation analysis |
§1.1 与 §5.5 |
| 趋势造成的交叠点 | crossover、trend、Phys Rev E 64 |
§2.2 第二组与 §4.2 |
| 非平稳性的三类 | nonstationarity、cutout、spikes |
§2.2 第三组与 §4.2 |
| 反相关序列的修正 | anti-correlated、integrate、F(n)/n |
§1.2 与 §4.5 |
| 真实数据上的对标 | fantasia、nsrdb、chfdb |
§6.1 |
| 生成方法与种子 | 官方页面未给出 | §3.3 与 §10 |
6.3 与其他库的分工判据
| 任务 | 主粮仓该用什么 | TNS 的位置 | 原因 |
|---|---|---|---|
| 标度估计方法的误差标定 | 无替代 | 主力 | 唯一提供真值的资源 |
| 趋势去不去的决策依据 | 无替代 | 主力 | 叠加规则可被直接验证 |
| 预处理必要性的论证 | 无替代 | 主力 | 同一序列可跑"预处理前后"对照 |
| 标度分析的教学演示 | 无替代 | 主力 | 参数写在文件名里,学生可对答案 |
| 真实生理信号的机制研究 | 生理数据库 | 不适用 | 合成数据无生理语义 |
| 心率变异性临床指标研究 | 生理数据库 | 不适用 | 无受试者、无结局 |
| 模型训练与基准跑分 | 大规模标注库 | 不适用 | 28 条序列不构成基准 |
| 多中心泛化验证 | 多中心库 | 不适用 | 无中心维度 |
前四行是它的全部领地,后四行一律不适用。判断标准只有一条:你要结论的对象是"方法"还是"生理"。前者用它,后者不要用。
§7 质量评估与局限性
7.0 阅读本节前的一个前置校正
先纠正一个常见误判:把"只有 28 条序列"当成质量缺陷。这 28 条不是采集能力不足的结果,而是一个方法学基准的合理粒度——它要覆盖三类失效,每类给出典型条件,而不是做参数扫描。评价它时不能用"越大越好"的尺子,而要问:在它能回答的那个问题上,这些条件够不够典型?
这个校正会改变五维评分的读法。规模一项它拿不到高分,但"真值可得性"上它几乎没有替代品。把这两件事混在一起看,会得出"太小了不值得用"的错误结论。
7.1 五维评分
按 DAIMS 的常用维度打分,每项 1–5 分,分数针对"作为标度估计方法的校准基准"这个用途:
| 维度 | 分数 | 理由 |
|---|---|---|
| 数据规模 | 2 | 28 条序列,够枚举不够抽样 |
| 真值质量 | 5 | alpha 为生成参数,是定义层面的真值 |
| 任务适配 | 5 | 三类失效各自有对应文件,条件典型 |
| 文档完整 | 4 | 参数逐条列出,但生成算法与种子缺失 |
| 可获取性 | 5 | 免注册、ODC-BY、体量小,一次下完 |
五项合计 21 分(满分 25)。分数结构很清晰:规模是唯一短板,真值与适配拉满。这正是一个"量具"该有的分数形状。
7.2 真值的两层
第一层是写在文件名里的设定值。alpha 与 Nmax 直接编码在文件名中,官方页面又逐条复述了一遍,还额外给出趋势斜率、周期、幂次、概率、宽度、幅值等参数。这一层的可信度最高——它是生成时的输入,不是事后的测量。
第二层是官方页面未给出的估计值。页面没有列出"用 DFA 跑这些序列会得到什么"。这不是遗漏,而是设计:一旦给出参考输出,使用者就会朝参考值调参,标定就失去了意义。代价是使用者必须自己实现方法、自己定口径,也必须为口径的选择负责。
| 层 | 内容 | 谁负责 | 风险 |
|---|---|---|---|
| 设定值 | alpha、Nmax 与扰动参数 | 数据集 | 无,直接读取即可 |
| 估计值 | 各方法在各序列上的输出 | 使用者 | 盒长、阶数、拟合区间都影响结果 |
| 参考文献值 | 论文中的图形与结论 | 论文 | 需按论文口径复现,不能直接套用 |
7.3 已知的、可枚举的偏差
| 偏差 | 表现 | 影响 |
|---|---|---|
| 参数稀疏 | 多数维度只有一到两个取值 | 只能回答定性问题,不能拟合参数依赖 |
| 长度绑定 | 更长的四条恰好都是局部异方差类 | 长度效应与扰动类型混杂,无法分离 |
| 无重复 | 每个条件只有一条序列 | 无法估计实现本身的随机波动 |
| 无生成细节 | 算法与种子未提供 | 序列不可重建,也无法扩展生成 |
| 无生理语义 | 纯合成 | 结论只能关于方法,不能关于生理 |
| 单列无单位 | 没有采样率与物理单位 | 结果不能换算成频率或时间尺度 |
| 官方笔误 | 一处文件名少字母,一处参数行截断 | 照抄页面会 404,须以目录为准 |
7.4 外部验证矩阵
| 验证角色 | 做法 | 讲得通的地方 | 风险 |
|---|---|---|---|
| 方法自检 | 用 6 条平稳序列看估计值是否逼近设定值 | 真值明确,判定无歧义 | 需先遵守反相关的修正提示 |
| 预处理论证 | 同一条带趋势序列跑去趋势前后 | 唯一变量是去趋势与否 | 盒长与拟合区间必须两次一致 |
| 抗扰比较 | 两种估计方法在尖峰序列上比偏差 | 扰动浓度与幅值已知 | 只有两个幅值,结论偏定性 |
| 教学复现 | 让学生重跑并对照设定值 | 参数公开,可判分 | 学生实现不同会导致数值不同 |
TNS 在文献里的角色与"被当作外部测试集"的那类库不同。它不出现在"我们在这个库上取得了多少分"这类表述里,而是出现在方法章节——用来说明某个估计步骤为什么必要、或者某个修正为什么有效。这个角色更隐蔽,但也更稳固:只要还有人在做标度分析,就需要一把已知真值的尺子。
7.5 它为何能持续
它没有更新、没有版本演进,2003 年发布后只做过一次校验和清单的更新,却一直被引用。原因很直接:它回答的那个问题不会过时。标度估计方法会迭代,趋势与非平稳性的处理方式会变,但"这个方法偏多少"这个问题永远需要真值来回答,而真值只能来自合成数据。
更实际的一点是成本。生成这样一批序列需要的是对相关噪声生成与标度分析的双重理解,而不是采集设备或伦理审批。这意味着它很难被"更大的版本"替代——后续研究需要新条件时,通常是自己按论文公式生成,而不是等数据集扩版。
§8 生态位与历史
8.1 历史沿革
TNS 出现在 PhysioNet 早期的一批"方法学附属品"里。2000 年代初,平台上已经积累了 MIT-BIH 系列的多套生理库,形成了格式统一、工具统一的生态。随着标度分析方法在心率变异性研究里流行起来,一个现实问题浮出水面:不同研究组用同一方法在同类数据上得到的指数并不一致,而没有人能说清谁对。
TNS 是对这个问题的直接回应。它的贡献者本身就是用这批序列写论文的人,把数据交出来的目的是让别人的结果可以对照。这种做法在当时的 PhysioNet 上并不少见——论文发表后把所用数据托管到平台,供他人复现。
8.2 与挑战赛的关系
它与各类挑战赛没有关系。PhysioNet 的挑战赛数据通常是"真实观测加任务标签",目标是让参赛者比高低;TNS 没有标签可比、没有排行榜、没有划分好的训练与测试集。把它当成某届挑战赛的附属品去查,会一无所获。
这个区别值得说清,因为它影响使用姿态。挑战赛数据鼓励"调出更高分",而 TNS 鼓励"证明自己的实现没偏"。两者的评价标准相反:前者看分数,后者看偏差。
8.3 生态位:校准块而不是材料
| 角色 | 材料 | 校准块 |
|---|---|---|
| 典型用法 | 训练、评测、跑分 | 标定、验证、复现 |
| 需要的前提 | 数据量大、标签细 | 真值已知、扰动可控 |
| 代表资源 | 生理波形库、间期库、标注影像库 | 本数据集、其他合成基准 |
| 失败模式 | 过拟合、标签噪声 | 把标定结果当成生理结论 |
TNS 坐在右边这一列。把校准块当材料用,会立刻遇到样本量瓶颈;把材料当校准块用,会因为缺真值而永远说不清对错。两者不能互换,也不能互相替代。
8.4 谁在用它,用来做什么
从数据集的自身定位与配套论文看,使用者集中在三类。第一类是做标度分析方法的课题组,用它验证新方法在趋势与非平稳性下的表现——这是它的设计初衷。第二类是把标度指数当作特征的工程人员,用它确认自己的特征提取流程在不同扰动下是否稳定。第三类是教学场景,用它演示"看起来很直的双对数曲线也可以错得很远"。
第三类常被低估。标度分析的教学难点在于学生无法判断自己算得对不对,而 TNS 把答案写进了文件名。这一点让它在课堂上比任何真实数据集都好用。
§9 使用指引
9.1 三种角色的路径
| 角色 | 第一天 | 第一周 | 注意事项 |
|---|---|---|---|
| 方法研究者 | 读官方页面的参数说明,跑通 §5.5 的 DFA | 28 条全跑一遍,出偏差表 | 先按反相关的修正提示处理 alpha < 0.5 的序列 |
| 工程人员 | 用 6 条平稳序列自检管线 | 在带趋势与尖峰序列上测稳定性 | 盒长范围要在不同序列间保持一致 |
| 教学人员 | 用 noise0517 演示白噪声基线 | 用 trlina 三条演示交叠点移动 | 明确告知学生估计值可与设定值对照 |
9.2 一条最短的可用流程
#-- 1. 取全部数据文件
wget -r -N -c -np https://physionet.org/files/tns/1.0.0/
#-- 2. 看一眼文件清单与体积
ls -l tns/1.0.0/tns/*.txt.gz | head -30
#-- 3. 校验完整性
cd tns/1.0.0 && sha256sum -c SHA256SUMS.txt
import glob, gzip, io
import numpy as np
#-- 4. 批量读,并把文件名里的 alpha 与长度解析出来
import re
rows = []
for path in sorted(glob.glob('tns/1.0.0/tns/*.txt.gz')):
name = path.split('/')[-1]
with gzip.open(path, 'rb') as fh:
x = np.loadtxt(io.BytesIO(fh.read()))
m = re.match(r'noise(\d\d)(\d\d)$', name.replace('.txt.gz', ''))
alpha = int(m.group(1)) / 10 if m else None
rows.append((name, len(x), alpha))
for r in rows[:8]:
print(r)
这段只解析了六条平稳序列的 alpha,其余留空。要补全 28 条的参数,按 §2.2 的三张表手工抄一份 28 行清单更可靠——文件名编码规则并不统一,第三组尤其绕。
9.3 引用方式
PhysioNet 的惯例是引用数据集本身加平台,本数据集还应当引用它配套的两篇论文:
| 引用对象 | 内容 |
|---|---|
| 数据集 | Surrogate Data with Correlations, Trends, and Nonstationarities, version 1.0.0. PhysioNet. 2003. DOI: 10.13026/C2KK54 |
| 论文一(趋势) | Hu K, Ivanov PCh, Chen Z, Carpena P, Stanley HE. Effects of trends on detrended fluctuation analysis. Phys Rev E 2001; 64:011114 |
| 论文二(非平稳性) | Chen Z, Ivanov PCh, Hu K, Stanley HE. Effects of nonstationarities on detrended fluctuation analysis. Phys Rev E 2002; 65:041107 |
| 平台 | PhysioNet 平台综述论文,按官方页面的 Cite 按钮生成 |
| 联系人 | 官方页面的通讯作者栏需登录后查看 |
写论文时建议同时注明:使用的版本号(1.0.0)、是否遵守了最大盒长取 Nmax/10 的建议、以及反相关序列是否做了积分修正。这三条决定了你的偏差数字能不能被别人复现。
§10 AI 使用声明
| 项目 | 声明 |
|---|---|
| 文本生成 | 本文由 AI 辅助撰写,编辑把关结构与事实 |
| 数字来源 | 规模、结构、边界三类数字来自 PhysioNet 官方页面与官方文件目录 |
| 文件核验 | 版本目录、28 个 .txt.gz 文件名与体积、SHA256SUMS.txt、两篇论文的网页版均经直接访问确认 |
| 不一致说明 | 官方页面写 ut0117w20p50,文件目录为 cut0117w20p50,已在 §2.2 标注并以目录为准 |
| 显示问题 | 官方页面 Nmax = 217 为上标丢失后的显示,按 2^17 理解,理由见 §2.4 |
| 论文信息 | 两篇论文仅读取随数据集托管的网页版摘要与章节目录,未读期刊全文 |
| 未核验内容 | 生成算法与随机种子、各序列的实际标度估计值、官方页面第三组 c 第四条的参数行原文 |
| 图像 | 无配图;封面为生成式提示词,不含真实波形截图 |
| 免责 | 本文不构成临床建议;数据使用须遵守 ODC-BY 1.0 的署名要求 |
常见误读(避坑清单)
| 说法 | 实际 | 证据 |
|---|---|---|
| 「它是某个生理信号的缩写库」 | slug 只是简短标识,官方页面标题是"带相关、趋势与非平稳性的替代数据" | 官方页面标题与数据描述段 |
| 「里面有病人记录」 | 受试者为零,全部由生成算法产生 | 官方页面数据描述只讲生成参数 |
| 「它有二十八条以上的序列」 | 28 个 .txt.gz,官方按 6+7+15 计数 | 文件目录列举与官方分组 |
| 「Nmax 是二百一十七」 | 上标丢失,实际是 2 的 17 次方 | 同页面 2-16 等写法同样退化 |
| 「alpha 一定能被 DFA 还原」 | 反相关序列在小尺度会被高估 | 官方页面转述第二篇论文的提示 |
| 「盒长可以一路取到一半」 | 官方建议最大盒长取 Nmax/10 | 官方页面数据描述段 |
「文件名里的 sp 表示特种信号」 |
表示 spikes(尖峰),sp 后缀表示仅含尖峰项 |
官方页面 “spikes signal only” |
| 「可以拿来训练模型」 | 28 条、每条件一条,会立刻过拟合 | 文件目录与分组结构 |
| 「它有采样率」 | 没有采样率,时间轴是整数下标 | 官方页面未出现任何频率单位 |
| 「它是某届挑战赛的数据」 | 与挑战赛无关,没有标签与排行榜 | 官方页面无挑战赛关联标识 |
| 「官方页面的文件名都对」 | 一处少字母,一处参数行被截断 | 文件目录实际文件名 |
FAQ
Q1:TNS 里到底有没有病人数据?
没有。官方页面把内容分成三组——平稳相关信号、带趋势信号、带非平稳性信号,全部由生成算法产生。文件目录里也没有任何与受试者相关的字段。它是一个方法学基准,不是临床数据集。
Q2:为什么官方页面写 Nmax = 217?
这是上标在网页上丢失后的显示结果,实际是 2 的 17 次方,等于 131072 个点。同一页面上把线性趋势斜率写成 2-16、2-12、2-8,负号同样退化成了短横,属于同一类渲染问题。第三组局部标准差的四条写的是 218,即 2 的 18 次方。
Q3:反相关序列为什么特别麻烦?
官方页面转述第二篇论文的结论:对反相关信号,DFA 得到的标度指数在小尺度上会高估真实的相关强度。修正办法是先把原信号积分,再跑 DFA,并且用 F(n)/n 对 n 的关系取斜率,而不是常规的 F(n) 对 n。跑 alpha 为 0.1 与 0.2 的两条时必须遵守这条,否则偏差里会混进方法缺陷。
Q4:能拿它训练一个预测标度指数的模型吗?
不适合。28 条序列,每个条件只有一条,没有重复也没有随机种子。任何模型都能把它记全,而记全之后无法判断是学会了还是背下了。它的用途是标定已有方法,不是训练新方法。
Q5:为什么趋势会让标度指数失真?
第一篇论文的摘要给出的机制是:噪声有自己的标度,趋势也有一个"表观标度",两者竞争就在双对数曲线上造出一个交叠点,两侧斜率不同。交叠点的位置本身还服从标度律——它随趋势参数呈长程幂律变化。论文还给出一个可操作的判据:如果噪声与趋势互不相关,DFA 结果等于分别跑噪声与趋势后的叠加;一旦叠加规则不成立,说明两者不独立,此时去掉趋势会改变噪声本身的相关性质。
Q6:尖峰组为什么要额外给"仅尖峰"文件?
因为要把尖峰的效应分离出来。sp02p05a1 是带尖峰的完整信号,sp02p05a1sp 是同一批尖峰单独成列。两者相减或分别跑,可以判断偏差有多少来自尖峰本身、多少来自尖峰与底噪的相互作用。幅值 1 与幅值 10 各有一对,可以再做一次幅值扫描。
Q7:它的许可允许商用吗?
ODC-BY 1.0 允许,包括商业用途,条件是署名。官方页面的访问策略写明"任何人都可以访问这些文件,只要遵守指定许可的条款"。引用时应给出数据集名称、版本号与 DOI,并引用两篇配套论文。
Q8:为什么只有 28 条,官方不扩版?
官方页面没有给出扩版说明。从设计看,它的目标是覆盖三类失效的典型条件,而不是做参数扫描;多数维度只有一到两个取值,如周期只有 128、宽度只有 20。需要更细的参数网格时,通常的做法是按官方页面给出的公式自行生成序列,而不是等数据集扩版。
Q9:能不能用它研究长度对估计的影响?
只能提供两个点,而且这两个点还绑着别的因素。24 条是 2^17,4 条是 2^18,而属于 2^18 的那四条恰好都是局部标准差类。长度效应与扰动类型混在一起,无法分离。
Q10:下载后怎么确认文件没损坏?
用官方的 SHA256SUMS.txt。wget -r 取完整个版本目录后,在目录里跑 sha256sum -c SHA256SUMS.txt 即可。这个清单的更新时间是 2019 年 2 月 20 日,比数据文件的时间戳晚,是后来补的校验文件。
术语表
| 术语 | 解释 |
|---|---|
| 去趋势波动分析(DFA) | 估计序列长程相关指数的标度分析方法,流程为积分、分盒、去趋势、拟合 |
| 标度指数 alpha | 刻画涨落随观察尺度增长的指数,0.5 为无长程相关,小于 0.5 为反相关 |
| 反相关 | 相邻取值倾向反向,alpha 小于 0.5 |
| 正相关 | 相邻取值倾向同向,alpha 大于 0.5 |
| 长程相关 | 相距很远的两个取值之间仍存在统计依赖 |
| 交叠点(crossover) | 双对数曲线上斜率发生明显改变的位置 |
| 表观标度 | 趋势本身贡献的、并非来自噪声的标度行为 |
| 叠加规则 | 噪声与趋势互不相关时,DFA 结果等于两者分别结果之和 |
| 盒长 n | DFA 分盒时每盒包含的采样点数 |
| 涨落函数 F(n) | 盒长为 n 时残差的均方根 |
| 非平稳性 | 序列的统计性质随时间变化 |
| 替代数据 | 为检验方法而人工生成的、性质已知的数据 |
| 合成数据 | 由算法生成而非采集得到的数据 |
| 截断(cutout) | 从序列中切掉一段再把剩余部分拼接起来 |
| 尖峰(spike) | 幅值远大于周围取值的离群点 |
| 局部标准差 | 序列某一段内部的标准差,与另一段不同即为异方差 |
| 局部相关指数 | 序列某一段内部的相关指数,与另一段不同即为相关混合 |
| 幂律趋势 | 形如 Ap / Nmax^lambda 的趋势项 |
| Nmax | 序列总点数 |
| ODC-BY | 开放数据共享署名许可,允许商用但要求署名 |
| PhysioNet | 由 MIT 计算生理学实验室维护的生物医学信号数据平台 |
| gzip | 通用的文件压缩格式,本数据集的 .txt.gz 即用它压缩 |
附录 A:核心数字核对表
| 项 | 值 | 来源 | 来源层级 |
|---|---|---|---|
| 序列条数 | 28 | 官方页面 6+7+15;文件目录列举 | 官方页面 |
| 平稳相关序列 | 6 | 官方页面第一组 | 官方页面 |
| 带趋势序列 | 7 | 官方页面第二组(3+2+2) | 官方页面 |
| 带非平稳性序列 | 15 | 官方页面第三组(4+4+4+3) | 官方页面 |
| 单条长度(多数) | 2^17 = 131072 | 官方页面 Nmax 标注 | 官方页面 |
| 单条长度(局部标准差类) | 2^18 = 262144 | 官方页面 Nmax 标注 | 官方页面 |
| 单条行数(noise0117) | 131072 | 官方文件解压后按非空行计数 | 官方文件 |
| 单条行数(d2h4pd050118s) | 262144 | 官方文件解压后按非空行计数 | 官方文件 |
| 受试者数 | 0 | 官方页面无受试者相关字段 | 官方页面 |
| 通道数 | 1 | 官方页面"每个文件含一列数据" | 官方页面 |
| alpha 取值 | 0.1、0.2、0.5、0.8、0.9、1.5 | 官方页面第一组清单 | 官方页面 |
| 线性趋势斜率 | 2^-16、2^-12、2^-8 | 官方页面第二组 a | 官方页面 |
| 正弦周期 | 128 | 官方页面第二组 b | 官方页面 |
| 幂次 lambda | 0.4、-0.7 | 官方页面第二组 c | 官方页面 |
| 截断宽度 W | 20 | 官方页面第三组 a | 官方页面 |
| 尖峰幅值 | 1、10 | 官方页面第三组 b | 官方页面 |
| 局部标准差对 | 1 与 4 | 官方页面第三组 c | 官方页面 |
| 局部相关占比 | 90% 与 10% | 官方页面第三组 d | 官方页面 |
| 最大盒长建议 | Nmax/10 | 官方页面转述第二篇论文 | 官方页面 |
| 未压缩总量 | 18.1 MB | 官方页面文件区 | 官方页面 |
| 整包 ZIP | 18.3 MB | 官方页面文件区 | 官方页面 |
| 版本号 | 1.0.0 | 官方页面版本历史 | 官方页面 |
| 发布日期 | 2003-03-07 | 官方页面版本历史 | 官方页面 |
| 校验清单日期 | 2019-02-20 | 文件目录时间戳 | 官方文件 |
| DOI | 10.13026/C2KK54 | 官方页面 Discovery 区 | 官方页面 |
| 许可 | ODC-BY 1.0 | 官方页面 License 区 | 官方页面 |
附录 B:数字的来源分层
第一层:官方页面与官方文件。 序列条数、分组、alpha 取值、趋势与非平稳参数、长度、格式、许可、DOI、发布日期。这些数字来自项目主页的数据描述段与版本历史,以及文件目录里 28 个 .txt.gz 的文件名与体积。
第二层:配套论文。 趋势造成交叠点的机制、叠加规则、反相关序列的修正办法、最大盒长建议。这些来自随数据集托管的两篇论文网页版摘要,以及官方页面对第二篇论文的转述。摘要只能支撑"论文报告了什么",不能支撑"在你的实现上会怎样"。
第三层:未核实。 生成算法与伪随机数发生器、随机种子、各序列的实际标度估计值、官方页面第三组 c 第四条参数行的原文。这些需要读论文全文或联系作者,正文中凡涉及处均只做定性表述或明确标注缺失。
附录 C:完整参考文献
| 编号 | 文献 | 链接 | 用途 |
|---|---|---|---|
| 1 | Surrogate Data with Correlations, Trends, and Nonstationarities v1.0.0 | https://physionet.org/content/tns/1.0.0/ | 全部规模、结构、边界数据的来源 |
| 2 | 该数据集的 PhysioNet 文件目录 | https://physionet.org/files/tns/1.0.0/ | 28 个文件名、体积、校验清单 |
| 3 | Hu K, Ivanov PCh, Chen Z, Carpena P, Stanley HE. Effects of trends on detrended fluctuation analysis. Phys Rev E 2001; 64:011114 | https://physionet.org/files/tns/1.0.0/tns/paper1/ | §4.2 趋势机制与叠加规则 |
| 4 | Chen Z, Ivanov PCh, Hu K, Stanley HE. Effects of nonstationarities on detrended fluctuation analysis. Phys Rev E 2002; 65:041107 | https://physionet.org/files/tns/1.0.0/tns/paper2/ | §1.2、§4.2、§4.5 非平稳性与修正提示 |
| 5 | PhysioNet 平台综述(2026,Nature Health) | https://doi.org/10.1038/s44360-026-00096-z | 托管模式与引用规范 |
| 6 | ODC-BY 1.0 许可全文 | https://opendatacommons.org/licenses/by/1-0/ | 许可条款 |
附录 D:任务代码
任务一:28 条序列的偏差表
import gzip, io, glob, re
import numpy as np
#-- 官方页面给出的设定值;其余文件按 §2.2 的三张表补齐
TRUTH = {
'noise0117': 0.1, 'noise0217': 0.2, 'noise0517': 0.5,
'noise0817': 0.8, 'noise0917': 0.9, 'noise1517': 1.5,
}
def load(path):
#-- 单列 ASCII,gzip 压缩
with gzip.open(path, 'rb') as fh:
return np.loadtxt(io.BytesIO(fh.read()))
def dfa(x, order=1):
y = np.cumsum(x - np.mean(x))
N = len(y)
hi = N // 10 #-- 官方建议的最大盒长
scales = np.unique(np.logspace(np.log10(8), np.log10(hi), 20).astype(int))
scales = scales[(scales >= 8) & (scales <= hi)]
fn = []
for n in scales:
m = (N // n) * n
seg = y[:m].reshape(-1, n).T
t = np.arange(n)
A = np.vstack([t, np.ones(n)]).T #-- 一阶(线性)去趋势
coef, *_ = np.linalg.lstsq(A, seg, rcond=None)
fn.append(np.sqrt(np.mean((seg - A @ coef) ** 2, axis=0)))
f = np.array([v.mean() for v in fn])
return np.polyfit(np.log(scales), np.log(f), 1)[0]
rows = []
for path in sorted(glob.glob('tns/1.0.0/tns/*.txt.gz')):
key = path.split('/')[-1].replace('.txt.gz', '')
x = load(path)
est = dfa(x)
rows.append((key, len(x), TRUTH.get(key), est))
for r in rows:
print(r)
任务二:反相关序列的积分修正
import numpy as np
def dfa_anticorr(x, scales=None):
#-- 官方提示:先对原信号积分,再用 F(n)/n 对 n 取斜率
z = np.cumsum(x - np.mean(x)) #-- 第一次积分
y = np.cumsum(z - np.mean(z)) #-- 再积分一次后做 DFA
N = len(y)
hi = N // 10
if scales is None:
scales = np.unique(np.logspace(np.log10(8), np.log10(hi), 20).astype(int))
scales = scales[(scales >= 8) & (scales <= hi)]
fn = []
for n in scales:
m = (N // n) * n
seg = y[:m].reshape(-1, n).T
t = np.arange(n)
A = np.vstack([t, np.ones(n)]).T
coef, *_ = np.linalg.lstsq(A, seg, rcond=None)
fn.append(np.sqrt(np.mean((seg - A @ coef) ** 2, axis=0)))
f = np.array([v.mean() for v in fn])
#-- 关键区别:拟合的是 log(F(n)/n) 而不是 log(F(n))
slope = np.polyfit(np.log(scales), np.log(f / scales), 1)[0]
return slope
第二段代码的价值在于它把官方那句提示具体化成了两处实现差异:多一次积分,以及拟合对象从 F(n) 换成 F(n)/n。跑 alpha = 0.1 与 0.2 两条时,用它得到的指数才适合与设定值做差。
附录 E:如果只记五件事
| 序号 | 记住什么 | 为什么 |
|---|---|---|
| 1 | 28 条合成序列,零受试者,零采样率 | 它衡量算法,不是生理 |
| 2 | alpha 与 Nmax 写在文件名里 | 这是唯一能对照的真值 |
| 3 | 长度是 2^17 与 2^18,不是 217 与 218 | 盒长与拟合区间全靠这个数 |
| 4 | 最大盒长取 Nmax/10,反相关序列要积分修正 | 不遵守这两条,偏差无法归因 |
| 5 | 它是校准块,不是材料 | 训练它没用,标定它才有用 |
编辑说明
本文的核验时间为 2026 年 10 月 28 日。核对方式为直接访问 PhysioNet 项目页与版本文件目录,逐一确认 28 个 .txt.gz 的文件名与体积、SHA256SUMS.txt、以及两篇配套论文的网页版摘要。三处需要提请注意:一是官方页面把一条截断序列的文件名写成 ut0117w20p50.txt.gz,目录中的实际名称是 cut0117w20p50.txt.gz;二是官方页面的 Nmax 标注因上标丢失显示为 217 与 218,按 2^17 与 2^18 理解;三是第三组 c 的第四条参数行在页面上被截断,按命名规则与目录确认为 d2h4pd950918s.txt.gz。未覆盖的内容包括生成算法与随机种子、各序列的实际标度估计值、以及论文全文中的具体图形与数值。这些需要读全文或联系作者,本文按要求只写规模、结构、边界三类数字。
相关数据集导航
以下为站内 AI-Ready 数据集百科中与本词条共享多个主题标签的相关数据集,按相关度降序排列:
- fantasia:共享标签 生理信号 / 时序信号 / 心率变异性
- physiozoo:共享标签 生理信号 / 时序信号 / 方法学基准
- nsrdb:共享标签 生理信号 / 时序信号 / 长时程记录
- nsr2db:共享标签 生理信号 / 时序信号 / 间期序列
- chfdb:共享标签 生理信号 / 时序信号 / 心血管疾病
- chf2db:共享标签 生理信号 / 时序信号 / 心血管疾病
- mit-bih-afdb:共享标签 生理信号 / 时序信号 / 节律紊乱
- gaitdb:共享标签 生理信号 / 时序信号 / 运动与神经
- tremordb:共享标签 生理信号 / 时序信号 / 运动与神经
- tappy:共享标签 生理信号 / 时序信号 / 运动与神经
导航说明:本章节由全站统一标签体系自动计算生成(标签重合度算法),双向可达;点击链接可跳转至对应数据集词条。

