前言
开发该课题也有一个月了,整个过程并不是很顺利,很多细节部分如果没有得到及时梳理,对以后的研究和论文写作也有坏处。基于以上和其他原因,遂决定分阶段进行记录。
数据集
深度学习项目的良好开端就是有一个优良标注的数据集。而由于本课题起源于一个极小领域下,导致数据集必须完全自建。所有工作由我一人进行,工作量不可避免的大。所以必须尽可能的减少工作量,尽量实现在课题的中后期的所有标注工作都由程序自动化解决。
计组数据集的构建分为了以下几个过程:
- 计组数据集来源
- 数据预处理
- 数据集的预标注
- 基于词典的多次迭代标注
- 数据集格式的转换
接下来对每一个部分进行详述。
计组数据集来源
目前数据的来源如下:
- 计算机组成原理第6版 (白中英),pdf 转 txt
- 计算机组成原理第6版 (白中英) 课件,ppt 转 txt
数据预处理
以下是大概的预处理过程:
- 将所有的文本合并到一个文件,方便后续操作;
- 手工去掉一些与课题无关的文本和小部分错误内容;
- 去掉所有的空白字符(空格、换行符、制表符等);
- 去掉所有的特殊字符(数字、半角符号、特殊字符);
- 以中文句号进行分割,分别以整句、分词的形式输出到 json 文件中。
处理结果:
1 2 3 4
// 分词 { "0": ["\u8ba1", "\u7b97", "\u673a", "\u7cfb", "\u7edf", "\u4e0d", "\u540c", "\u4e8e", "\u4e00", "\u822c", "\u7684", "\u7535", "\u5b50", "\u8bbe", "\u5907", "\uff0c", "\u5b83", "\u662f", "\u4e00", "\u4e2a", "\u7531", "\u786c", "\u4ef6", "\u3001", "\u8f6f", "\u4ef6", "\u7ec4", "\u6210", "\u7684", "\u590d", "\u6742", "\u7684", "\u81ea", "\u52a8", "\u5316", "\u8bbe", "\u5907"] }
数据集的预标注
以上所有数据处理完后,共得到5632条文本。如果要自己一条条的标注,真就是整一个月啥也别干,所以还是要用比较省力的方式进行标注。我选择用一个在中文语料集上训练过的预训练模型进行第一轮标注,也就是预标注。
我选择了 RaNER命名实体识别-中文-通用领域-large 作为预标注阶段的预训练模型。该模型的标签如下:
实体类型 | 英文名 |
---|---|
公司名 | CORP |
创作名 | CW |
其他组织名 | GRP |
地名 | LOC |
人名 | PER |
消费品 | PROD |
为什么要选择这个模型呢?我当时认为有以下几点可以考虑:
- 标签覆盖范围广:其他的预训练模型只对 PER、LOC、ORG 这三种基本实体有所覆盖,如 CPU、内存这类实体反而识别不出来。相比以上,该模型能成功将计组教材中的大部分实体识别出来,并赋予 PROD、CW、GRP、CORP、PER等标签;
- 中文平台 ModelScope:因为 ModelScope 在国内,所以各种工具使用起来相对方便。
整个预标注过程如下:
- 读取以整句进行分割的语料集;
- 构建 Pytorch 的 Dataset 、DataLoader ,方便后续分批加载数据;
- 创建 ModelScope 的 Pipeline ;
- 将数据顺序输入到 Pipeline 中,由模型进行推理;
- 将结果输出到 txt 文件中。
可以从上面的结果中看到,计算机系统这个实体被识别了出来,并被标注为 PROD 消费品。但是硬件、软件这两个概念实体没有识别出来,说明预标注的结果只能在一定程度上减少工作量,其余的大部分工作仍需要更高精度的校对。
(标注的结果分析:在所有数据集都处理完成之后才能进行这一步)
基于词典的多次迭代标注
预标注的准确率极为有限,出现了大量识别错漏的情况。这伴随而来的是超大工作量,想要在短时间内修复绝大部分错误几乎是不可能的。那有没有什么方法可以半自动,甚至在之后可以全自动的解决这些问题呢?我想到的是基于词典的多次迭代标注方法。
为了能快速准确的校对大量数据,引入了词典。所谓词典就是 Python 的字典数据结构,由大量键值对组成。为了方便进行迭代标注,我做了以下三个工作:
分割数据集:数据集以训练集 : 验证集 : 测试集 = 8 : 1 : 1 的比例进行划分,而训练集又分成了 5 份;
细分标签:
- 将计组实体分为了以下十一类:
Label Meaning Use COMP 组件 用于标注计算机系统的具体组件,如“寄存器”、“总线”、“控制单元”等 DATA 数据 用于标注数据类型和格式,如“二进制数据”、“十六进制数据”等 ARCH 架构 用于标注计算机体系结构相关的实体,如冯·诺依曼架构、RISC等 PROG 程序与软件 用于标注具体的程序或软件,如“操作系统”、“编译器”等 PROT 网络协议 用于标注网络协议或通信协议,如“TCP/IP”、“HTTP”等 PERF 性能指标 用于标注与计算机性能相关的实体,如处理速度、吞吐量、延迟、响应时间等 STOR 存储器 用于标注各种存储类型和技术,如“RAM”、“ROM”、“闪存”等 ALG 算法 用于标注算法相关的实体,如排序算法、加密算法 IO IO设备 用于标注与输入输出设备相关的实体,如键盘、鼠标、显示器、打印机等 TECH 技术 用于标注计算机科学技术和概念,如“虚拟内存”、“流水线”、“缓存”等 INST 指令 用于标注具体的指令或指令集,如“ADD指令”、“MIPS指令集”等
- 将计组实体分为了以下十一类:
最长匹配原则:
- 以“页式虚拟存储系统中,虚地址空间被分成等长的页,称为逻辑页”为例;
- 地址空间、虚地址空间都被标记为 DATA 实体。在这里标记地址空间为 DATA 不完整的,而遵循最长匹配原则,虚地址空间被标记为 DATA 。
以上部分完成后,才正式开始迭代标注,以下是一个大致过程:
- 以第一份数据集的校对结果构建初始词典;
- 在其他份数据集校对前先用词典进行一次快速校对;
- 每次人工校对完一份数据集,就以其标注结果更新词典;
- 重复 1~3 ,直到基于完整数据集的词典更新完毕,得到最终版本词典。
值得一提的是,第一份训练集、验证集、测试集都参与了初始词典的构建,主要采用人工校对。标注平台选用开源库 Open Source Data Labeling | Label Studio 在本地进行标注。
最终版本的词典精确率和召回率都很高,明显高于没有微调的预训练模型。之后还有什么文本,直接用以上方法进行一次快速标注。
数据集格式的转换
模型训练的数据格式有两种:
json-tag
1
{"words": ["痛", "1", "天", "。"], "ner": ["B-SIGNS", "O", "O", "O"]}
conll
把标注过的数据转换为以上格式,就得到用于训练的标准数据集了。