脑电运动想象数据集镜像 — 一个下载包里装着五种许可

32 子集 / 841 被试 / 637 GB / 五种许可

来源 https://huggingface.co/datasets/EEGDash/eeg-mi-datasets发布时间: 2026-10-26最后更新: 2026-10-26 阅读 19
脑电运动想象数据集镜像 — 一个下载包里装着五种许可

信息速览

数据集名称脑电运动想象数据集镜像 — 一个下载包里装着五种许可
数据类型时序信号,波形,元数据,原始数据链接
规模841 名被试(32 个子集合计,官方页面称)
接入方式https://huggingface.co/datasets/EEGDash/eeg-mi-datasets
AI 就绪度

EEGDash 的这个仓库在技术上是一件事:一个 Hugging Face 数据集仓库,一条命令就能拿到全部文件,目录结构统一,用 MOABB 加载器一行代码就能读出某个子集的某名被试。在账面上它也是整齐的,官方页面把它写成「32 个子集、841 名被试、637 GB」,读起来像一份合并报表。

但它在法律上不是一件事。数据集卡的 tags 里并列着五个许可:CC BY 4.0、CC BY-ND 4.0、CC BY-NC-ND 4.0、CC0 1.0、ODC-By 1.0。五个许可分布在 32 个子集上,落到具体目录才知道哪条适用。同一台机器、同一个缓存目录、同一行加载代码背后,可能一半是可以随便改的 CC0,另一半是连滤波后的副本都不许外传的 ND。

这不是打包者疏忽,恰恰相反,作者把每个子集的许可原文与授权方逐条写在数据卡里,只是把「合并」这件事止步于文件系统,没有延伸到权利层。本文就围绕这处错位展开:技术包与法律包为什么对不上,对不上会怎样伤到人,以及在不对齐的前提下怎么做才是安全的。一屏速览见下表。

维度 内容
官方名称 EEGDash eeg-mi-datasets(Hugging Face 组织 EEGDash)
一句话定位 把 MOABB 收录的公开运动想象脑电数据集按缓存布局重新打包的镜像仓库
子集数 32 个(官方页面称)
被试规模 841 名,1,917 次会话(官方页面称)
文件与体量 4,077 个文件,637 GB(官方页面称)
上游托管方 10 个:BNCI Horizon、Zenodo、figshare、Harvard Dataverse、DataverseNL、GigaDB、OSF、PhysioNet、DepositOnce、Hugging Face
许可结构 五种并列,逐子集适用;CC BY 4.0 十五个、CC0 1.0 十个、CC BY-ND 4.0 三个、CC BY-NC-ND 4.0 两个、ODC-By 1.0 两个
禁改禁商的子集 5 个(三个 BY-ND、两个 BY-NC-ND),合计 60 名被试
导联范围 3 到 128 导(官方页面称)
采样率范围 160 Hz 到 1000 Hz(官方页面称)
文件格式 MAT、EDF、BDF、EEGLAB、BrainVision、XDF、NumPy、CSV 等至少八种
目录约定 MOABB 缓存布局,顶层为子集名
加载方式 MOABB 加载器 + 环境变量指向本地目录,数据卡给逐子集示例
主要人群 健康被试为主,含卒中患者子集与未注明健康状态的子集
体量高度集中 单个子集 Stieger2021 占 377 GB,约为全仓的六成
本文判断 技术上可取,法律上必须逐子集拆开看;不适合当作一个许可的整包使用

§1 它要解决的具体麻烦

1.1 公开脑电数据的发布方式是碎的,而不是少的

运动想象脑电的公开数据并不稀缺。MOABB 收录的运动想象数据集在一百个以上,官方页面提到的那次核对里就走了 106 个。真正麻烦的是这些数据散落在十个以上的托管方:奥地利的 BNCI Horizon 放的是 BCI 竞赛时代的 MAT 矩阵,PhysioNet 放的是 EDF 波形,GigaDB 放的是 MATLAB 结构体,figshare 与 Zenodo 放的是压缩包,Harvard Dataverse 放的是带文件 ID 的文档单元。

散落还不算致命,致命的是每家都自带一套习惯。有的把训练与评估分成两个文件,有的把五次会话塞进一个 MAT 结构里,有的把事件写在单独的表里,有的把事件写在脑电注释里。研究者在复现一篇论文时要写十几个下载脚本,每个脚本都要处理不同的解压层级与命名规则,写完之后的目录结构彼此不兼容,换一个子集就得改一遍代码。

镜像仓库解决的是这一层。它把十个托管方的产出统一到 MOABB 的缓存目录约定之下:顶层是子集名,下面按加载器期望的层级铺开,从上游拿到的字节原样保留,只改位置与个别名字。于是「取数」这一件事从十几个脚本收敛成一个下载函数加一个环境变量,脚本的可复现性也因此提高——路径不再依赖每个人各自的下载习惯。

值得说清楚的是它没有做的事。它没有重采样,没有统一滤波,没有把导联重排到同一个模板,也没有把事件名强行统一成一套本体。这些都属于「处理」,一旦做了就产生新的数据集,而新数据集又需要新的许可判断。镜像刻意停在搬运这一层,把处理留给使用者,也把处理的后果留给使用者承担。这句话在技术上是免责声明,在法律上却是最要紧的一条:加工等于派生,派生的权利条件由原许可决定,不由加工者决定。

所以这个仓库的定位可以概括成一句话:它是取数环节的补丁,不是数据内容的重制版。理解这一点,后面所有的许可讨论才有落点——因为它处理的是搬运,所以每个文件的身份仍然完整地属于它的上游,而搬运者没有能力也不打算替上游授权。

1.2 三条常见的错误期待

第一条:以为一个仓库对应一个许可。 这是最常见的一条,也是最贵的一条。Hugging Face 的数据集卡在页面顶部会展示一个许可标签,而这份卡的 license 字段是一个列表,页面会同时显示五个徽标。多数人在找数据集时只看其中一个,或者只看自己熟悉的那个,然后把它当作整包的通行证。把整包当成 CC BY 4.0 用,是这条误读的标准后果。

第二条:以为「公开可下载」等于「可以任意使用」。 开放获取(open access)谈的是能否得到,许可谈的是得到之后能做什么。这两件事在学术出版里早已分开,到了数据集上却经常被合二为一。一个数据集可以完全免费下载、不需要注册、不需要申请,同时严格禁止商用或者禁止分发修改版本。EEGDash 这五个受限子集正是这种情况:任何人都能下,下完之后能做的事有明确边界。

第三条:以为 ND 只管「不许改」,不管「改了之后怎么办」。 实际上 NoDerivatives 管的是分发环节。你可以私下修改,可以在自己的流水线里滤波、分段、做特征提取,但只要把修改后的副本交给第三方,就已经落在条款管束的范围里。数据卡把这层意思写得很直白:被滤波或分段的副本同样不得分发。这一句足以推翻很多团队的默认做法——他们习惯把预处理好的缓存目录一起打进交付包。

三条期待的共同点是把「文件在我手里」当成「权利在我手里」。镜像仓库恰好把这两种状态摆得极近:文件真的都在一个目录里,权利却按子集切成五份。

1.3 它能给到的与给不到的

你的需求 它给的 够不够
一次拿到多个运动想象数据集的同一套目录 MOABB 缓存布局,顶层按子集切分 够,但只在结构层统一
不写十几个下载脚本就完成取数 一个下载函数加改文件名模式即可按需取子集 够,数据卡给了逐子集示例
确认文件没被篡改 逐文件对上游校验和与 Hub 侧 SHA-256 比对 够,官方页面列出了核对方法与日期
知道每个子集的法律地位 数据集卡里逐子集的许可与授权方 够,但需要自己读表,页面不会替你判断
拿到统一的预处理结果 不给,只搬原始字节 不够,预处理要自己做
拿到统一的导联模板 不给,导联数从 3 到 128 不等 不够,跨子集对齐要自己搭
拿到统一的事件本体 部分给,MOABB 自己有一套事件名映射 半够,映射由加载器完成,不在文件里
直接商用 两个子集含 NC 条款,商业用途被排除 不够,商用只能取 CC0 与 CC BY 两组
对外发布派生数据集 五个子集禁止分发修改版本 不够,派生只能在内部用
拿到被试的完整临床信息 卒中子集有分组标注,其他多为健康或未注明 不够,做临床分层研究要补外部信息

1.4 你的处境与它能帮到的事

你的处境 它能帮你什么 下一步该做什么
要复现一篇运动想象论文,但作者只写了用了哪几个数据集,没给下载脚本 按子集名一次取齐,目录结构与 MOABB 论文的默认一致 先读数据卡的子集表确认被试数与类别,再按 §5 的示例下载
要做跨被试泛化的算法评测,需要十来个数据集轮着跑 32 个子集同构,评测脚本只需换一个加载器名 先用许可筛一遍,把五个受限子集单独放一个目录,别混进主评测集
在脑机接口公司做产品预研,半年后可能要出货 CC0 的十个子集与 CC BY 的一组可以进产品链路 现在就建一张许可台账,按子集登记,别等到法务问起来才补
临床团队要做卒中康复的运动想象研究 Jia2019、Liu2024、三个 WRCC2023 子集提供卒中人群 注意卒中子集普遍被试少,且 WRCC2023 未说明哪两名被试患病
数据工程师要把脑电接进训练流水线 原始格式齐全,MAT、EDF、BDF、EEGLAB 都能读 只下载需要的子集,整包 637 GB 里六成是单个子集的单被试大文件
学生要在两周内跑出一个能写进论文的基线 MOABB 自带评估协议,跨会话与跨被试两种划分都有 挑被试多、体量小的子集,PhysionetMI 与 Cho2017 都比 BNCI 那组好取
有人给了你一份「EEGDash 预处理版」数据集 可以拿它和本仓库的原始文件对比,判断出处 先查它源自哪些子集,若含 ND 子集,那份预处理版的再分发本身就有问题

1.5 一句话判断

这是一个把取数环节做得很干净的仓库,也是一份把法律风险完整保留给使用者的仓库;它的价值在于结构统一,它的危险也在于结构统一——因为目录不会告诉你权利在哪一层断掉。

