☰
DeepKE 远程监督关系标注工具实战:用 ds_label_data.py 自动生成关系抽取训练数据
2026/10/6 2:02:37 网站建设 项目流程
  • 人工智能
  • NLP
  • 知识图谱
  • 深度学习

【免费下载链接】DeepKE

[EMNLP 2022] An Open Toolkit for Knowledge Graph Extraction and Construction

项目地址:https://gitcode.com/gh_mirrors/de/DeepKE
点击查看免费下载

远程监督(Distant Supervision)是关系抽取(Relation Extraction, RE)领域最实用的自动标注手段之一:不需要人工逐条标注,只要有一份高质量知识库三元组,就能把"句子 + 实体对"批量打上关系标签。本文讲解 DeepKE 在example/re/prepare-data目录下提供的基于远程监督的关系标注工具ds_label_data.py,涵盖源文件与三元组文件的格式要求、标注匹配原理、输出文件结构、全部命令行参数及与下游 DeepKE 标准 RE 训练流程的衔接方式。读完本文,你将能够把任意一份"只含实体对、没有关系标签"的语料自动转化为 DeepKE 可直接使用的标注数据集。

工具定位:DeepKE 数据准备链条的第一环

DeepKE 官方将关系抽取的数据准备分成两条路径:

  • 数据本身已经带关系标签:直接按json/xlsx/csv三种格式整理成训练集、验证集、测试集即可(参见 example/re/standard/data/README.md 与 example/re/standard/README.md);
  • 数据只有句子与实体对、缺少关系标签:使用本工具基于远程监督自动打标。

官方文档对它的定位非常明确:"We provide a simpledistant supervisedbased tool to label relation labels for our RE tasks"——它是一个面向 DeepKE RE 任务的、简单易用的远程监督关系标注工具,入口脚本为 example/re/prepare-data/ds_label_data.py。

远程监督的核心假设是:如果知识库中存在三元组(head, relation, tail),那么任何同时包含head与tail两个实体的句子,都可以被标注为该关系。本工具正是这一思想的极简实现——实体对与三元组做字符串全匹配,命中即打上关系标签,未命中则标记为None。

源文件格式:每条数据一个实体对

待标注的源文件必须为.json格式,且每条数据只包含一个实体对(头实体head与尾实体tail各一个)。每条数据至少包含以下五个字段:

字段含义
sentence包含实体对的完整句子
head头实体文本
tail尾实体文本
head_offset头实体在句子中的偏移位置
tail_offset尾实体在句子中的偏移位置

完整的 JSON 结构如下(英文示例):

[ { "sentence": "This summer, the United States Embassy in Beirut, Lebanon, once again made its presence felt on the cultural scene by sponsoring a photo exhibition, an experimental jazz performance, a classical music concert and a visit from the Whiffenpoofs, Yale University's a cappella singers.", "head": "Lebanon", "tail": "Beirut", "head_offset": "50", "tail_offset": "42" } ]

中文示例(源自 example/re/prepare-data/README_CN.md):

[ { "sentence": "如何演好自己的角色,请读《演员自我修养》《喜剧之王》周星驰崛起于穷困潦倒之中的独门秘笈", "head": "周星驰", "tail": "喜剧之王", "head_offset": "26", "tail_offset": "21" } ]

这里有一个容易忽略的细节:源文件中head_offset/tail_offset均为字符串形式,且该工具在标注阶段并不使用这两个偏移字段——它们的作用是为下游 DeepKE 模型保留实体的位置信息。从 ds_label_data.py 的源码可以看到,标注时只读入了sentence、head、tail三个字段,偏移字段随原样透传到输出文件,供后续预处理阶段构造位置向量使用。

三元组文件:标注的"知识库词典"

源文件中的实体对将与三元组文件中的三元组做匹配:匹配成功,实体对被标注为对应关系;没有匹配项,则标注为None。三元组文件有内置词典和自定义两种来源。

内置英文词典(NYT 数据集)

官方提供了一个英文三元组文件,来源于NYT数据集,包含 25 种关系类型:

"/business/company/place_founded", "/people/person/place_lived", "/location/country/administrative_divisions", "/business/company/major_shareholders", "/sports/sports_team_location/teams", "/people/person/religion", "/people/person/place_of_birth", "/people/person/nationality", "/location/country/capital", "/business/company/advisors", "/people/deceased_person/place_of_death", "/business/company/founders", "/location/location/contains", "/people/person/ethnicity", "/business/company_shareholder/major_shareholder_of", "/people/ethnicity/geographic_distribution", "/people/person/profession", "/business/person/company", "/people/person/children", "/location/administrative_division/country", "/people/ethnicity/people", "/sports/sports_team/location", "/location/neighborhood/neighborhood_of", "/business/company/industry"

