信息速览
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:完整参考文献
- 数据卡与仓库:EEGDash. EEG motor imagery datasets [Data set]. Hugging Face. https://huggingface.co/datasets/EEGDash/eeg-mi-datasets
- MOABB 项目主页。https://moabb.neurotechx.com/
- 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
- 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
- Schalk, G. (2009). EEG Motor Movement/Imagery Dataset (version 1.0.0). PhysioNet. https://doi.org/10.13026/C28G6P
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- Creative Commons. Attribution-NoDerivatives 4.0 International. https://creativecommons.org/licenses/by-nd/4.0/
- Open Data Commons. ODC Attribution License (ODC-By) v1.0. https://opendatacommons.org/licenses/by/1-0/
- 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:如果只记五件事
- 这不是一个数据集,是三十二个。技术上在一个仓库里,法律上是三十二份资产,许可分五档。
- 最常被引用的那几个恰恰是最受限的。BNCI2014 系列是 CC BY-ND,其中三个子集禁止分发派生副本。
- 滤波、分段、特征化都算派生。派生物的再分发要回到原许可,不是回到加工者。
- 体量高度集中。六成体量在单个子集,而十五个轻量子集承载了约一半被试;按需取,不要整包拉。
- 引用到子集,不是到仓库。写清子集名、访问日期、加载器 commit,才能在许可与复现两个层面站得住。
编辑说明
本文的规模与结构数字取自数据卡与 Hugging Face 数据集 API,核查日期为二〇二六年十月二十六日。逐子集许可与授权方取自数据卡子集表的最后一列,未逐条回访上游页面,因此作为二手陈述引用时建议注明「数据卡称」。体量分布是从子集表逐行加总得到的相对比例,不是官方字段。
代码块全部以公开地址为入口,或使用本地相对路径;不含凭据占位符,也不依赖私有镜像。其中 #-- 开头的行为注释。
两处判断留给后续复核:一是被试年龄与性别的分布,数据卡未系统给出,本文未作估计;二是四个卒中子集的病程与病灶信息完整度,数据卡只标注了人群属性,未展开临床细节。这两项若补齐,会显著改变 §7.3 的结论强度。
许可判断属资料整理,不构成法律意见。涉及商用、对外发布派生数据、跨组织交付,请以授权方页面与专业法律意见为准。
相关数据集导航
以下为站内 AI-Ready 数据集百科中与本词条共享多个主题标签的相关数据集,按相关度降序排列:
- moabb — 共享标签:生理信号 / 脑电信号 / 脑机接口 / 评测基准
- auditory-eeg — 共享标签:生理信号 / 脑电信号 / 脑机接口
- bigp3bci — 共享标签:生理信号 / 脑电信号 / 评测基准
- oculusgraphy-erg — 共享标签:生理信号 / 脑电信号 / 评测基准
- seed — 共享标签:生理信号 / 脑机接口
- tuab — 共享标签:生理信号 / 脑电信号 / 评测基准
- neurocritical-pediatric — 共享标签:生理信号 / 脑电信号 / 评测基准
- eeg-power-anesthesia — 共享标签:生理信号 / 脑电信号 / 评测基准
- ltrsvp — 共享标签:生理信号 / 脑电信号 / 评测基准
- tusz — 共享标签:生理信号 / 脑电信号 / 评测基准
导航说明:本章节由全站统一标签体系自动计算生成(标签重合度算法),双向可达;点击链接可跳转至对应数据集词条。