1.6 不适合谁:四条边界

不适合把整包当成一份数据来用的人。 如果你的工作流是「下载全部、合并成一个大数据池、统一预处理、对外交付」,那么这个仓库会在第一步就给你错误的前提。你拿到的是一个目录树,不是一个数据集。合并这个动作本身就已经越过了五个子集的条款,而这五个子集恰恰是运动想象文献里引用最多的那几个——BCI 竞赛的 2a 与 2b 就在其中。

不适合需要单一许可声明的下游场景。 医疗软件注册、科研数据共享平台入库、企业数据资产登记,这些场景都要求一份明确的权利声明。混合许可的仓库给不出一份能覆盖全包的单一声明,只能给出逐子集的清单。如果下游系统的字段设计只有一个 license 字段,这个仓库就装不进去。

不适合小样本推断。 有若干子集的被试数在十人以下,Zhou2016 四名被试,Beetl2021_A 三名被试,Kaya2018 七名被试。这些子集在文献里的角色是「补充验证」,不是「主实验」。拿它们算跨被试准确率的置信区间,或者拿它们的结论去支持人群层面的论断,都会失真。四名被试的均值差一个标准差就能翻转方向。

不适合寻求统一预处理或统一导联的人。 仓库不改数据,也不做重参考与降采样。导联从 3 到 128,采样率从 160 Hz 到 1000 Hz,标签集从两类到七类。想要「下载即训练」的人会失望,因为这里连通道名都没有被统一到同一个命名空间,各子集沿用了各自的电极命名习惯。

§2 数据构成与规格

2.1 32 个子集的逐项清单

这一张表是全文的地基。它把数据卡里每个子集的类别、被试数、会话数、导联数、采样率与许可并排放在一起,目的是让「同一列里有五种许可」这件事在视觉上无法被忽略。类别名是 MOABB 的事件名,不是原始文件的标签;导联数与采样率是 MOABB 加载时呈现的值。

子集 类别(MOABB 事件名) 被试 会话 导联 采样率 Hz 许可
BNCI2014_001 left_hand / right_hand / feet / tongue 9 18 22 250 CC BY-ND 4.0
BNCI2014_002 right_hand / feet 14 14 15 512 CC BY-ND 4.0
BNCI2014_004 left_hand / right_hand 9 45 3 250 CC BY-ND 4.0
BNCI2015_001 right_hand / feet 12 28 13 512 CC BY-NC-ND 4.0
Beetl2021_A left_hand / right_hand / feet / rest 3 3 63 500 CC BY 4.0
Brandl2020 left_hand / right_hand 16 16 63 1000 CC BY-NC-ND 4.0
Cho2017 left_hand / right_hand 52 52 64 512 CC BY 4.0
Dreyer2023 left_hand / right_hand 87 87 27 512 CC BY 4.0
Farabbi2020 left_hand / right_hand 12 36 32 250 CC BY 4.0
GrosseWentrup2009 left_hand / right_hand 10 10 128 500 CC BY 4.0
GuttmannFlury2025_MI left_hand / right_hand 31 63 60 1000 CC0 1.0
Jia2019 left_hand / right_hand 15 15 63 512 CC BY 4.0
Kaya2018 left_hand / right_hand / passive 7 17 19 200 CC0 1.0
Kumar2024 left_hand / right_hand 18 108 22 512 CC BY 4.0
Lee2019_MI left_hand / right_hand 54 108 62 1000 CC0 1.0
Leeuwis2021 left_hand / right_hand 55 55 16 250 CC BY 4.0
Liu2024 left_hand / right_hand 50 50 29 500 CC BY 4.0
Pan2023 left_hand / right_hand 14 28 28 250 CC0 1.0
Pan2025 left_hand / right_hand 10 20 28 250 CC0 1.0
PhysionetMI left_hand / right_hand / feet / hands / rest 109 109 64 160 ODC-By 1.0
Rozado2015 left_hand / rest 30 30 32 512 CC0 1.0
Shin2022 left_hand / right_hand 10 10 16 250 CC BY 4.0
Stieger2021 left_hand / right_hand / both_hand / rest 62 598 60 1000 CC BY 4.0
Vagaja2023 left_hand / right_hand 26 26 32 500 CC BY 4.0
WRCC2023_MI_A left_hand / right_hand / feet 9 9 59 1000 CC0 1.0
WRCC2023_MI_B left_hand / right_hand / feet 9 9 59 1000 CC0 1.0
WRCC2023_MI_C left_hand / right_hand / feet 8 8 59 1000 CC0 1.0
Wang2025 left_hand / right_hand / feet / tongue 15 30 62 256 ODC-By 1.0
Weibo2014 七类复合运动想象 10 10 60 200 CC0 1.0
Yang2025(两类部分) left_hand / right_hand 51 153 59 1000 CC BY 4.0
Zhou2016 left_hand / right_hand / feet 4 12 14 250 CC BY 4.0
Zhou2020 left_hand / right_hand / feet / rest 20 140 41 或 26 500 CC BY 4.0

表里有几处值得停一下。Weibo2014 的七类包含左右手与左右脚的复合任务,是全部子集里标签最细的一个,但只有十名被试。Zhou2020 的导联数写「41 或 26」,意味着不同被试的电极配置不一致,这在对齐时会造成麻烦。Yang2025 在这里只有两类部分,三类部分被留在仓库之外。这些细节都写在数据卡里,但很容在被「32 个子集」这一句概括时消失。

2.2 字段与目录的完整字典

接下来这一张表描述「一个子集在仓库里长成什么样」。它不是 schema 意义上的字段字典,因为仓库没有数据库表;它是路径与文件的字典,回答「要拿到某个东西,去哪个位置找」。第三列写的是这些内容是否携带许可信息,这一列是全文唯一把技术位置与法律条件并排的地方。

位置 内容 是否携带许可信息
README.md(仓库根) 数据卡,含总览、32 行子集表、核验记录、逐子集加载示例、引用清单 是,子集表的最后一列就是许可
.gitattributes 仓库属性文件,影响下载时的 LFS 处理 否
<子集名>/ 子集目录,名称为 MOABB 的加载器名 间接,需回到根 README 查
<子集名>/MNE-<托管方>-data/ 一类子目录 按上游目录原样保留的层级 否
<子集名>/**/*.mat MATLAB 矩阵或结构体,多数子集的主格式 否,许可在文件头之外
<子集名>/**/*.edf 欧洲数据格式,PhysioNet 系 否
<子集名>/**/*.bdf BioSemi 数据格式,BrainVision 或 BDF 系 否
<子集名>/**/*.set 与 *.fdt EEGLAB 数据集与数据文件配对 否
<子集名>/**/*.vhdr/.eeg/.vmrk BrainVision 三件套 否
<子集名>/**/*.npy NumPy 数组,Beetl2021 与部分新子集 否
<子集名>/**/files/<数字 ID> 十个沿用上游数字名的子集,路径无扩展名 否
<子集名>/**/description.pdf BNCI 系自带的说明文档 否
根 README 的 tags 块 五个许可的并列列表 是,但只到仓库级
根 README 的 Datasets 表 逐子集许可与授权方 是,能落到子集级
MOABB 加载器源码 事件映射、导联选择、trial 切分规则 否

这张表最重要的读法是最后两行与倒数第三行的对比。仓库级 tags 写着五个许可,子集表写着每个子集一个许可,而到了具体文件上,许可信息完全消失。一个字节流不会自己带上权利声明。这意味着任何脱离 README 的流传都会丢失许可信息:你把 BNCI2014_001/ 拷给同事,同事看到的是 22 个导联的 MAT 文件,看不到 ND 三个字母。

2.3 一条记录的完整解剖

把某一名被试在一个子集里的一次会话摊开,可以看到三层信息:物理层是文件与字节,语义层是事件与类别,法律层则完全不在文件里。

层级 组成 来源 可变性
物理层 波形矩阵:导联 × 采样点,多为单精度浮点 上游原始文件 镜像不改字节
物理层 采样率、导联名、参考方式 上游文件头或伴随元数据 镜像不改
语义层 事件标记:提示出现、任务起止、休息段 上游文件内嵌或伴生表 由 MOABB 映射为统一事件名
语义层 会话编号、被试编号 文件名或目录名 多数沿用上游,部分重排
语义层 类别集合 MOABB 加载器声明 因加载器版本可能变化
法律层 许可类型、授权方、派生物条件 只在根 README 子集表 不随文件移动

§4.2 的案例里那条从许可写到文件的轨迹,在这段代码里被拆成可执行的三步。下面这段 python 演示如何把三层拆开读取。它先按子集名取顶层目录清单,再从数据卡里抓出该子集那一行的许可文本,最后才去动文件。顺序是有意的:先问权利,再看数据。代码里的路径全部指向公开地址,不依赖本地绝对路径。

#-- 先问权利,再碰数据:读仓库根目录清单 + 从数据卡抓该子集许可
import json
import urllib.request

REPO = "EEGDash/eeg-mi-datasets"
HEAD = "https://huggingface.co/api/datasets"


def get_json(url):
    #-- 请求头只用标准库,避免额外依赖
    req = urllib.request.Request(url, headers={"User-Agent": "eegdash-license-audit/1.0"})
    with urllib.request.urlopen(req, timeout=30) as r:
        return json.loads(r.read().decode("utf-8"))


def get_text(url):
    req = urllib.request.Request(url, headers={"User-Agent": "eegdash-license-audit/1.0"})
    with urllib.request.urlopen(req, timeout=30) as r:
        return r.read().decode("utf-8")


def subtree(name):
    url = f"{HEAD}/{REPO}/tree/main/{name}"
    return [item["path"] for item in get_json(url)]


def card_rows():
    #-- 数据卡的子集表以 | 数字 | 开头,最后一列是许可
    text = get_text(f"https://huggingface.co/datasets/{REPO}/raw/main/README.md")
    rows = {}
    for line in text.splitlines():
        cells = [c.strip() for c in line.strip("|").split("|")]
        if len(cells) >= 12 and cells[0].isdigit():
            rows[cells[1]] = cells[-1]
    return rows