内置中文词典

中文三元组文件包含 50 种常见关系类型,每条以 JSON 形式给出主语类型、谓词与宾语类型:

{"object_type": "地点", "predicate": "祖籍", "subject_type": "人物"} {"object_type": "人物", "predicate": "父亲", "subject_type": "人物"} {"object_type": "地点", "predicate": "总部地点", "subject_type": "企业"} {"object_type": "地点", "predicate": "出生地", "subject_type": "人物"} {"object_type": "人物", "predicate": "妻子", "subject_type": "人物"} {"object_type": "人物", "predicate": "导演", "subject_type": "影视作品"} {"object_type": "人物", "predicate": "母亲", "subject_type": "人物"} {"object_type": "人物", "predicate": "编剧", "subject_type": "影视作品"} {"object_type": "国家", "predicate": "国籍", "subject_type": "人物"} {"object_type": "人物", "predicate": "丈夫", "subject_type": "人物"} {"object_type": "人物", "predicate": "主持人", "subject_type": "电视综艺"} {"object_type": "人物", "predicate": "歌手", "subject_type": "歌曲"} {"object_type": "人物", "predicate": "作词", "subject_type": "歌曲"} {"object_type": "人物", "predicate": "主角", "subject_type": "网络小说"} {"object_type": "人物", "predicate": "董事长", "subject_type": "企业"} {"object_type": "学校", "predicate": "毕业院校", "subject_type": "人物"} {"object_type": "人物", "predicate": "作者", "subject_type": "图书作品"} {"object_type": "人物", "predicate": "作曲", "subject_type": "歌曲"} {"object_type": "人物", "predicate": "嘉宾", "subject_type": "电视综艺"} {"object_type": "人物", "predicate": "主演", "subject_type": "影视作品"} {"object_type": "作品", "predicate": "改编自", "subject_type": "影视作品"} {"object_type": "人物", "predicate": "创始人", "subject_type": "企业"} {"object_type": "地点", "predicate": "总部地点", "subject_type": "企业"} {"object_type": "地点", "predicate": "出生地", "subject_type": "人物"} {"object_type": "企业", "predicate": "出品公司", "subject_type": "影视作品"} {"object_type": "人物", "predicate": "制片人", "subject_type": "影视作品"} {"object_type": "出版社", "predicate": "出版社", "subject_type": "书籍"} {"object_type": "音乐专辑", "predicate": "所属专辑", "subject_type": "歌曲"} {"object_type": "城市", "predicate": "首都", "subject_type": "国家"} {"object_type": "城市", "predicate": "所在城市", "subject_type": "景点"} {"object_type": "语言", "predicate": "官方语言", "subject_type": "国家"} {"object_type": "Date", "predicate": "上映时间", "subject_type": "影视作品"} {"object_type": "Date", "predicate": "出生日期", "subject_type": "人物"} {"object_type": "Date", "predicate": "成立日期", "subject_type": "机构"} {"object_type": "Date", "predicate": "成立日期", "subject_type": "企业"} {"object_type": "Number", "predicate": "面积", "subject_type": "行政区"} {"object_type": "Number", "predicate": "注册资本", "subject_type": "企业"} {"object_type": "Number", "predicate": "身高", "subject_type": "人物"} {"object_type": "Number", "predicate": "修业年限", "subject_type": "学科专业"} {"object_type": "Number", "predicate": "海拔", "subject_type": "地点"} {"object_type": "Number", "predicate": "人口数量", "subject_type": "行政区"} {"object_type": "Number", "predicate": "占地面积", "subject_type": "机构"} {"object_type": "Text", "predicate": "简称", "subject_type": "机构"} {"object_type": "Text", "predicate": "字", "subject_type": "历史人物"} {"object_type": "Text", "predicate": "朝代", "subject_type": "历史人物"} {"object_type": "Text", "predicate": "民族", "subject_type": "人物"} {"object_type": "Text", "predicate": "号", "subject_type": "历史人物"} {"object_type": "Text", "predicate": "专业代码", "subject_type": "学科专业"} {"object_type": "Text", "predicate": "邮政编码", "subject_type": "行政区"} {"object_type": "目", "predicate": "目", "subject_type": "生物"} {"object_type": "气候", "predicate": "气候", "subject_type": "行政区"} {"object_type": "网站", "predicate": "连载网站", "subject_type": "网络小说"}

