第2章 知识图谱构建技术基础:实体识别、关系抽取、属性填充

构建药物知识图谱,说白了就是要把散落在文献、说明书、临床报告里的信息,变成结构化的三元组。

这一章我们聊聊三个核心任务:实体识别、关系抽取、属性填充。我把它们称为知识图谱的「三把刀」。

2.1 实体识别:先找到「谁」和「什么」

实体识别,就是找出文本里的命名实体。比如药物名、疾病名、基因名、靶点名。

举个例子,给一句话:

阿托伐他汀能显著降低LDL-C水平,适用于高胆固醇血症患者。

实体识别要抓出「阿托伐他汀」(药物)、「LDL-C」(指标)、「高胆固醇血症」(疾病)。

我个人习惯把实体类型整理成一张清单,避免遗漏。我在一个项目中遇到过最头疼的问题——同一实体在不同文献里写法完全不一样。比如「吉非替尼」有人写「Gefitinib」,还有人写「ZD1839」。你想想看,不统一的话,图谱里会多出好几个重复节点。

小技巧:构建实体类型时,建议先列一个最小集,再按需扩展。我的经验是,最开始不要超过10种实体类型,否则标注成本会飞涨。

常用的实体识别方法,我分了三大类:

方法类型 代表工具/模型 适用场景
基于规则 正则、词典匹配 术语规范、实体类型少
基于统计 CRF、HMM 标注数据中等规模
基于深度学习 BiLSTM-CRF、BERT 大规模、上下文复杂

我个人偏好用深度学习做第一轮,再用规则做后处理。为什么呢?因为模型识别的边界经常不准,比如漏了「盐酸」前缀,这时候用正则一补,效果立竿见影。

避坑指南:实体识别的「漏报」比「误报」更难处理。我曾经在一个项目中漏掉了一批罕见病药物名,导致下游关系抽取直接断了链路。建议上线前做一次实体覆盖率测试。

2.2 关系抽取:把孤立的实体连起来

实体找到了,但它们之间有什么关系呢?关系抽取就是干这个的。

还是刚才那句话:

阿托伐他汀能显著降低LDL-C水平,适用于高胆固醇血症患者。

这里有两条关系:「阿托伐他汀 — 降低 — LDL-C」 和 「阿托伐他汀 — 适用于 — 高胆固醇血症」。

关系抽取的难点在于:关系的类别往往比实体多得多。我见过一个项目定义了200多种关系,最后模型根本训不动。我建议从「核心关系」入手,先覆盖80%的场景。

常用的关系抽取方法:

  • 流水线方法:先做NER,再对实体对做分类。简单,但误差会累积。
  • 联合抽取:用一个模型同时做实体和关系。效果更好,但实现复杂。

我个人更喜欢联合抽取的方式,尤其在大规模构建时。为什么呢?因为流水线方法里,NER漏掉的实体直接导致关系缺失,而联合模型能「互相拉一把」。

注意:关系类型要有明确的语义定义。我在一个项目中遇到过「治疗」和「缓解」混用的尴尬事。建议每一类关系都配一个示例文本,方便标注和审核。

2.3 属性填充:给实体加上「标签」

实体和关系构成了骨架,属性则负责填充血肉。

比如药物实体,它的属性可能包括:分子式、剂量范围、不良反应、半衰期……

属性填充一般有两种方式:

  • 结构化抽取:从数据库或表格中直接读取,数据干净。
  • 非结构化抽取:从文本里抓取,比如从「每次10mg,每日一次」里抽取出「剂量=10mg,频次=每日一次」。

我建议对属性做分级管理。比如「必填属性」和「可选属性」。先保证必填属性填充完整,再逐步丰富可选属性。否则很容易陷入「追求完美但永远填不完」的陷阱。

# 属性填充示例(JSON格式)
{
  "entity": "阿托伐他汀",
  "attributes": {
    "分子式": "C33H35FN2O5",
    "剂量": "10-80mg/日",
    "半衰期": "14小时",
    "不良反应": ["肌肉疼痛", "肝酶升高"]
  }
}
经验之谈:属性值的归一化很关键。比如「每日一次」和「一天一次」其实是一个意思。如果放任不管,图谱里会充满冗余信息。

2.4 本章整体流程

下面这张图展示了我个人偏好的构建流程:

知识图谱构建核心流程 原始文本 实体识别 关系抽取 属性填充 知识融合 知识图谱 包含:药物、疾病、基因 实体类型 + 同义词映射 如:治疗、抑制、激活 关系类型定义 + 置信度阈值

从原始文本出发,依次经过实体识别、关系抽取、属性填充,再做一遍知识融合——这一步很关键,能消除重复和冲突——最终形成一个可用的知识图谱。

2.5 总结一下

  • 实体识别:先找「谁」和「什么」,宁少勿多,但要定义清晰。
  • 关系抽取:把实体「连」起来,优先覆盖高频关系。
  • 属性填充:给实体加「标签」,做归一化,先保证必填字段。

这三个任务互相关联,任何一个环节出问题,下游都会受影响。嗯,这就是为什么一致性规则和质控那么重要——后面几章会慢慢展开。