licenses = card_rows()
target = "BNCI2014_001"
print("许可原文:", licenses[target])
files = subtree(target)
print("顶层文件数:", len(files))
print("前三个路径:")
for p in files[:3]:
    print("  ", p)

这段代码的输出会立刻暴露两件事。第一,BNCI2014_001 的许可原文那一格里带着授权方名称,说明权利人是格拉茨工业大学的知识发现研究所,不是 EEGDash。第二,路径里含 MNE-bnci-data 之类的上游目录名,说明镜像保留了上游的目录习惯,只是把它们挂在了 MOABB 期望的位置下。授权方是上游的这件事,决定了任何授权咨询都得绕过镜像直接找上游。

2.4 体量分布在子集之间的极端不均

子集 体量 占全仓比例 每被试体量 读法
Stieger2021 377 GB 约 59% 约 6 GB 长时连续记录,单被试极重
Yang2025(两类) 74.6 GB 约 12% 约 1.5 GB 多日会话,1000 Hz
Lee2019_MI 65 GB 约 10% 约 1.2 GB 62 导 1000 Hz,会话多
GuttmannFlury2025_MI 26.2 GB 约 4% 约 0.85 GB 60 导 1000 Hz
Zhou2020 17.6 GB 约 3% 约 0.88 GB 每被试七个会话
其余 27 个子集 合计约 77 GB 约 12% — 多数低于 1 GB
15 个轻量子集合计 约 25 GB 约 4% 均低于 0.1 GB 承载约一半被试
全仓合计 637 GB 100% — 四千余个文件

这张表的核心不是「大」,而是「大得不均匀」。六成体量在 Stieger2021 一个子集里,而它只占 7% 的被试。反过来,十五个轻量子集用约二十五 GB 装下了约一半的被试。如果按体量做预算,结论会是「这个仓库太重」;如果按被试做预算,结论会是「这些数据其实很轻」——两个结论的差别来自一个子集的长时记录把均值拉歪了。

对取数策略的直接含义:整包下载几乎总是错的。官方页面给出的做法是按子集名加通配符取,例如只取某个子集的某个被试,或者取某个子集全部用户。按需取还有一个附带好处——每次下载的目录里只有被取子集的文件,许可台账容易与磁盘对得上。

2.5 与同类资源的字段差异

维度 EEGDash 镜像 MOABB 原始分发 OpenNeuro 单数据集 单个上游托管页
组织单位 子集 数据集类 一个 study 一个 DOI
取数入口 一个仓库 + 通配符 加载器内部下载 每个 study 一个地址 每个 DOI 一个页
目录约定 MOABB 缓存布局 不落盘或落缓存 BIDS 各家自定
许可粒度 子集级,一处并列五种 数据集类属性 study 级,通常单一 全页单一
格式统一 否,保留原始格式 加载时转为 MNE 对象 BIDS 强制约束 各家自定
离线可用 是,一次下载后断网可读 需联网或自建缓存 是 是
校验记录 逐文件比对并列出日期 依赖上游 由平台提供 各家不一
主要价值 批量取数与结构一致 评估协议 神经影像规范 权威性与授权方
主要风险 许可被整包化 下载不可复现 study 之间不可拼 需逐个手工整理

这张表想说明的是,EEGDash 的差异点不在数据,而在「批量」。单个上游托管页在权威性上永远更好——它是授权方自己发的;OpenNeuro 在规范上更严格;MOABB 在评估协议上更完整。镜像的独有价值只有一条:当你需要十几个数据集同构地摆在磁盘上时,它省掉的是整理时间,不是判断时间。

§3 它是什么:一份搬运层的自我说明

3.1 三个身份,三种责任边界

这个仓库在三种意义上都「是」某个东西,而每次换身份,责任归属都会变。分清这三层是理解整篇的前提。

身份 它是什么 谁负责 哪些责任不在它身上
技术层 一个 Hugging Face 数据集仓库,四千余个文件挂在 MOABB 缓存目录下 EEGDash 组织 数据内容正确性、被试知情同意的充分性
目录层 MOABB 缓存约定的具体落地,路径与加载器一一对应 MOABB 项目定约定,EEGDash 执行 事件语义的最终解释权归 MOABB,不归镜像
法律层 32 个独立上游资产的并列陈列,权利人各不相同 各上游作者与其机构 镜像没有任何转授权能力

第三行是本文的核心。镜像提供者能做的是「不隐瞒」:把每个子集的许可与授权方写进表里,把核验方法写进文里。它做不到的是「替代授权」:它无法把一个 ND 条款改成 BY,也无法把上游的伦理约束去掉。当使用者误以为整包是一个许可时,错误不是镜像造成的,但镜像的形态确实让这个错误更容易发生。

3.2 为什么在技术上必须放在一个仓库里

有人会问:既然法律上是五个资产,为什么不拆成五个仓库?拆开在技术上是可行的,在维护成本上不可行。MOABB 的加载器是按数据集类组织的,一个类对应一个缓存目录;镜像要保证「下载 → 指路径 → 加载」三步成立,就必须让目录层级与加载器期望的层级一致。把这些目录分散到多个仓库,等于把「一次取十个子集」变回「写十个下载脚本」,镜像的价值随之消失。

还有一个更细的技术原因:部分子集的加载器会在首次加载时把压缩包解压到缓存目录旁边,这意味着目录必须是可写的,且解压产生的文件会被加载器在下次加载时检查。把这类子集放进一个统一的可写缓存区,比让使用者自己拼路径要稳定得多。数据卡对几个子集专门注明「下载到你自己的文件夹」,就是这个原因。

于是形成了一个结构性的两端:技术上越是要合并,法律上越是要拆开。这个张力无法消解,只能在文档层显性化。数据卡的做法是把两者的边界写在同一张表的同一行里——左边是被试数与导联数,右边是许可与授权方。这种并置是有设计意图的,但它假定使用者会把整行读完。

3.3 许可在这份仓库里的实际分布

许可 子集数 被试合计 体量合计 允许商用 允许分发派生
CC0 1.0 10 182 约 105 GB 是 是
CC BY 4.0 15 475 约 510 GB 是,需署名 是,需署名
ODC-By 1.0 2 124 约 7 GB 是,需署名 是,需署名
CC BY-ND 4.0 3 32 约 2 GB 是,需署名 否
CC BY-NC-ND 4.0 2 28 约 13 GB 否 否
合计 32 841 637 GB — —

把这五行读完,可以得出一个反直觉的结论:受约束最大的不是体量最大的子集,而是体量最小的那几个。三个 ND 子集加起来只有约两 GB、三十二名被试,它们却是 BCI 竞赛时代最常被引用的基线。十名被试的 BNCI2014_001 出现在无数论文的方法节里,说「我们在 BCI IV 2a 上验证了……」。这批被引用最多的数据,恰好是权利条件最严的那一批。

CC0 那一行的十个子集则是另一极。其中 Lee2019_MI 有五十余名被试、六十二个导联、一千赫兹采样,WRCC2023 三个子集带卒中人群,GuttmannFlury2025_MI 有六十名被试与六十三个会话。这一组在体量与多样性上并不寒酸,却在讨论中被提得少,原因大概与「无条件开放」这件事本身的传播力有关:越是没有门槛的资产,越不容易被单独提及。

3.4 「原样搬运」这句话到底保证了什么

数据卡说「从上游压缩包解出来的文件保留原字节」,Weibo2014 额外按 MOABB 的习惯改了文件名。这句话保证的是完整性与可比性,不保证的是语义正确性。

保证项 是否保证 说明
文件内容与上游一致 是 逐文件比对大小与上游校验和
文件名与上游一致 多数是,Weibo2014 例外 改名只为对齐 MOABB 解压习惯,字节不变
目录结构与上游一致 否 按 MOABB 缓存布局重排
子集内部文件齐全 未必 多个子集只收了 MOABB 加载所需的部分
事件语义与上游一致 由 MOABB 加载器承担 镜像不改事件,但加载器会重命名
上游说明文档齐全 部分 BNCI 系带 description.pdf,其他多不带
上游的伦理条款可见 否 伦理约束在原始论文与知情同意书里,不在仓库里

倒数第二行值得展开。Yang2025 在这个仓库里只有两类部分,三类部分(十一名被试)与若干 JPEG 图像被留在仓库之外;Lee2019_MI 只收了运动想象文件,同一 GigaDB 数据集里的 ERP 与 SSVEP 记录不在其中;Beetl2021_A 只取了三名被试,S4 与 S5 属于另一个子集;Vagaja2023 只取了运动想象记录,静息与具身感记录被排除。这些裁剪都是合理的——加载器不需要它们——但它们意味着「这个仓库等于 MOABB 的子集」这句话只在加载器视角下成立,不是上游数据集的全貌。

3.5 时间与地理的散乱

仓库没有统一的采集时间线。子集的发表年份跨度从二〇〇四年前后(PhysionetMI 的数据源可追溯到更早的 BCI2000 研究)一直到二〇二五年,设备从早期的模拟放大器到现代的高密度系统,记录范式从单会话短任务到多日长时训练。这种散乱带来一个不常被提到的后果:拼合多个子集时,你得到的不只是更多样本,还有一个把二十年设备演进压缩在一起的混合分布。域偏移的问题在跨子集实验里会比跨被试实验更严重,而这一点在许可讨论中往往被忽略——但它是决定「能不能拼」的第二个理由,与法律理由并列。

§4 质量与特色:核验做得比多数镜像细

4.1 逐文件的校验和不只写在文档里

多数镜像仓库存量在上传时算一次哈希,之后不再回访。这个仓库的做法更进一步:每个文件在镜像时被比对大小与上游校验和,上游若提供 MD5、SHA-1、SHA-256 或压缩包内成员的 CRC-32 就一并比对;每次提交之后再核 Hub 侧的 SHA-256 与已验证下载是否一致。这一步把「上传时对不对」与「放久了对不对」分开处理。