自定义三元组文件(CSV 格式)

官方也允许用户提供自定义三元组文件,但格式必须是.csv,并包含表头head, tail, rel三列:

headtailrel
LebanonBeirut/location/location/contains
.........

从源码实现看,CSV 的读取方式决定了表头的必要性:ds_label_data.py 第 20-21 行使用csv.reader读取文件后,通过list(dic)[1:]显式跳过第一行(表头)。也就是说,表头行不会被当作实体参与匹配,自定义 CSV 时务必保留表头。此外,读取时指定了encoding='utf-8',因此无论是英文还是中文三元组文件,都应以 UTF-8 编码保存。

标注匹配原理(源码级解读)

整个标注逻辑在 ds_label_data.py 中非常简洁,核心流程如下:

  1. 读取三元组词典:用csv.reader读取三元组文件,去掉表头后得到形如[head, tail, rel]的行列表;
  2. 读取源文件:用json.load载入待标注的 JSON 数组;
  3. 逐条匹配:对每条源数据取出sentence、head、tail,然后遍历三元组列表,判断是否存在h == head and t == tail的字符串全匹配;
  4. 大小写归一化:当language == 'en'时,匹配前会把源文件的head、tail以及三元组的h、t全部转为小写(head.lower()),以消除英文大小写差异带来的误匹配;中文(cn)则不做小写化;
  5. 关系赋值:命中即取triple[2]作为relation并break跳出;遍历完仍未命中则标记data['relation'] = 'None';
  6. 进度显示:使用tqdm打印标注进度,方便监控大规模数据集的标注过程。

需要特别注意两点:

  • 匹配是严格字符串全等,而非子串或模糊匹配,因此head/tail的写法必须与三元组文件中完全一致(英文不区分大小写,中文必须逐字一致);
  • 遍历三元组时取第一条命中即终止,若同一实体对在知识库中对应多个关系,只会保留顺序最靠前的那一个标签,这在构建"单标签"分类训练数据时是合理的默认行为。

输出文件与数据集划分

工具会自动生成三个输出文件,分别对应训练集、验证集和测试集:

文件名对应数据集
labeled_train.json训练集
labeled_dev.json验证集
labeled_test.json测试集

输出文件在源文件字段基础上增加了relation字段,示例:

[ { "sentence": "This summer, the United States Embassy in Beirut, Lebanon, once again made its presence felt on the cultural scene by sponsoring a photo exhibition, an experimental jazz performance, a classical music concert and a visit from the Whiffenpoofs, Yale University's a cappella singers.", "head": "Lebanon", "tail": "Beirut", "head_offset": "50", "tail_offset": "42", "relation": "/location/location/contains" } ]

中文对应示例中relation被标注为"主演"等中文谓词(见 example/re/prepare-data/README_CN.md)。

数据集划分比例默认为0.8 : 0.1 : 0.1,且可自定义。从源码看划分逻辑为:先取前int(total * train_rate)条作为训练集,再取其后int(total * dev_rate)条作为验证集,最后取末尾int(total * test_rate)条作为测试集(train_data = labeled_data[:train_len]、dev_data = labeled_data[train_len:train_len + dev_len]、test_data = labeled_data[-test_len:])。这意味着划分依赖源文件的排列顺序——若希望训练/验证/测试分布更均匀,建议在生成源文件时先将数据随机打乱。另外源码在划分前有一个断言assert args.train_rate + args.dev_rate + args.test_rate == 1.0,三个比例之和必须严格等于 1,否则程序直接报错退出。

命令行参数详解

官方文档给出了五个参数,其中前三个是必用的文件/语言参数,后三个是划分比例参数(注意文档原文将第一个误写为test_rate,源码 ds_label_data.py 中实际参数名为train_rate,本文以源码为准):

参数类型默认值说明
--languagestren数据语言,可选en(英文)或cn(中文);决定是否做小写化归一
--source_filestrsource_data.json待标注的源文件(JSON 格式,UTF-8)
--triple_filestrtriple_file.csv三元组文件(CSV 格式,含表头)
--train_ratefloat0.8训练集占比
--dev_ratefloat0.1验证集占比
--test_ratefloat0.1测试集占比

train_rate + dev_rate + test_rate必须等于 1。三个输出文件生成在当前工作目录下,文件名固定为labeled_train.json、labeled_dev.json、labeled_test.json。

运行示例

在example/re/prepare-data目录下,准备好源文件与三元组文件后直接运行:

python ds_label_data.py --language en --source_file source_data.json --triple_file triple_file.csv

中文数据只需切换--language cn:

python ds_label_data.py --language cn --source_file source_data_cn.json --triple_file triple_file_cn.csv

自定义划分比例示例(6:2:2):

python ds_label_data.py --language en --source_file source_data.json --triple_file triple_file.csv --train_rate 0.6 --dev_rate 0.2 --test_rate 0.2

源码中源文件与三元组文件的路径均基于当前工作目录拼接(os.path.join(os.getcwd(), args.triple_file)),因此建议把source_data.json与triple_file.csv放在与脚本相同的目录下运行,避免路径解析问题。

与下游 DeepKE 标准 RE 流程的衔接

标注产出的 JSON 文件并不能直接送入模型,还需要一步格式转换,因为 DeepKE 标准 RE 训练流程读取的是csv格式。具体衔接如下:

  1. 格式转换:DeepKE 官方提供了 src/deepke/transform_data.py,其中的json2csv/xlsx2csv函数可将 JSON 标注结果转换为标准 CSV。转换后 CSV 的表头格式为sentence,relation,head,head_offset,tail,tail_offset,可参考 example/re/standard/data/example.csv 中的示例数据;
  2. 补齐关系标签表:标准流程还需要一份relation.csv,为每个关系分配index、head_type、tail_type。从 src/deepke/relation_extraction/standard/tools/preprocess.py 的_handle_relation_data函数可以看到,每个关系被组织为{'index': ..., 'head_type': ..., 'tail_type': ...}三个属性,预处理时会通过_add_relation_data为每条样本写入rel2idx与头尾实体类型;
  3. 训练数据组织:将转换后的 CSV 按data/origin目录组织为train.csv、valid.csv、test.csv和relation.csv,预处理参数(如是否分词chinese_split、是否用实体类型替换实体replace_entity_with_type、位置限制pos_limit等)见 example/re/standard/conf/preprocess.yaml;
  4. 训练:在example/re/standard下执行python run.py即可开始训练,具体流程见 example/re/standard/README.md。

从源码看,预处理阶段 preprocess.py 还会做一步"数据清洗"(_clean_data):剔除head或tail未出现在sentence中的样本。也就是说,即使远程监督工具把实体对标注上了关系,只要实体不在句子中,下游预处理也会自动丢弃该样本——这提醒我们在构造源文件时应保证实体文本确实出现在句子内。

使用建议与注意事项

综合官方文档(README.md 与 README_CN.md)与源码实现,使用该工具时有几点值得留意:

  • 词典质量决定标注质量:远程监督的标签质量高度依赖三元组文件。官方建议优先使用官方提供的 NYT 英文三元组与 ExtractTriples 中文三元组,或使用高质量的自定义三元组,同时准备足够多的源数据(官方 README 在"Data Labeling"一节中特别强调了这两点);
  • 匹配是硬匹配:实体对与三元组必须字符串全等(英文忽略大小写),这会导致大量实体对匹配失败而落入None类,属远程监督的正常现象;
  • 单关系语义:每条数据只允许一个实体对、且只保留首个命中关系,适合构建单标签分类数据;若需要多标签或多实体对,需自行扩展;
  • 划分顺序敏感:训练/验证/测试按源文件顺序切分,建议预先打乱源数据;
  • UTF-8 编码:源文件与三元组文件读取均指定 UTF-8,其他编码会引发异常;
  • 多关系类型注意类别不平衡:None占比通常较高,训练时可结合 example/re/standard 的模型与配置自行处理类别权重问题。

这套"源文件 + 三元组词典 + 全匹配标注 + 自动切分"的极简流程,正是 DeepKE 帮助用户在缺乏标注数据时快速启动 RE 任务的实用方案,从 example/re/prepare-data/ds_label_data.py 到下游 example/re/standard 的完整链路,构成了 DeepKE 关系抽取模块数据侧的最小闭环。

  • 人工智能
  • NLP
  • 知识图谱
  • 深度学习

【免费下载链接】DeepKE

[EMNLP 2022] An Open Toolkit for Knowledge Graph Extraction and Construction

项目地址:https://gitcode.com/gh_mirrors/de/DeepKE
点击查看免费下载

相关推荐

上一篇:解锁GoSpider终极爬取能力:利用第三方源扩展数据采集范围的完整指南
下一篇:Babylon.js Tree-Shaking 维护脚本全指南:纯导入面、副作用清单与打包体积校验

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询