简介SIGHAN中文纠错数据集及转换后格式.zip面向中文自然语言处理研究者与开发者聚焦汉语语法错误检测、拼写检查与拼音标注任务适合需要训练和评估中文纠错模型的中高级学习者。压缩包共78个文件约19.92MB以txt文本、sgml标注文件、zip子数据集、readme说明、jar工具、pdf论文、xlsx表格及py脚本为主兼顾原始语料、转换脚本与格式说明。资源涵盖SIGHAN原始版本及CLP14、SIGHAN7/8等历年CSC数据并附pair_data、simplified、traditional等目录便于按简繁与配对格式组织实验。转换流程涉及数据预处理、错误位置标注、训练验证测试集划分、CoNLL等格式转换及纠正标签创建读者可据此快速搭建纠错训练管线理解不同格式对模型效果与评估准确性的影响。目前已有378人学习下载适合作为中文纠错算法复现与语料建设的参考素材。1. 拿到 SIGHAN 中文纠错数据集先别急着解压这份 zip 里到底装了什么如果你正在做中文拼写检查CSC或者语法纠错GEC大概率绕不开 SIGHAN 这个名字。但很多人第一次拿到SIGHAN中文纠错数据集及转换后格式.zip时解压完看着一堆clp14csc_release1.1、sighan8csc_release1.0、pair_data、raw_data的目录直接懵了——哪个是原始语料哪个是能直接喂给模型的generate_pair_data.py又该怎么跑。这份资源解决的正是这个断层它把 SIGHAN 历年2013/2014/2015/2017/2018 等届的官方发布包和一份已经转好的平行句对格式放在一起省去你自己写解析脚本的功夫。适合两类人一是刚入门 CSC、想快速搭起训练/验证/测试流水线的同学二是已经跑过模型、但被原始 XML/文本格式折腾过的从业者可以直接拿pair_data做 baseline 对比。下面按「先看清结构 → 再动手转换 → 最后避坑」的顺序拆。2. 目录结构与数据来源raw_data、pair_data 和 file_io.py 各管什么2.1 原始发布包与转换后格式的对应关系先把 zip 解开用tree -L 2或资源管理器看一眼顶层。典型结构长这样不同打包版本略有出入但核心目录一致SIGHAN中文纠错数据集及转换后格式/ ├── sighan_raw-master/ # 原始语料与官方脚本 │ ├── raw_data/ # 各届原始发布包解压后的内容 │ │ ├── clp14csc_release1.1/ │ │ ├── sighan7csc_release1.0/ │ │ └── sighan8csc_release1.0/ │ ├── file_io.py # 读写原始格式的工具函数 │ ├── generate_pair_data.py # 生成平行句对的核心脚本 │ ├── ss.md # 说明文档 │ └── README.md ├── pair_data/ # 转换后的平行句对 │ ├── simplified/ # 简体 │ └── traditional/ # 繁体 └── clp14csc_release1.1.zip 等 # 原始压缩包备份raw_data里放的是官方发布包解压后的原始文件通常是「每行一个句子 错误位置标注」的文本或者带 XML 标签的结构。pair_data是转换后的成果simplified和traditional分别对应简繁两套每行一般是「错误句 \t 正确句」的平行格式可以直接被 seq2seq、BERT 类纠错模型读取。file_io.py负责解析原始格式generate_pair_data.py调用它批量生成平行句对。理解这条链路后面出问题才知道该查哪一环。2.2 各届数据集的特点与选型建议SIGHAN 各届的语料来源和标注粒度不一样选错版本会让你的实验结论没法跟别人对齐。常见几届的差异大致如下发布包主要来源简繁典型用途clp14csc_release1.1母语者写作 学习者语料简/繁2014 届 CSC 评测基准sighan7csc_release1.0新闻 网络文本简/繁2017 届规模较大sighan8csc_release1.0多来源混合简/繁2018 届含更多错误类型如果你要复现某篇论文的指标先确认它用的是哪一届、哪个 release 号再决定从raw_data里取哪份。做通用纠错、想要更大规模优先sighan8csc做简繁对比实验pair_data下的simplified和traditional直接可用。注意不同届的标注规范有细微差别混用训练集和测试集会导致指标虚高这是新手最容易翻车的地方。2.3 用 file_io.py 读懂原始格式在动手转换前先花十分钟读file_io.py它决定了原始文件怎么被解析。常见做法是里面会有类似read_lines、parse_sighan这样的函数把「错误位置 正确字」的标注还原成完整句子。你可以先跑一个小脚本打印前几条原始记录看看结构# 快速窥探原始格式路径按实际解压位置调整 import os raw_dir sighan_raw-master/raw_data/sighan8csc_release1.0 for root, dirs, files in os.walk(raw_dir): for f in files: if f.endswith((.txt, .sgml, .xml)): path os.path.join(root, f) print(, path) with open(path, encodingutf-8, errorsignore) as fp: for i, line in enumerate(fp): if i 3: break print(repr(line[:120])) break break这段代码只做一件事定位原始文件并打印前三行帮你判断它是纯文本还是带标签。参数上errorsignore是为了防止个别编码异常字符中断读取repr能把换行、制表符显式暴露出来方便你判断分隔符。看清格式后再决定是直接用generate_pair_data.py还是自己写解析逻辑。3. 生成平行句对generate_pair_data.py 的参数与执行流程3.1 转换脚本的核心逻辑generate_pair_data.py干的事可以概括为遍历raw_data下的原始文件 → 用file_io.py解析出「错误句」和「正确句」→ 按简繁分类 → 写出到pair_data/simplified和pair_data/traditional。它通常支持指定输入目录、输出目录、是否保留简繁、是否切分训练/验证/测试等参数。执行前先确认 Python 环境脚本一般只依赖标准库少数版本会用到tqdm之类做进度条。# 建议在虚拟环境里跑避免污染全局 python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install tqdm # 若脚本 import 了它 python generate_pair_data.py --help先看--help输出确认参数名。不同打包版本的参数命名可能不同别照搬网上的命令以你本地脚本为准。3.2 一次完整的转换执行假设脚本支持--input、--output、--lang三个参数典型调用如下# 生成简体平行句对 python generate_pair_data.py \ --input sighan_raw-master/raw_data \ --output pair_data/simplified \ --lang simplified # 生成繁体平行句对 python generate_pair_data.py \ --input sighan_raw-master/raw_data \ --output pair_data/traditional \ --lang traditional参数说明--input指向原始语料根目录脚本会递归扫描--output是写出目录不存在时一般会自动创建--lang控制简繁过滤因为部分原始文件同时含简繁需要按目标拆分。跑完后检查输出行数正常情况每行是「错误句 \t 正确句」用wc -l和head各看一眼wc -l pair_data/simplified/*.txt head -n 3 pair_data/simplified/*.txt如果行数为 0 或明显偏少多半是--input路径不对或者原始文件扩展名不在脚本的扫描白名单里回到file_io.py确认它认哪些后缀。3.3 划分训练/验证/测试集pair_data给的是全量平行句对真正训练前要自己切分。常见比例是 8:1:1注意同一来源的句子不要跨集合泄漏。下面这段脚本按行随机切分并落盘import random random.seed(42) # 固定种子保证可复现 src pair_data/simplified/all.txt lines open(src, encodingutf-8).read().splitlines() random.shuffle(lines) n len(lines) train, dev, test lines[:int(n*0.8)], lines[int(n*0.8):int(n*0.9)], lines[int(n*0.9):] for name, data in [(train, train), (dev, dev), (test, test)]: with open(fpair_data/simplified/{name}.txt, w, encodingutf-8) as fp: fp.write(\n.join(data)) print(name, len(data))random.seed(42)是后悔药保证每次切分结果一致方便复现实验。切分后建议统计一下错误类型分布如果某一类错误只出现在测试集指标会失真。这一步没有标准答案但「先看分布再定切分」是稳妥习惯。4. 避坑与常见问题排查编码、简繁混用和标注错位4.1 现象读文件报 UnicodeDecodeError原因原始语料里混有 GBK/GB18030 编码的旧文件直接用 UTF-8 打开会崩。解决读取时显式指定编码或加errorsignore先跑通再回头定位问题文件。稳妥做法是用chardet探测import chardet raw open(some_file.txt, rb).read(10000) print(chardet.detect(raw))拿到编码后再用对应编码打开别一上来就errorsignore那会静默丢字导致平行句对错位。4.2 现象pair_data 里简繁混杂原因部分原始文件本身同时含简繁--lang过滤不彻底或脚本按字符集判断时把边界字判错。解决转换后做一次简繁检测把明显不属于目标语言的句子剔掉。常见做法是用opencc做转换对比或维护一个高频简繁差异字表做粗筛。别指望一次转换就干净人工抽检 200 行是必要的。4.3 现象错误句和正确句长度对不上原因原始标注里有多字替换、增删解析时如果只按「单字替换」处理会把长错误截断。解决回到file_io.py看它怎么处理多字 span必要时自己扩展解析逻辑。平行句对长度差超过阈值比如 5 个字符的样本建议单独存疑别直接进训练集。4.4 现象训练指标高得离谱原因训练集和测试集来自同一批原始文件句子级泄漏。解决切分前先按来源文件分组同一文件的句子只进一个集合。这个坑很隐蔽指标虚高十几个点都可能血泪经验是切分脚本里加一句来源标记。4.5 现象脚本跑完没报错但输出为空原因--input指向了压缩包而不是解压后的目录或脚本扫描的后缀与实际文件不符。解决先ls确认目录里有文件再对照file_io.py里的后缀白名单。别忽略README.md和ss.md里面往往写了作者预期的调用方式。5. 进阶用法把 pair_data 接进纠错模型并做基线验证拿到干净的平行句对后下一步是验证它能不能真的训出东西。最省事的做法是先跑一个字符级 seq2seq 或直接用pycorrector这类现成工具做零样本测试确认数据格式没问题再上大模型。下面给一个最小验证脚本用编辑距离粗算「错误句→正确句」的改动量帮你判断数据难度import Levenshtein # pip install python-Levenshtein def stat(path): total, changed 0, 0 for line in open(path, encodingutf-8): parts line.rstrip(\n).split(\t) if len(parts) ! 2: continue src, tgt parts total 1 if src ! tgt: changed 1 print(f{path}: {total} 行, 需纠错 {changed} 行, 占比 {changed/total:.2%}) stat(pair_data/simplified/test.txt)如果「需纠错占比」接近 100%说明这份平行数据是「每句都含错」的评测风格如果只有一部分说明混入了正确句训练时要留意损失计算。这个统计能帮你快速判断数据是否符合预期比盲目开训省时间。再进一步可以把pair_data转成模型需要的格式。以 BERT 类纠错模型为例常见输入是「错误句」、标签是「每个位置是否错误 正确字」这时需要把平行句对做字符级对齐。对齐可以用difflib.SequenceMatcherimport difflib def align(src, tgt): sm difflib.SequenceMatcher(None, src, tgt) labels [K] * len(src) # Kkeep for tag, i1, i2, j1, j2 in sm.get_opcodes(): if tag replace: for i in range(i1, i2): labels[i] tgt[j1] if i2 - i1 j2 - j1 else R elif tag delete: for i in range(i1, i2): labels[i] D return labels print(align(我今天去学校, 我今天去学院))get_opcodes返回的replace/delete/insert对应替换、删除、插入labels里K表示保留、具体字符表示替换目标、D表示删除。注意等长替换和不等长替换要分开处理否则标签会错位。这套对齐逻辑是很多 CSC 模型数据预处理的核心跑通它pair_data才算真正能用。从那以后我每次拿到新的纠错数据集都强制先跑一遍「行数统计 简繁抽检 长度分布 对齐测试」四件套确认无误再开训省下的返工时间远超这十分钟。希望帮到你。本文还有配套的精品资源点击获取