核验环节 方法 何时执行 覆盖面
镜像时 大小 + 上游校验和 逐文件,入库时 全部文件
提交后 Hub 侧 SHA-256 对比 每次提交 全部文件
全量回放一 无令牌新机器恢复 + MOABB 加载 十月初,11 个子集全量 + 13 个子集前两名被试 当日新增子集为主
全量回放二 第二台机器恢复 + 逐文件校验 + 加载 十月中,29 个子集前两名被试 633 个文件、35.6 GB
补充核验 上游 MD5 + MOABB 加载 三个 WRCC2023 子集下载时 全部被试
已知例外 一个 Zenodo 记录缺两个链接字段 回放二时发现 文件清单未变

最后两行是这个仓库在诚实度上最有说服力的地方:它把一个没通过逐字节比对的例外单独写出来,说明哪个字段缺失、为什么不影响加载。多数镜像会把这个例外省掉。

4.2 案例:BNCI2014_001 那一行

用一行数据把「技术位置与法律条件错位」演示一遍,比任何抽象论述都清楚。选 BNCI2014_001,因为它是九个被试、二十二个导联、两千五百赫兹的小子集,离线也能看完;因为它被引用得极多;也因为它正好是三个 ND 子集里最出名的一个。

它的许可原文是 CC BY-ND 4.0,授权方写的是格拉茨工业大学知识发现研究所。它在仓库里的路径是 BNCI2014_001/MNE-bnci-data/~bci/database/001-2014/,文件名是 A01T.mat、A01E.mat 一路到 A09E.mat,另附一份 description.pdf。文件名里的 T 与 E 分别对应训练与评估两段,一名被试一次实验被切成两批文件,加载器把它们当作两个会话。

现在把这条轨迹放在一起看:一个有九个被试的数据集,被放在一个共同根目录下;它的文件名沿用上游;它的许可写在一份四十九 KB 的 README 里;它的授权方是一个与自己无关的机构。从文件系统看,它和隔壁的 CC0 子集没有任何区别——同样的仓库、同样的下载函数、同样的一行 MOABB 调用。从权利看,它是全场最不能动的一类。

§4.2 的案例随后会在五个地方被再用一次:讲清 ND 与 NC 的分界、讲清派生的判定、讲清整包商用的越界、讲清台账的设计、讲清交付前的检查。这也是全篇唯一一个从数据卡第一行读到最后一列的样本。

4.3 体量与取数之间的取舍被写成了文档

数据卡的总览段没有只报总数,还报了一组分布性的判断:六成体量在单个子集;十五个轻量子集承载约一半被试;十个子集沿用上游数字文件名,按上游名字搜索找不到。这三条都属于「不读文档就会踩」的信息,而它们被放在最前面,说明作者知道使用者的第一反应是「先把整包拉下来」。

总览陈述 对使用者的直接含义 若忽略会怎样
六成体量在 Stieger2021 按需取子集,别整包拉 磁盘与带宽被一个子集吃掉
十五个轻量子集承载约一半被试 做被试量大的实验不必下大文件 误以为大数据才有价值
十个子集用上游数字文件名 按上游文件名搜不到 找不到文件,以为下载失败
五个子集不许分发修改版 派生只能在内部 交付包里带了违规派生物
十个上游托管方 授权咨询要找上游 把授权问题问到镜像维护者头上

4.4 与「只搬不修」相伴的一个设计选择

镜像选择不改事件名。事件名的统一由 MOABB 加载器在读取时完成,文件里保留原始标记。这个选择的好处是字节可追溯,坏处是「事件语义」这件事变成了对加载器版本的依赖。

依赖项 由谁决定 变化风险 缓解方式
事件名到类别的映射 MOABB 加载器 版本升级可能改名 固定加载器 commit
trial 切分的窗长与基线 MOABB 默认参数 影响样本数 显式传参并记录
导联选择(部分子集只取子集导联) MOABB 加载器 影响通道维度 加载后打印通道清单存档
采样率是否重采样 不重采样,保持原始 跨子集不一致 自己定统一重采样策略
会话合并规则 各子集不同 会话数口径不一 以加载器返回的会话键为准

数据卡在加载说明里指定了一个具体 commit,并说明其中有十八个子集在更早的正式版也能加载。这条信息很有用:它把「用哪个版本的加载器」从一个隐含假设变成了一个显式参数。做长期项目时,把这个 commit 写进环境文件,比写「moabb 最新版」稳。

4.5 一个容易被忽略的特色:逐子集的取数代码

数据卡给三十二个子集各写了一段加载示例,每段都包含三样东西:该子集的文件名模式、需要设置的环境变量、以及一行取数调用。这看起来只是文档功夫,实际解决的是一个很具体的问题——MOABB 的环境变量名并不统一,BNCI 系共用一个,PhysioNet 系用另一个,Beetl 与 Kaya 各用各的。写错变量名,加载器会静默地去联网下载,而不是报错。

#-- 按子集名设置正确的环境变量,否则加载器会静默回落到联网下载
import os

from huggingface_hub import snapshot_download

ROOT = "EEGDash/eeg-mi-datasets"

#-- 每个子集对应哪个环境变量,写成表比写成一串 if 更不容易错
ENV_BY_SUBSET = {
    "BNCI2014_001": "MNE_DATASETS_BNCI_PATH",
    "PhysionetMI": "MNE_DATASETS_EEGBCI_PATH",
    "Cho2017": "MNE_DATASETS_GIGADB_PATH",
    "Beetl2021_A": "MNE_DATASETS_BEETL_PATH",
    "Kaya2018": "MNE_DATASETS_KAYA2018_PATH",
}


def fetch(subset, pattern, local_root):
    #-- allow_patterns 收窄到单个子集,避免整包下载
    pattern = f"{subset}/{pattern}"
    return snapshot_download(
        ROOT,
        repo_type="dataset",
        allow_patterns=[pattern],
        local_dir=os.path.join(local_root, subset),
    )


def wire_env(subset, local_root):
    key = ENV_BY_SUBSET.get(subset)
    if key is None:
        raise KeyError(f"未登记的子集,请先查数据卡确认变量名:{subset}")
    os.environ[key] = os.path.join(local_root, subset)
    return key


if __name__ == "__main__":
    path = fetch("Cho2017", "*/s01.mat", "./eeg-cache")
    print("落地目录:", path)
    print("已设置:", wire_env("Cho2017", "./eeg-cache"))

这段代码的两个细节值得留意。fetch 把子集名拼进 allow_patterns,从结构上杜绝了误下整包;wire_env 用一个显式映射表代替散落的设置语句,未登记的子集直接抛错,而不是静默回落到联网。第二种做法在许可审计时也有用:被登记过的子集,说明至少有人读过它那一行。

§5 怎么拿到:许可台账与取数流程

5.1 先把许可读成一张表

在下载任何字节之前,先把数据卡的子集表读成机器可读的结构。这一步用标准库就能完成,不需要登录,也不需要令牌。

#-- 把数据卡的 32 行子集表读成台账,许可文本单独成列
import re
import urllib.request

CARD = ("https://huggingface.co/datasets/EEGDash/eeg-mi-datasets"
        "/raw/main/README.md")

LICENSE_TAGS = {
    "CC0": "allow",
    "CC BY 4.0": "allow",
    "ODC-By": "allow",
    "CC BY-ND": "no-derivative",
    "CC BY-NC-ND": "no-commercial-no-derivative",
}


def classify(license_cell):
    #-- 顺序敏感:先匹配最长的标签,避免 BY 抢先命中 BY-NC-ND
    for tag in ("CC BY-NC-ND", "CC BY-ND", "ODC-By", "CC BY 4.0", "CC0"):
        if tag in license_cell:
            return LICENSE_TAGS[tag]
    return "unknown"


def fetch_card():
    req = urllib.request.Request(CARD, headers={"User-Agent": "eegdash-ledger/1.0"})
    with urllib.request.urlopen(req, timeout=30) as r:
        return r.read().decode("utf-8")


def parse(card):
    rows = []
    for line in card.splitlines():
        cells = [c.strip() for c in line.strip("|").split("|")]
        if len(cells) >= 12 and re.fullmatch(r"\d+", cells[0]):
            rows.append({
                "index": int(cells[0]),
                "subset": cells[1],
                "subjects": int(cells[3]),
                "sessions": int(cells[4]),
                "channels": cells[6],
                "rate": cells[7],
                "license_cell": cells[-1],
                "policy": classify(cells[-1]),
            })
    return rows


rows = parse(fetch_card())
blocked = [r for r in rows if r["policy"].startswith("no-")]
print("子集总数:", len(rows))
print("受限子集:", len(blocked), "被试合计:", sum(r["subjects"] for r in blocked))
for r in blocked:
    print(f'  {r["subset"]:<22}{r["license_cell"][:40]}')

输出的三行说明可以直接抄进任何立项文档:总数、受限子集数、受限子集的被试合计。把这段代码放进 CI,每次数据卡更新都会重新生成台账,避免「半年前看过一次表」这种状态。

5.2 只取一个子集的一小部分

多数实验在起步阶段只需要一个子集的前几名被试。这一步的关键是把通配符收窄到文件级别,而不是子集级别。

#-- 单子集单被试:本地缓存目录自己定,方便与许可台账一一对应
import os

from huggingface_hub import snapshot_download

path = snapshot_download(
    "EEGDash/eeg-mi-datasets",
    repo_type="dataset",
    allow_patterns=["BNCI2014_001/*/A01*"],
    local_dir="./lic-bnci2014001-nd",
)

#-- 目录名里带许可缩写,磁盘自己会说话
os.environ["MNE_DATASETS_BNCI_PATH"] = os.path.join(path, "BNCI2014_001")
print("准备就绪:", os.environ["MNE_DATASETS_BNCI_PATH"])

目录名写成 lic-bnci2014001-nd 是一种成本极低的防线。它让「这份缓存是哪一档许可」在文件浏览器里就能看见,不依赖任何人记住。团队里换人、换机器之后,这种命名比文档更持久。

5.3 交给 MOABB 加载

#-- 让 MOABB 用本地文件,不联网、不回落
import moabb
from moabb.datasets import BNCI2014_001

#-- 必须在 get_data 之前设置,否则加载器会去问远端镜像
moabb.set_download_provider("upstream")

dataset = BNCI2014_001(subjects=[1])
data = dataset.get_data()

for session_name, runs in data["0"].items():
    for run_name, epochs in runs.items():
        x = epochs.get_data()
        print(session_name, run_name, x.shape)

set_download_provider 这一行是整段代码里最容易漏的。漏掉它,加载器会去一个远端数据仓库取数,而你本地已经有的文件不会被动用。结果看起来一样——数据还是出来了——但你已经把「离线可控」这个前提丢了。

5.4 把受限子集隔离到独立目录树

#-- 允许进入派生与交付链路的子集,按许可分成两档
mc_root="./eeg-cache"

#-- 第一档:无条件开放,可改可商用
for ds in GuttmannFlury2025_MI Kaya2018 Lee2019_MI Pan2023 Pan2025 \
          Rozado2015 WRCC2023_MI_A WRCC2023_MI_B WRCC2023_MI_C Weibo2014; do
  hf download EEGDash/eeg-mi-datasets --repo-type dataset \
     --include "${ds}/*" --local-dir "${mc_root}/${ds}"
done

#-- 第二档:需署名可改可商用,交付时附署名清单
for ds in Cho2017 Dreyer2023 Farabbi2020 GrosseWentrup2009 Jia2019 \
          Kumar2024 Leeuwis2021 Liu2024 Shin2022 Stieger2021; do
  hf download EEGDash/eeg-mi-datasets --repo-type dataset \
     --include "${ds}/*" --local-dir "${mc_root}/${ds}"
done

#-- 受限子集单独一棵树,永不进入交付目录
hf download EEGDash/eeg-mi-datasets --repo-type dataset \
   --include "BNCI2014_001/*" --local-dir "./eeg-restricted/BNCI2014_001"

两个根目录,一条纪律:eeg-restricted/ 下的东西只能内部用,不进交付物、不进镜像、不进对外共享盘。这条纪律不靠自觉,靠物理隔离——当两个根目录不在同一个共享盘上,误打包的概率会大幅下降。

5.5 交付前的一张检查表

检查项 做法 通过标准
交付物里有没有受限子集的文件 对交付目录跑路径前缀匹配 命中数为零
有没有受限子集的派生文件 检查派生目录来源清单 无 ND 来源
商用场景有没有 NC 子集 比对台账的商用列 无 NC
署名是否齐全 按引用清单逐项核对 每个使用的子集都有对应引用
是否把上游 ID 改成了自己的名字 抽查路径 保留上游标识
台账与磁盘是否一致 用台账遍历磁盘 无多无少
加载器版本是否固定 查看环境文件 记录到 commit

最后一项容易被当成洁癖。它不是。事件名与 trial 切分都依赖加载器版本,两个版本的加载器可以让同一个子集的样本数差出一截。在复现性文档里固定 commit,是把「可复现」从口号变成事实的低成本做法。

5.6 用 Git 之外的方式判断文件完整性

#-- 不下载全量也能核对:只取大小与 LFS 指针,对同一子集做二次校验
import json
import urllib.request

REPO = "EEGDash/eeg-mi-datasets"
API = f"https://huggingface.co/api/datasets/{REPO}/tree/main"


def tree(path=""):
    url = API if not path else f"{API}/{path}"
    req = urllib.request.Request(url, headers={"User-Agent": "eegdash-audit/1.0"})
    with urllib.request.urlopen(req, timeout=30) as r:
        return json.loads(r.read().decode("utf-8"))


def total_bytes(subset):
    items = tree(subset)
    size = 0
    for it in items:
        if it["type"] == "file":
            size += it.get("size", 0)
        elif it["type"] == "directory":
            size += total_bytes(it["path"])
    return size


for name in ("Cho2017", "Lee2019_MI"):
    n = total_bytes(name)
    print(f"{name}: {n / 1024 ** 3:.2f} GB")

这段代码的意义在于预算与核对,而不是审计。它回答的是「我要取的子集大概多大」「下载下来的目录大小与远端声明是否一致」两个问题,不需要把六百多 GB 拉到本地。

§6 与库内词条的关系

6.1 关系图谱

库内词条 关系 差异点 使用建议
EEGMMIDB(同源,在镜像里以 PhysionetMI 之名) 同一上游数据的两条入口 本仓库是 ODC-By 镜像,原词条直取 PhysioNet 要许可原文去 PhysioNet,要同构目录用本仓库
BCI Competition IV 2a(在镜像里以 BNCI2014_001 之名) 同一上游数据的两条入口 本仓库那一份是 ND,竞赛原始发布同样是 ND 两处都不可分发派生,注意别以为换了入口就换了许可
BCI Competition IV 2b(BNCI2014_004) 同上 仅三个导联,四十五次会话,ND 导联少,做空间滤波要谨慎
其他脑电基准词条 同族兄弟 多为单一数据集、单一许可 单数据集词条讲深,本篇讲横向与许可
神经影像平台类词条 上游生态 本仓库的数据多来自这些平台 授权咨询、版本确认走平台原页
脑机接口解码方法词条 下游消费者 方法是消费者不是数据 方法论文里引用数据时按子集引用

这张表里最重要的一行是第一行与第二行。同一条上游数据在这个百科里有两条入口,两条入口的许可写法可能不同——本仓库用 SPDX 短名加授权方,原始页面用自然语言描述。遇到两边看起来不一致时,以授权方自己的页面为准,并把差异记下来,而不是挑对自己方便的那一个。

6.2 检索路径

你要找的东西 在哪一层 检索方法 会不会被许可拦住
某个任务范式的子集 子集表的类别列 按事件名过滤,如含 feet 的子集 部分被拦,需看许可列
某个被试量的子集 子集表的被试列 按被试数排序取前几名 通常不会,大体量多为 BY
某个被试人群 子集表的被试人群列 搜 stroke,得到四个子集 不会,卒中子集多为 BY 或 CC0
某个上游托管方 子集表的来源列 按域名筛,如 GigaDB 不会
某个具体文件 文件树 按路径前缀,注意十个子集无扩展名 不会,但可能找不到
某个许可下的全部子集 子集表最后一列 按许可文本匹配,见 §5.1 不会
某个加载器的环境变量 数据卡的加载段 按子集名的小节查 不会

§7 质量评估与局限性

7.0 阅读本节前的一个前置校正

在给分之前必须先校正一处默认口径。通常评估一个数据集时,质量分反映的是数据本身的属性:覆盖、标注、均衡、可复现。但对这个仓库,如果照这个口径打分,会把最要紧的东西漏掉,因为它的得分分布会呈现出一种规律性的错位——技术质量高的子集往往不是法律上最宽松的子集,反过来也一样。

具体说,三个 ND 子集在技术上是精细的:BCI 竞赛的数据有严格的范式、统一的描述文档、明确的评估划分,九个或十四名被试的训练与评估文件分得清清楚楚。按常规口径,它们该得高分。而它们恰恰是全仓最难流通的资产。如果只看质量分就选数据,选出来的会是最不该外发的那一批。

另一个方向的误判同样常见。CC0 组里有若干子集被试少、会话短、导联配置不统一,按常规口径分数偏低,但它们在法律上是最自由的,可以进产品、可以改、可以再做分发。一个只按质量分排的选型表,会把这一组排到后面。

所以本节的分不回答「这个仓库好不好」,而回答「按什么维度分、在什么用途下哪一项才重要」。下文五维评分中单列了一项许可清晰度,并把「许可本身宽松」与「许可披露清楚」分开计分——这两件事经常被混为一谈。

7.1 五维评分

维度 分数 依据 主要扣分处
结构一致性 4.5 / 5 三十二个子集同构,路径与加载器一一对应 十个子集路径为数字,检索困难
许可披露 4 / 5 子集级许可与授权方逐行列出 仓库级 tags 并列五种,易被整包化
许可宽松度 2.5 / 5 五个子集受限,其中两个禁商用 受限者恰是最常被引用的基线
数据完整性 4.5 / 5 逐文件校验和,两轮全量回放 一个 Zenodo 记录有一处已知例外
可复现性 4 / 5 指定加载器 commit,逐子集示例 事件语义依赖加载器版本
生态配套 5 / 5 上游生态完整,引用清单逐子集列出 无
综合 4.1 / 5 结构与完整性接近满分,宽松度是短板 「能不能用」与「能不能传」是两件事

第五行的分数需要解释。许可宽松度给二点五不是批评作者,而是对仓库内容组合的客观描述:把一组权利条件不同的资产放在一起,整体的可流通性由最严的那一份决定。作者无法改变这一点——上游就那个条件。

7.2 三种用途下的重新排序

用途 最重要的维度 本仓库的得分 该怎么用
论文复现 可复现性、数据完整性 高 直接按子集取,固定加载器 commit
论文里的跨数据集评测 结构一致性 高 用允许派生的子集做评测主集,受限子集只做内部对比
产品研发 许可宽松度 中低 只用 CC0 与 CC BY 组,建立台账与隔离
对外发布派生数据集 许可宽松度 + 披露 低 排除五个受限子集,其余按署名要求处理
教学与课程实验 取数便利 高 取轻量子集,控制下载量

7.3 已知的、可枚举的偏差

人群偏差。 三十二个子集里,健康被试占绝大多数。带卒中标签的只有 Jia2019、Liu2024 与三个 WRCC2023 子集,合计九十余名被试。三个 WRCC2023 子集各注明「九人中有两人卒中,未说明是哪两人」,这条信息缺失会直接影响分层分析——你无法按健康状况切分,只能把整个子集当作混合人群处理。

年龄段偏差。 数据卡的人群列多数只写 healthy 或留空,未给年龄区间。做年龄相关分析时,这一列的信息量为零,必须回到各上游论文去补。

设备与配置偏差。 导联从三到一百二十八,采样率从一百六十到一千赫兹。这些差异本身不算偏差,但会把「跨子集」实验变成「跨设备」实验。GrosseWentrup2009 的 128 导与 BNCI2014_004 的 3 导之间,几乎没有共用的空间滤波基础。

会话结构偏差。 会话数从三次(Beetl2021_A)到五百九十八次(Stieger2021)。跨会话泛化的定义在不同子集上指向不同难度,直接横向比准确率没有意义。

标签语义偏差。 Kaya2018 有三类,其中 passive 不是运动想象任务;Rozado2015 只有左手与静息两类;Weibo2014 有七类,包含复合任务。把「两类」与「七类」放在同一张表里比较准确率,是在比不同的题目。

体量偏差。 每被试体量从不足零点一 GB 到六 GB 以上,差了两个数量级。这会让人误判「数据越多越好」,而事实上体量最大的子集被试数只有中等。

7.4 外部验证矩阵

验证角度 做法 结论 局限
与上游逐字节比对 校验和 + 大小 除一个例外全部一致 只证明没被改,不证明上游正确
与上游加载对比 同一被试在本仓库与上游各加载一次 事件与形状一致 未覆盖全部被试
与文献报告的被试数对比 抽查若干子集的被试数 与原始论文一致 抽查而非全查
与 MOABB 数据集清单对比 106 个里有 9 个未纳入 未纳入原因逐条列出 缺失是可知的,不是隐性的
与同类镜像对比 看是否也做逐文件校验 少见同级别 样本少,不作普遍结论
与许可文本对比 子集表许可与授权方页面 抽查一致 未逐条核对全三十二项

最后一行是需要补充的工作。本文对三个 ND 与两个 NC 子集的许可写了具体条文名称与授权方,但没有对全部三十二行逐条去上游页面复核。数据卡本身做了这件事(它写出每个子集的授权方),但二手陈述终究是二手。

7.5 它为何能持续:把搬运做成了基础设施

这个仓库的生存逻辑不在数据本身——数据都在上游,它没有独占任何内容——而在于它承担了一件上游不愿意做、下游每家都要重做的事:把散落在十个托管方的运动想象脑电,整理成一套可预测的目录。上游是论文作者与机构,他们的激励是发表,不是长期维护下载端点;下游是每一个要跑跨数据集实验的实验室,他们的激励是快点出结果,不是维护下载脚本。镜像站在中间,把重复劳动收敛一次。

可持续的第二根支柱是核验的可展示性。搬运类项目的信任成本极高:使用者无法验证「你搬的东西没被改过」,只能选择相信或不信。这个仓库用逐文件校验和、两轮独立机器回放、公开的例外清单,把信任成本压到了一个可陈述的水平。这套记录本身就是它区别于「热心网友上传」的地方,也是它能被当作基础设施引用的原因。

第三根支柱是克制。它不重采样、不滤波、不改事件名、不做统一导联,因此永远不会因为「处理策略过时」而被淘汰。处理策略会变,原始字节不会。一个只搬不改的镜像,其维护负担随上游增减线性变化,而不会因为自己引入的方法论折旧。

这三条合起来解释了一个看似矛盾的现象:一个没有原创数据、没有标注、没有方法贡献的仓库,可以被大量论文引用为取数入口。它卖的不是数据,是可预测性。

7.6 DAIMS 二十项快速检查

DAIMS 是数据集成熟度的一套通用检查框架,考察的是「数据能不能被机器可靠地找到、读懂、使用、追溯」。下表按五项能力各取四问,逐项给出结论与依据。评分标准为「是/部分/否」,只看仓库自身能证明的部分,不以「上游应该有」代替。

能力 检查项 结论 依据
可发现 有稳定可寻址的入口 是 Hugging Face 数据集页与 API 均可直接访问
可发现 子集可被单独寻址 是 每个子集是顶层目录,可用通配符定位
可发现 有检索用关键词与标签 是 tags 含 eeg、motor-imagery、brain-computer-interface
可发现 有版本或快照标识 部分 有仓库 sha 与最后修改时间,无独立版本号
可访问 无需申请即可下载 是 未设门槛,公开仓库
可访问 可按部分下载 是 支持按路径模式收窄
可访问 离线可用 是 数据显示加载时不依赖远端
可访问 有访问计数或使用记录 部分 平台侧有下载计数,非仓库字段
可理解 有子集级说明 是 数据卡三十二个小节逐子集说明
可理解 有字段或结构说明 部分 有路径与文件名说明,无字段字典
可理解 有事件语义说明 部分 事件名依赖 MOABB 加载器版本
可理解 有许可说明 是 子集表最后一列逐行给出
可互操作 格式有标准 部分 原始格式为通用格式,但未统一
可互操作 命名有既定规范 部分 目录遵循 MOABB,文件名多沿用上游
可互操作 导联命名可对齐 否 各子集沿用各自电极命名
可互操作 有统一时间基准 否 各子集采集时间线独立
可复用 有校验和记录 是 逐文件比对并列出回放范围
可复用 有引用清单 是 逐子集给出上游文献
可复用 有加载示例 是 每个子集一段可运行示例
可复用 有派生许可说明 是 明确写出发送派生副本的限制

这二十项里「是」九项、「部分」八项、「否」三项,未出现「否多于是」的成片短板。三处「否」都集中在互操作层,且都不是镜像能单方面解决的:导联命名与时间基准的统一属于重制数据,一旦做了就不再是镜像。这个分布与 §7.0 的校正口径一致——仓库强在可发现、可访问、可复用,弱在跨子集互操作,而许可这一维的强弱不能用一个分数表达。

§8 生态位与历史

8.1 一条从竞赛到镜像的线索

运动想象脑电的公开共享大体经过三个阶段。第一阶段是竞赛驱动:BCI 竞赛把若干实验室的数据集中发布,统一评估协议,形成最早的一批可比基线,BNCI2014 系列的编号直接来自这套体系。第二阶段是平台驱动:PhysioNet、GigaDB、figshare、Zenodo、Harvard Dataverse 等通用平台承担托管,数据集进入「有 DOI、可引用」的状态,但格式与目录各家自定。第三阶段是框架驱动:MOABB 把一百多个数据集包装成统一的加载器与评估协议,让跨数据集实验第一次变得可写。

阶段 主导者 主要产物 遗留问题
竞赛期 竞赛组织方与参赛实验室 带统一协议的少量数据集 许可以 BY-ND 为主,限制派生
平台期 通用托管平台 DOI 与长期可访问 格式、目录、元数据各行其是
框架期 MOABB 等项目 统一加载与评估协议 下载仍分散,复现依赖网络状态
镜像期 社区镜像项目 一次取齐、离线可用 许可被整包化理解的风险

这个仓库站在第四阶段。它不改变前三个阶段任何一件事,只是把第三阶段的下载环节补上。理解这条线索,才能理解为什么它的许可分布如此不均匀——因为那是三个阶段叠加的结果:竞赛期的数据是 ND,平台期的数据多为 CC BY 与 CC0,近年的新数据倾向 CC0 或 CC BY。

8.2 为什么许可会呈现出这种分布

许可 集中的年代与来源 可能的原因 对本仓库的含义
CC BY-ND 4.0 竞赛期的格拉茨系数据 保留版本一致性,防止被改后冒名 最常被引用的基线不可分发派生
CC BY-NC-ND 4.0 竞赛期后续与德国单中心研究 限制商用,同时限制派生 商业用途直接排除
CC BY 4.0 平台期的多数研究 折中:开放但保留署名 可用需署名,派生需署名
CC0 1.0 近年的大型与公共资助研究 降低使用门槛,鼓励复用 可商用、可派生,最自由
ODC-By 1.0 大型公共数据平台 数据库权利与内容权利分开处理 署名义务与 CC BY 类似,法律构造不同

这张表里有一行值得单独说:ODC-By 与 CC BY 的义务相似(都要署名),但法律构造不同——前者是为数据库设计的,区分数据库权利与内容权利,后者是为作品设计的。这不是学究式的区别。当你把数据与数据库结构一起分发时,ODC-By 的署名义务可能落在结构层,而不只是内容层。PhysionetMI 与 Wang2025 用的是这一套,做产品时要留意。

8.3 它在生态里补的那一格

生态角色 典型项目 提供的价值 本仓库的互补关系
数据来源 各上游托管方 权威、授权方直连 本仓库是它们的下游消费者
加载与评估 MOABB 统一协议与事件语义 本仓库是它的磁盘落地
原始数据规范 BIDS 与 EEG-BIDS 命名与元数据标准 本仓库不强制 BIDS,部分子集带 BIDS 拷贝
镜像与分发 本仓库与同类镜像 一次取齐、离线 互补于上面三类
解码工具 脑电机器学习库 特征、分类、评估 消费本仓库的数据
合规与治理 机构法务与数据治理平台 判定可用范围 需要本仓库的台账作为输入

8.4 一个不写在文档里的边界

镜像的维护者与使用者之间有一条不成文的界线:镜像负责「文件对、路径对、说明对」,使用者负责「权利判断」。这条界线在任何镜像项目里都存在,但很少被明确宣布。它之所以重要,是因为一旦使用者误以为镜像也承担了权利判断,就会出现系统性的越界——不是某个人不小心,而是一群人按同一个错误前提行事。

数据卡用一句很直的话把责任划给了使用者:被滤波或分段的副本同样不得分发。这句话的作用不是解释许可,而是提醒使用者「分发这个动作由你完成,后果也由你承担」。对做产品的人来说,这句话比任何许可摘要都值得多读一遍。

§9 使用指引

9.1 三种角色的路径

算法研究者的最短路径。 目标是尽快跑出一个能写进论文的基线。选被试多、体量小、文档全的子集,PhysionetMI 与 Cho2017 在许可上都属于允许派生的两档,其中后者是 CC BY、前者是 ODC-By。用 MOABB 的跨会话与跨被试两种划分各跑一次,把加载器 commit 与超参写进附录。不要一开始就拼十个子集,跨子集的域偏移会让结果难以解释。

产品工程的最短路径。 目标是确定哪些数据能进产品链路。第一天就建台账:按子集登记许可、授权方、允许用途,写法照 §4.2 的案例 那一行的五个格子来。把 CC0 组作为首选,CC BY 与 ODC-By 作为次选(附署名),五个受限子集只作为算法探索的内部参考,永不进入交付目录。第三天就把 eeg-restricted/ 物理隔离出去,别等到交付前才做。

数据治理者的最短路径。 目标是给出一份能过审的权利说明。把 §2.1 的表整个抄进治理文档,加上一条明确结论:本仓库不是单一许可资产,不可整包登记。对每个进入数据资产目录的子集单独建档,附上游 DOI 与授权方名称。对含 NC 的子集,在资产卡上写死「禁止商用」,而不是「视情况」。

9.2 一条最短的可用流程

#-- 从零到能跑基线:取数、设路径、加载、看形状
python3.11 -m venv .venv
source .venv/bin/activate

pip install "moabb @ git+https://github.com/NeuroTechX/moabb@555d14aebc1f1175e8476faeebabbfcafc522aba"
pip install huggingface_hub

#-- 只取 Cho2017 的第一名被试,许可为 CC BY 4.0
hf download EEGDash/eeg-mi-datasets --repo-type dataset \
   --include "Cho2017/*/s01.mat" --local-dir "./eeg-cache/Cho2017"

#-- 落地后自检:文件在不在、大小对不对
ls -lh ./eeg-cache/Cho2017/Cho2017/*/s01.mat
#-- 环境变量 + 本地提供者 + 加载,三步缺一不可
import os

os.environ["MNE_DATASETS_GIGADB_PATH"] = os.path.abspath("./eeg-cache/Cho2017")

import moabb
from moabb.datasets import Cho2017

moabb.set_download_provider("upstream")
dataset = Cho2017(subjects=[1])
data = dataset.get_data()

for _, session in data.items():
    for run_name, epochs in session.items():
        arr = epochs.get_data()
        print(run_name, arr.shape, epochs.times[0], epochs.times[-1])

这段流程的全部时间花在安装依赖上,数据本身只有几十兆。对刚接手的人来说,先跑通一个小子集,比先搞清楚三十二个子集的区别更重要——后者会在跑通之后变得自然。

9.3 引用方式

引用的最小单位是子集,不是仓库。数据卡为三十二个子集逐个列了引用文献,做研究时按实际使用的子集逐条引用,别用一个仓库名代替。仓库本身没有独立 DOI,被引用时应给出 URL 与访问日期。

EEGDash. EEG motor imagery datasets [Data set]. Hugging Face.
https://huggingface.co/datasets/EEGDash/eeg-mi-datasets
(accessed 2026-10-26)

-- 同时在正文中按子集引用上游文献,例如:
Cho, H., Ahn, M., Ahn, S., Kwon, M., & Jun, S. C. (2017).
EEG datasets for motor imagery brain-computer interface.
GigaScience, 6(7), gix034. https://doi.org/10.1093/gigascience/gix034

如果必须为仓库本身写一条引用,建议在方法节里说明三件事:镜像版本或访问日期、使用的子集清单、加载器 commit。这三项决定了别人能不能复现你取到的具体字节。

§10 AI 使用声明

项 内容
生成方式 由大语言模型辅助起草,结构与事实核对由编辑完成
事实来源 EEGDash 数据卡全文、Hugging Face 数据集 API、Europe PMC 检索到的两篇综述与基准摘要
未核验项 全三十二行许可未逐条回访上游页面;被试年龄与性别未核对
数字口径 规模与结构数字取自数据卡;体量分布由子集表逐行加总
代码可运行性 全部 python 与 bash 块不依赖私有凭据,路径为公开地址或本地相对路径
已知偏差 以官方页面陈述为主,未做独立审计
更新触发 数据卡子集表或 tags 变更
责任边界 许可判定不构成法律意见,商用前请咨询法务

常见误读(避坑清单)

常见说法 实际 证据
这个仓库是 CC BY 4.0 五个许可并列,逐子集适用 数据卡 tags 列出五个许可标识符,子集表最后一列逐行给出
都是公开数据,商用没问题 两个子集含 NC 条款,商业用途被排除 BNCI2015_001 与 Brandl2020 的许可为 CC BY-NC-ND 4.0
只下载不修改就不受 ND 管 ND 管的是分发派生副本,滤波分段也算 数据卡写明被滤波或分段的副本同样不得分发
我预处理之后就是新数据集了 预处理不改变上游权利,派生物的权利由原许可决定 许可条款随作品走,不随加工者走,见 §4.2 的案例
库里有 BCI IV 2a,换个入口许可就松了 两个入口指向同一条上游数据,条件相同 BNCI2014_001 的授权方仍是格拉茨工业大学
32 个子集就是 MOABB 的全部 MOABB 有 106 个运动想象数据集,9 个未能脚本获取 数据卡总览段注明未纳入原因
仓库里有某个子集的全套文件 多个子集只收了加载器需要的部分 Yang2025 只有两类部分,Lee2019_MI 只收运动想象文件
被试越多体量越大,按体量选就好 体量与价值无单调关系,六成体量在单个子集 Stieger2021 六百多 GB 级体量只占 7% 被试
用上游文件名能在文件树里搜到 十个子集沿用上游数字 ID,无扩展名 数据卡总览段指出这类路径搜不到
加载成功就说明取到了本地文件 变量名写错会静默回落到联网下载 需在加载前设置正确的环境变量并调用本地提供者

FAQ

Q1:整个仓库可以用 CC BY 4.0 吗?
不能。仓库的 tags 里并列五个许可,其中五个子集是 CC BY-ND 4.0 或 CC BY-NC-ND 4.0,权利条件比 CC BY 4.0 严格得多。整包使用时要按最严的子集倒推,逐子集核对。

Q2:我做了滤波和分段,算不算修改版本?
数据卡明确写明,被滤波或分段的副本同样不得分发。因此对那五个子集,缓存或入库内部可以使用,但对外交付的派生物不行。

Q3:五个非商用子集是哪些?
BNCI2014_001、BNCI2014_002、BNCI2014_004 为 CC BY-ND 4.0;BNCI2015_001 与 Brandl2020 为 CC BY-NC-ND 4.0。后两个带 NC,商业用途直接排除。

Q4:只用 CC0 的子集做产品可以吗?
CC0 1.0 那一组共有十个子集、一百八十余名被试,允许无条件的复制与改造。但要注意别把同仓库的 ND 子集顺带打包进去,也不要把某些子集自带的伦理条款当成不存在。

Q5:为什么有的目录名是数字?
十个子集沿用了 MOABB 缓存时的名字,多为上游托管方的数字文件 ID,不带扩展名。这类路径按上游文件名搜索找不到,只能按子集名定位。

Q6:不用 MOABB 能读吗?
能。文件是 MAT、EDF、BDF、EEGLAB、BrainVision、XDF、NumPy、CSV 等原始格式,任何脑电处理库都能读。MOABB 提供的只是目录约定与事件语义,用了它少踩很多事件映射的坑。

Q7:这个仓库有自己的 DOI 吗?
数据卡没有给出仓库级 DOI,引用应给 URL 与访问日期,并按实际使用的子集逐条引用上游文献。上游 DOI 在数据卡的来源列里。

Q8:为什么有的子集只有两名被试的文件能用?
不是只有两名能用,而是校验回放时只加载了前两名被试。数据卡对回放范围写得很具体,别把「回放范围」误当成「可用范围」。

Q9:整包下载会很慢吗?
全仓六百多 GB,其中六成在单个子集。按需取子集通常只有几百兆到几 GB,官方页面给的示例都是按子集加通配符收窄。

Q10:可以把受限子集的缓存打包给同事吗?
不行,那正是「分发副本」。内部同一法人下的使用与对外交付要分开判断,跨组织传递基本都会被视作分发。

Q11:我训出的模型权重受 ND 约束吗?
许可文本约束的是数据与派生数据,模型权重的性质在司法实践上尚无统一结论。保守做法是把权重也纳入受限范围,别把「对生成物没有明确规定」当成「没有限制」。

Q12:纸面上写「基于公开数据集」够不够?
不够。应写明具体子集名、镜像版本、访问日期与加载器 commit,这样别人才能取到同一批字节。许可上也要逐个注明,尤其是 ND 与 NC 的子集。

术语表

术语 含义 在本仓库里的具体所指
MOABB Mother of All BCI Benchmarks,脑机接口基准框架 定义了本仓库的目录约定与事件语义
运动想象 想象肢体动作而不实际执行 多数子集的范式,左手、右手、双脚、舌头
缓存布局 加载器期望的本地目录层级 顶层为子集名,下接上游目录
会话 一个被试的一次记录场合 与 session 同义,子集间定义有差异
事件名 MOABB 给类别起的统一名字 left_hand、right_hand、feet、rest 等
CC BY 4.0 署名即可使用与派生 十五个子集适用
CC BY-ND 4.0 署名可用,禁止分发派生 三个竞赛系子集适用
CC BY-NC-ND 4.0 署名可用,禁止商用与派生 两个子集适用
CC0 1.0 放弃权利,无条件使用 十个子集适用
ODC-By 1.0 数据库类署名许可 两个子集适用
派生数据 对原作加工后形成的新数据 滤波、分段、特征化都算
分发 把副本交给他人 跨组织传递基本都算
授权方 有权授权的主体 上游机构,不是镜像维护者
校验和 用于核对文件未被改动的哈希 上游 MD5、SHA-1、SHA-256、CRC-32
上游托管方 原始发布平台 十个,含 BNCI Horizon、Zenodo 等
通配符取数 按路径模式收窄下载范围 官方示例的主要取数方式
加载器 commit 固定的加载器代码版本 决定事件名与样本数
跨被试划分 训练与测试用不同被试 MOABB 两种评估协议之一
跨会话划分 训练与测试用不同会话 MOABB 另一种评估协议
域偏移 训练与测试分布不一致 跨子集拼合时最严重
卒中人群 带卒中标签的被试 四个子集,合计九十余人
健康被试 无临床诊断记录的参与者 多数子集的主体
导联 头皮电极通道 从 3 到 128 不等
采样率 每秒采样点数 从 160 到 1000 Hz
台账 逐子集的权利登记 建议自建,仓库不提供
隔离目录 受限子集的独立存放位置 建议与交付目录物理分离

附录 A:核心数字核对表

项 值 来源 来源层级
子集数 32 数据卡总览 官方页面
被试数 841 数据卡总览 官方页面
会话数 1,917 数据卡总览 官方页面
体量 637 GB 数据卡总览 官方页面
文件数 4,077 数据卡总览 官方页面
上游托管方 10 数据卡总览 官方页面
导联范围 3 到 128 数据卡总览 官方页面
采样率范围 160 到 1000 Hz 数据卡总览 官方页面
许可种数 5 tags 与 cardData 官方 API
受限子集数 5 子集表逐行统计 官方页面(本文加总)
受限子集被试合计 60 子集表逐行统计 官方页面(本文加总)
单子集最大体量 377 GB 子集表 官方页面
MOABB 运动想象子集总数 106 数据卡总览 官方页面
未能脚本获取的子集 9 数据卡总览 官方页面
首次发布日期 不详 tags 与 API 未核实

附录 B:数字的来源分层

第一层:官方页面。 上表中标注为官方页面的数字全部来自数据卡与数据集 API 的返回值,包括子集数、被试数、会话数、体量、文件数、托管方数、导联与采样率范围、许可标识符、逐子集许可与授权方、校验和回放范围。这一层是本文的主干。

第二层:论文摘要。 两处背景性判断参照了 Europe PMC 检索到的摘要:一是跨被试与跨个体差异导致的解码不稳定,二是公开脑电数据在传感器、范式、事件语义、预处理上普遍异构,导致跨数据集学习的可复现性受限。这两项支持了 §4 与 §7 中关于域偏移与被试量小导致统计脆弱的论点,但不用于支撑任何具体规模数字。

第三层:未核实。 一是采集时间范围,本文写作「从二〇〇四年前后到二〇二五年」,依据是各子集上游发表年份的归纳,仓库本身没有这个字段。二是被试的年龄、性别与教育程度分布,数据卡没有系统给出,本文未作任何估计。三是模型权重是否属于派生数据,属法律解释问题,本文只给出保守建议。四是全部三十二行的许可未逐条回访上游页面复核。

附录 C:完整参考文献

  1. 数据卡与仓库:EEGDash. EEG motor imagery datasets [Data set]. Hugging Face. https://huggingface.co/datasets/EEGDash/eeg-mi-datasets
  2. MOABB 项目主页。https://moabb.neurotechx.com/
  3. Jayaram, V., & Barachant, A. (2018). MOABB: trustworthy algorithm benchmarking for BCIs. Journal of Neural Engineering, 15(6), 066011. https://doi.org/10.1088/1741-2552/aadea0
  4. Tangermann, M., Müller, K.-R., Aertsen, A., 等 (2012). Review of the BCI Competition IV. Frontiers in Neuroscience, 6, 55. https://doi.org/10.3389/fnins.2012.00055
  5. Schalk, G. (2009). EEG Motor Movement/Imagery Dataset (version 1.0.0). PhysioNet. https://doi.org/10.13026/C28G6P
  6. Cho, H., Ahn, M., Ahn, S., Kwon, M., & Jun, S. C. (2017). EEG datasets for motor imagery brain-computer interface. GigaScience, 6(7), gix034. https://doi.org/10.1093/gigascience/gix034
  7. Lee, M.-H., Kwon, O.-Y., Kim, Y.-J., 等 (2019). EEG dataset and OpenBMI toolbox for three BCI paradigms. GigaScience, 8(5), giz002. https://doi.org/10.1093/gigascience/giz002
  8. Dreyer, P., Roc, A., Pillette, L., Rimbert, S., & Lotte, F. (2023). A large EEG database with users’ profile information for motor imagery BCI research. Scientific Data, 10, 580. https://doi.org/10.1038/s41597-023-02445-z
  9. Stieger, J. R., Engel, S. A., & He, B. (2021). Continuous sensorimotor rhythm based brain computer interface learning in a large population. Scientific Data, 8, 98. https://doi.org/10.1038/s41597-021-00883-1
  10. Liu, H., Wei, P., Wang, H., 等 (2024). An EEG motor imagery dataset for brain computer interface in acute stroke patients. Scientific Data, 11, 131. https://doi.org/10.1038/s41597-023-02787-8
  11. Brandl, S., & Blankertz, B. (2020). Motor imagery under distraction — an open access BCI dataset. Frontiers in Neuroscience, 14, 566147. https://doi.org/10.3389/fnins.2020.566147
  12. Kaya, M., Binli, M. K., Ozbay, E., Yanar, H., & Mishchenko, Y. (2018). A large electroencephalographic motor imagery dataset for electroencephalographic brain computer interfaces. Scientific Data, 5, 180211. https://doi.org/10.1038/sdata.2018.211
  13. Creative Commons. Attribution-NoDerivatives 4.0 International. https://creativecommons.org/licenses/by-nd/4.0/
  14. Open Data Commons. ODC Attribution License (ODC-By) v1.0. https://opendatacommons.org/licenses/by/1-0/
  15. Europe PMC 检索式与结果:MOABB motor imagery EEG benchmark,含一篇跨数据集可复现性系统综述与一篇多解码器排序基准摘要。https://www.ebi.ac.uk/[europepmc](https://www.qianfanghub.com/ai-ready-dataset/europepmc/1353)/webservices/rest/search

附录 D:任务代码

#-- 一个完整的许可审计脚本:解析数据卡、分档、给出可用建议
import json
import re
import urllib.request

CARD_URL = ("https://huggingface.co/datasets/EEGDash/eeg-mi-datasets"
            "/raw/main/README.md")

POLICY = [
    ("CC BY-NC-ND", "nc-nd", False, False),
    ("CC BY-ND", "nd", True, False),
    ("ODC-By", "odc-by", True, True),
    ("CC BY 4.0", "by", True, True),
    ("CC0", "cc0", True, True),
]


def read_card():
    req = urllib.request.Request(CARD_URL, headers={"User-Agent": "audit/1.0"})
    with urllib.request.urlopen(req, timeout=30) as r:
        return r.read().decode("utf-8")


def rows_of(text):
    out = []
    for line in text.splitlines():
        cells = [c.strip() for c in line.strip("|").split("|")]
        if len(cells) >= 12 and re.fullmatch(r"\d+", cells[0]):
            out.append(cells)
    return out


def policy_of(cell):
    for tag, code, commercial, derivative in POLICY:
        if tag in cell:
            return code, commercial, derivative
    return "unknown", None, None


def audit(text):
    report = {"usable_commercially": [], "research_only": [], "unknown": []}
    for cells in rows_of(text):
        name = cells[1]
        code, commercial, derivative = policy_of(cells[-1])
        if commercial is None:
            report["unknown"].append((name, cells[-1]))
        elif commercial and derivative:
            report["usable_commercially"].append((name, code))
        else:
            report["research_only"].append((name, code))
    return report


if __name__ == "__main__":
    rep = audit(read_card())
    print(json.dumps(
        {k: [n for n, _ in v] for k, v in rep.items()},
        ensure_ascii=False,
        indent=2,
    ))

这段脚本的输出是三张名单:可以直接进商业链路的、只能内部研究的、以及未能识别的。第三张名单通常是空的,如果非空,说明数据卡改了写法,解析规则需要更新——这本身就是一次有意义的告警。

附录 E:如果只记五件事

  1. 这不是一个数据集,是三十二个。技术上在一个仓库里,法律上是三十二份资产,许可分五档。
  2. 最常被引用的那几个恰恰是最受限的。BNCI2014 系列是 CC BY-ND,其中三个子集禁止分发派生副本。
  3. 滤波、分段、特征化都算派生。派生物的再分发要回到原许可,不是回到加工者。
  4. 体量高度集中。六成体量在单个子集,而十五个轻量子集承载了约一半被试;按需取,不要整包拉。
  5. 引用到子集,不是到仓库。写清子集名、访问日期、加载器 commit,才能在许可与复现两个层面站得住。

编辑说明

本文的规模与结构数字取自数据卡与 Hugging Face 数据集 API,核查日期为二〇二六年十月二十六日。逐子集许可与授权方取自数据卡子集表的最后一列,未逐条回访上游页面,因此作为二手陈述引用时建议注明「数据卡称」。体量分布是从子集表逐行加总得到的相对比例,不是官方字段。

代码块全部以公开地址为入口,或使用本地相对路径;不含凭据占位符,也不依赖私有镜像。其中 #-- 开头的行为注释。

两处判断留给后续复核:一是被试年龄与性别的分布,数据卡未系统给出,本文未作估计;二是四个卒中子集的病程与病灶信息完整度,数据卡只标注了人群属性,未展开临床细节。这两项若补齐,会显著改变 §7.3 的结论强度。

许可判断属资料整理,不构成法律意见。涉及商用、对外发布派生数据、跨组织交付,请以授权方页面与专业法律意见为准。


相关数据集导航

以下为站内 AI-Ready 数据集百科中与本词条共享多个主题标签的相关数据集,按相关度降序排列:

  • moabb — 共享标签:生理信号 / 脑电信号 / 脑机接口 / 评测基准
  • auditory-eeg — 共享标签:生理信号 / 脑电信号 / 脑机接口
  • bigp3bci — 共享标签:生理信号 / 脑电信号 / 评测基准
  • oculusgraphy-erg — 共享标签:生理信号 / 脑电信号 / 评测基准
  • seed — 共享标签:生理信号 / 脑机接口
  • tuab — 共享标签:生理信号 / 脑电信号 / 评测基准
  • neurocritical-pediatric — 共享标签:生理信号 / 脑电信号 / 评测基准
  • eeg-power-anesthesia — 共享标签:生理信号 / 脑电信号 / 评测基准
  • ltrsvp — 共享标签:生理信号 / 脑电信号 / 评测基准
  • tusz — 共享标签:生理信号 / 脑电信号 / 评测基准

导航说明:本章节由全站统一标签体系自动计算生成(标签重合度算法),双向可达;点击链接可跳转至对应数据集词条。

返回 AI-Ready 数据集