想象你推开一间医院档案室的门:成排的病历夹里,是医生们龙飞凤舞的字迹——“阿司匹林 100mg 每日一次”、“皮疹原因待查”、“发热伴咳嗽 3 天”。这些文字不是孤立的词句,而是一张张隐藏的关系网:药物配着剂量、药物引出不良反应、疾病牵着症状。医学关系抽取,就是派一位“病历侦探”走进这座档案室,从杂乱无章的临床文本中找出“谁对谁做了什么”,把天书翻译成机器能读的结构化事实。这篇文章会带你认识这位侦探的办案工具:先看清临床文本的“黑话”,再用远程监督批量获取线索,用实体对建模拼出证据画像,用多标签分类列出全部罪名,用注意力机制过滤伪证,最后用精确率与召回率考核破案质量。读完你就能理解,医院的智能用药审核和药物警戒系统,是如何从病历中自动挖出金子的。

岗位关联

掌握医学关系抽取,等于掌握把海量临床文本升级为结构化医疗知识的核心技术——这是构建医疗知识图谱、智能用药审核与药物警戒系统的关键一环,也是最稀缺的医疗 AI 工程能力之一。

目录
  1. 可视化演示
  2. 任务定义:病历里的“案件三要素”
  3. 临床文本挑战:解读医生的“黑话”
  4. 远程监督:半真半假的“线人笔记”
  5. 实体对建模:拼出完整的“证据画像”
  6. 多标签分类:一个案件背多个“罪名”
  7. 噪声处理:用注意力甄别“伪证”
  8. 评测指标:给侦探的“结案率”打分
  9. 应用价值:从侦探笔记到“医疗天网”
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

展示从临床文本中抽取药物-剂量、药物-不良反应、疾病-症状关系的过程,包括实体识别、关系分类与噪声处理,交互切换查看不同关系类型抽取效果。

本节配有交互动效(进入视口后自动加载,约 3KB)。

医学关系抽取流程 实体识别:NER模型识别药物、疾病、症状等医学实体 关系分类:对实体对进行多标签分类确定关系类型 Triple = (Entity1, Relation, Entity2) 从临床文本中抽取结构化医学知识三元组,支持药物安全监控与临床决策

任务定义:病历里的“案件三要素”

小林的第一个案子是一份普通病历:“阿司匹林 100mg 每日一次,患者随后出现轻度皮疹。”主任说:“别只读文字,要读出链条——什么药、什么量、造成了什么。”小林恍然大悟:任何一条临床记录,都可以拆成“谁—对谁—做了什么”的破案三要素。这正是关系抽取的直觉起点:文本不是孤立的词,而是一个个等待还原的事实现场。

在自然语言处理里,这个“破案三要素”叫关系三元组。医学关系抽取的任务,就是从自由文本中自动找出头实体 h、尾实体 t,以及它们之间的语义关系 r,最终输出结构化三元组 (h, r, t)。比如上面那句,就藏着“阿司匹林—药物·剂量—100mg”和“阿司匹林—药物·不良反应—皮疹”两组事实。同一个实体可以同时扮演多个“角色”,这正是医学文本复杂性的源头。

这些事实来自多种临床文本:出院小结、门诊记录、检验报告、护理记录,它们统称电子病历(EHR)。我们关注的三类关系各有各的形态:药物-剂量是“药+用量”的组合,药物-不良反应是“药+副作用”的因果,疾病-症状是“病+表现”的关联。模型学会这三类,就能把非结构化病历转写成机器可查的结构化知识,支撑起后续的知识图谱与临床决策系统。

小林在笔记本上写下:“所谓关系抽取,就是给病历里的每个‘动作’验明正身。”他合上档案,望向第二摞病历——那上面全是医生天书般的缩写。

f(h,t,S)→r∈Rf(h, t, S) \to r \in \mathcal{R}
关系抽取被看作一个映射函数:给定句子集合与实体对,输出一个关系标签。R 是所有候选关系的集合,例如 {药物-剂量,药物-不良反应,疾病-症状}。
  1. 函数视角关系抽取是一个从“句子+实体对”到“关系标签”的映射,模型要做的是学习这个映射。
    f(h,t,S)→rf(h, t, S) \to r
  2. 实体要素h 是头实体(如药物阿司匹林),t 是尾实体(如剂量 100mg、不良反应皮疹)。
    (h,t)⊂S(h, t) \subset S
  3. 关系集合R 是预定义的关系类型全集,模型只能从 R 中选择答案,不能发明新关系。
    R={r1,r2,r3,⋯ }\mathcal{R} = \{ r_1, r_2, r_3, \cdots \}

临床文本挑战:解读医生的“黑话”

档案室第二摞病历让小林的眉头拧成麻花:“pt c/o N/V, T 38.5℃”——患者主诉恶心呕吐、体温 38.5℃。还有 “q8h”(每 8 小时一次)、“PO”(口服)这类用药黑话。侦探的第一课,是读懂案发现场独特的“方言”。如果连文字都认不全,后面的破案步骤就是空中楼阁。

临床文本与新闻、评论最大的不同在于极不规范:句子常常不完整,术语缩写密集,同一概念有多种写法(“心肌梗死”和“MI”、“发热”和“fever”),甚至出现拼写错误。这给关系抽取的预处理阶段带来巨大压力。更棘手的是“一词多义”:缩写 “MI” 可能是心肌梗死,也可能是二尖瓣关闭不全,必须依靠上下文消歧。

要让模型处理这些文本,第一步是把句子切成 token(词元)序列,再把每个 token 映射成稠密向量(词嵌入)。于是句子 S 就变成一串向量矩阵,作为后续实体对建模的输入。碰到 “MI” 这种缩写,模型需要看它附近是 “chest pain” 还是 “valve”,才能做出正确判断。这一步是把“黑话”翻译成机器能运算的数字语言。

小林把“黑话”翻译成了机器能读的向量。但光有句子还不够,他需要一张“线索地图”——哪里有嫌疑药物,哪里有受害症状。地图从哪来?主任递过来一本《医学事实大全》。

S=[ew1,ew2,⋯ ,ewn]\mathbf{S} = [ \mathbf{e}_{w_1}, \mathbf{e}_{w_2}, \cdots, \mathbf{e}_{w_n} ]
句子不再是字符串,而是一列词向量组成的矩阵,每个向量代表一个 token 的语义,后续所有模型操作都基于这个矩阵展开。
  1. 切分 token句子先被切成最小的语义单元 w₁ 到 wₙ,英文按空格和标点切,中文按词或字切。
    S=[w1,w2,⋯ ,wn]S = [w_1, w_2, \cdots, w_n]
  2. 查表嵌入每个 token 在预训练词表中查到对应的稠密向量 e,语义相近的词向量距离近。
    ewi∈Rd\mathbf{e}_{w_i} \in \mathbb{R}^{d}
  3. 拼接为矩阵所有向量按原顺序排成一列,得到整个句子的矩阵表示,供下游编码器使用。
    S=[ew1,⋯ ,ewn]\mathbf{S} = [ \mathbf{e}_{w_1}, \cdots, \mathbf{e}_{w_n} ]

远程监督:半真半假的“线人笔记”

主任扔给小林一本厚厚的《医学事实大全》,里面写着可靠知识:“阿司匹林—不良反应—皮疹。”“这不就是标准答案吗?”小林兴奋地对照病历,凡同时出现“阿司匹林”和“皮疹”的句子,统统标注成不良反应案例。省力极了。但经验丰富的老侦探在一旁冷笑:这份“标准答案”只会告诉他这两个名字出现在同一场景,却不会告诉他它们是否真有因果关系。

这种用外部知识库自动生成标注的方法叫远程监督(Distant Supervision)。它省去了昂贵的人工标注:只要知识库里存在三元组 (h, r, t),就假设所有同时包含 h 和 t 的句子都表达了关系 r。注意,这里有一个沉重的“假设”——它把“共现”直接当成了“关系”。对临床文本这种因果密集的领域,这个假设会制造大量噪声。

远程监督的假设可以形式化如下:若知识库 KB 中有事实 (h, r, t),则与之对齐的句子 s 都打上标签 r。它的问题在于“共现≠因果”:一句“因过敏禁用阿司匹林,停药后仍出现皮疹”同时提到阿司匹林和皮疹,却根本不是不良反应关系。于是自动标注里混入了大量噪声,这正是后续环节要去噪的原因。远程监督的价值在于“快”,代价在于“脏”。

小林在笔记本上画了一个问号:“线人笔记可以信,但不能全信。”他决定给每条线索加一道筛子——先把嫌疑人和受害者拼成完整的“证据画像”。

∀(h,r,t)∈KB,  ∀s∈Sh,t:label(s)=r\forall (h, r, t) \in \mathcal{KB}, \; \forall s \in S_{h,t}: \text{label}(s) = r
只要知识库中有 (h,r,t) 事实,所有同时包含 h 和 t 的句子都被当作正例。KB 表示外部医学知识库,S_{h,t} 是对应的句子集合。
  1. 知识库事实KB 是从药典、诊疗指南等整理出的三元组集合,每个事实都是“权威线报”。
    (h,r,t)∈KB(h, r, t) \in \mathcal{KB}
  2. 句子袋S_{h,t} 是所有同时出现头实体 h 和尾实体 t 的句子集合,这些句子被收集起来。
    Sh,t={s∣h∈s,t∈s}S_{h,t} = \{ s \mid h \in s, t \in s \}
  3. 全量标注句子袋中的每一个句子都被打上关系标签 r,不管语义是否真正相关。
    ∀s∈Sh,t:label(s)=r\forall s \in S_{h,t}: \text{label}(s) = r

实体对建模:拼出完整的“证据画像”

侦探破案不能只看一句话:嫌疑人阿司匹林、受害者皮疹,还要看整个案发环境的语境。“阿司匹林 100mg 导致皮疹”和“阿司匹林虽好但患者出现皮疹”,同样是阿司匹林与皮疹同框,因果方向截然不同。小林把“头实体—尾实体—句子语境”三样东西钉在证据板上,拼成一份完整的证据画像。模型要做的,也正是把这三股信息拧成一股绳。

在模型里,这份“证据画像”叫实体对表示。给定头实体 h、尾实体 t 和它们所在的句子 s,我们把三者分别编码成向量,再拼接成一个长向量 x_{h,t}。拼接操作把三份信息的维度合而为一,模型可以从中同时看到“谁、谁、在什么情况下”。这个向量就是该实体对在上下文中的综合指纹,后续分类器只认指纹,不认原文。

头实体 h 的向量通常由它包含的所有 token 向量取平均得到,尾实体 t 同理;句子向量则来自上一步的句子编码器。三者拼接后的维度是三者维度之和,信息完全不丢失。这种“先编码、再拼接”的方式简单有效,是关系抽取中最经典的实体对建模范式,也是更复杂的图神经网络等方法的基础。

证据画像拼好了,可小林发现一个案件里嫌疑人可能同时犯了多个罪——吃阿司匹林既是剂量问题,又引发了不良反应。他需要一套“多罪名并罚”的判定法。

xh,t=[h;t;s]\mathbf{x}_{h,t} = [ \mathbf{h}; \mathbf{t}; \mathbf{s} ]
分号表示向量拼接,把头实体、尾实体、句子三部分表示连成一个长向量。x 是实体对在上下文中的综合表示。
  1. 头实体表示h 向量由药物 mention 中所有 token 的向量取平均而来,例如“阿司匹林”的三个字向量求平均。
    h=1mh∑i=1mhvi\mathbf{h} = \frac{1}{m_h} \sum_{i=1}^{m_h} \mathbf{v}_i
  2. 尾实体表示t 向量同理,对“100mg”或“皮疹”的 token 向量求平均。
    t=1mt∑j=1mtvj\mathbf{t} = \frac{1}{m_t} \sum_{j=1}^{m_t} \mathbf{v}_j
  3. 拼接成一列三个向量按序拼接,维度相加,得到实体对级表示,供下游分类。
    xh,t=[h;t;s]∈Rdh+dt+ds\mathbf{x}_{h,t} = [\mathbf{h}; \mathbf{t}; \mathbf{s}] \in \mathbb{R}^{d_h+d_t+d_s}

多标签分类:一个案件背多个“罪名”

小林手里的案件越来越复杂:一个实体对可能同时成立多种关系。“阿司匹林 100mg 导致皮疹”里,阿司匹林和 100mg 构成药物-剂量关系,阿司匹林和皮疹又构成药物-不良反应关系。侦探不能只贴一个标签,而要列出全部成立的罪名。如果只准选一个,就像法庭只允许判一条罪,明显违背临床事实。

这正对应机器学习里的多标签分类问题。与常见的单标签分类(softmax 让所有类别概率和为 1)不同,多标签分类对每个关系类型独立做判断:每个关系 k 有自己的打分器和 Sigmoid 门,输出 0 到 1 之间的概率,互不压制。概率超过阈值 θ 的关系全部被接受。这样,一个“阿司匹林-100mg”实体对可以同时输出“药物-剂量”和“药物-不良反应”两个标签。

给定实体对表示 x,模型对每个候选关系 k 计算线性得分,再经 Sigmoid 压成概率。预测时收集所有概率大于 θ 的关系作为该实体对的多标签结果。阈值 θ 是个可调旋钮:调高则保守、只接受高置信关系;调低则激进、更容易把弱信号也纳入。在药物警戒场景,宁可调低阈值多报几个疑似信号,也不放过一个真实风险。

小林学会了“一案多罪”地归档,可新问题来了:线人笔记(远程监督)里混着假情报,有些句子表面提到两个实体,实际毫无关系。他需要一套甄别伪证的机制。

Pk=σ(wk⊤x+bk),R^={k∣Pk>θ}P_k = \sigma( \mathbf{w}_k^\top \mathbf{x} + b_k ), \quad \hat{\mathcal{R}} = \{ k \mid P_k > \theta \}
σ 是 Sigmoid 函数,把任意实数压到 (0,1) 区间,表示关系 k 成立的概率;最后把所有超过阈值 θ 的关系收集起来,形成多标签输出。
  1. 线性打分关系 k 的权重向量 w_k 与实体对表示 x 做内积,再加偏置 b_k,得到原始分数。
    zk=wk⊤x+bkz_k = \mathbf{w}_k^\top \mathbf{x} + b_k
  2. Sigmoid 概率化把任意实数分数压到 0 到 1 之间,解释为“该关系成立的概率”。
    Pk=11+e−zkP_k = \frac{1}{1 + e^{-z_k}}
  3. 阈值收网超过阈值 θ 的关系全部输出,允许多个关系同时成立。
    R^={k∣Pk>θ}\hat{\mathcal{R}} = \{ k \mid P_k > \theta \}

噪声处理:用注意力甄别“伪证”

档案室里躺着一条矛盾线索:“患者对阿司匹林过敏禁用,改用布洛芬后出现皮疹。”远程监督会把它标成“阿司匹林-不良反应-皮疹”——可阿司匹林根本没被吃下去!老侦探在证词上画了个红叉:这是伪证。这样一条伪证混进训练数据,模型就会学到“阿司匹林和皮疹同框就算不良反应”的错误规律。

这种伪证在远程监督标注中大量存在:实体共现但语义不相关。经典解法是“多实例学习”:把一个实体对涉及的所有句子看成一个袋子,模型只要确认袋子里至少有一个句子支持该关系,就算正例。更进一步,注意力机制让模型给袋内每个句子分配权重,语义相关的句子权重大,伪证句子权重自动趋近于 0。这就像侦探听取多个线人证词时,给可靠线人更高的信任分。

注意力权重通过一个可学习的查询向量 u(类似“理想关系句”的原型)计算:每个句子表示 sᵢ 与 u 做点积得到相关分数,再用 softmax 归一化成权重 αᵢ,最后把袋内所有句子按权重加权平均,得到干净的袋表示 x_bag。有了这个机制,噪声句子的影响被大幅削弱,模型不再被个别伪证带偏。

小林的案卷质量直线上升。月底主任来考核破案成绩:你抓了这么多“关系”,到底多少抓对了、多少漏掉了?小林愣住了——破案率怎么算?

xbag=∑i=1nαisi,αi=exp⁡(u⊤si)∑jexp⁡(u⊤sj)\mathbf{x}_{\text{bag}} = \sum_{i=1}^{n} \alpha_i \mathbf{s}_i, \quad \alpha_i = \frac{\exp(\mathbf{u}^\top \mathbf{s}_i)}{\sum_{j} \exp(\mathbf{u}^\top \mathbf{s}_j)}
αᵢ 是第 i 个句子的注意力权重,所有句子加权求和得到袋表示。与关系越相关的句子权重越大,伪证句的权重自动趋近于 0。
  1. 句子袋表示袋中有 n 个句子,每个句子已经通过编码器得到向量 sᵢ。
    B={s1,s2,⋯ ,sn}\mathcal{B} = \{ \mathbf{s}_1, \mathbf{s}_2, \cdots, \mathbf{s}_n \}
  2. 相关度打分可学习的查询向量 u 与每个句子做点积,得到该句与“理想关系句”的相似度分数。
    ei=u⊤sie_i = \mathbf{u}^\top \mathbf{s}_i
  3. Softmax 加权分数归一化成权重 αᵢ,加权平均得到袋表示;噪声句的相似度低,权重趋近 0。
    αi=exp⁡(ei)∑jexp⁡(ej)\alpha_i = \frac{\exp(e_i)}{\sum_j \exp(e_j)}

评测指标:给侦探的“结案率”打分

主任翻开小林的结案报告:“这个月你归档了 3000 条药物-剂量关系,我抽查发现 200 条是错的;还有 500 条真实关系漏在病历里没找出来。”小林第一次意识到:破案既要抓得准,还要抓得全。光看总量没有意义,一个只会输出“所有实体对都是药物-剂量关系”的笨系统,能“归档”几万条,但毫无用处。

信息抽取领域用精确率(Precision)和召回率(Recall)来衡量这两个维度。精确率 = 模型预测的关系中真正正确的比例,回答“抓得准不准”;召回率 = 真实存在的关系中被找回来的比例,回答“抓得全不全”。两者往往此消彼长:阈值设高,精确率上去了但漏掉很多;阈值设低,召得全但错得也多。这就像侦探:只抓证据确凿的案子,破案率高但漏案多;看见可疑就抓,破案率低但几乎不漏。

F1 分数是两者的调和平均,综合衡量系统质量。在药物不良反应监测这种场景,漏掉一个严重不良反应可能危及患者生命,因此召回率往往比精确率更受重视;而在构建用药知识库时,错误知识会误导临床决策,精确率就更关键。选型时应按业务场景看 PR 曲线找平衡点,而不是单看一个数字。

拿到评分标准后,小林的办案方向清晰了:不同案件对“准”和“全”的权重不同。半年后,他的知识档案被医院各科室争相调用——侦探的笔记,终于变成了守护患者安全的“天网”。

P=TPTP+FP,R=TPTP+FN,F1=2PRP+RP = \frac{TP}{TP+FP}, \quad R = \frac{TP}{TP+FN}, \quad F1 = \frac{2PR}{P+R}
TP 是预测为正且真实也为正的样本数;FP 是预测为正但真实为负;FN 是预测为负但真实为正。F1 是两者的调和平均。
  1. 精确率所有被预测为“有关系”的样本中,真正有关系的比例;分母是模型输出为正的全体。
    P=TPTP+FPP = \frac{TP}{TP+FP}
  2. 召回率所有真实存在关系的样本中,被模型找回来的比例;分母是真实为正的全体。
    R=TPTP+FNR = \frac{TP}{TP+FN}
  3. F1 调和平均一个分数同时反映准与全,比算术平均更严格,偏向两者中的较小值。
    F1=2PRP+RF1 = \frac{2PR}{P+R}

应用价值:从侦探笔记到“医疗天网”

半年后的清晨,药剂科主任敲开小林的办公室:“你整理的档案帮我们拦下了一张 2 倍剂量的阿司匹林处方!”原来,小林的关系抽取系统自动比对了处方中的“药物-剂量”三元组,在药物即将发放前拉响了警报。一纸档案,从“事后整理”变成了“事前拦截”,这就是结构化知识的力量。

这正是医学关系抽取的核心价值:把沉睡在病历里的非结构化知识,变成可供系统查询的结构化知识库。新知识三元组不断被抽取出来,知识库规模持续扩张。要判断一个三元组能否入库,只需看模型预测概率是否超过可靠阈值 θ。这像一个自动化的“知识流水线”,每天从新入院的病历中提炼事实,不断充实医疗知识图谱。

围绕三类关系,最典型的应用场景有三个:药物警戒系统实时扫描病历与文献,捕捉“药物-不良反应”信号,把传统上报模式下 18 个月的发现周期压缩到几周;临床决策支持系统审核“药物-剂量”合理性,在医生开出处方时即时提醒超量风险;科研团队从海量文献中抽取“疾病-症状”关联,构建辅助诊断知识图谱,支持罕见病循证研究。每一类应用,都依赖关系抽取把文本变成可计算的实体与连线。

小林站在档案室门口,看着那排病历架。曾经的天书,如今变成一张会呼吸的知识网,在每一条医嘱背后悄悄站岗。他忽然觉得,当一名“病历侦探”,是这个时代最酷的工作。

ΔK={(h,r,t)∣P(r∣h,t,S)>θ}\Delta \mathcal{K} = \{ (h, r, t) \mid P(r \mid h, t, S) > \theta \}
凡是模型对某实体对预测某关系概率超过阈值 θ 的三元组,就作为新知识写入知识库,构成知识库的增量。
  1. 候选实体对临床文本中所有被识别出的实体对,都可能构成候选知识,集合记为 C。
    (h,t)∈C(h, t) \in \mathcal{C}
  2. 概率预测模型预测实体对 (h,t) 在关系 r 上的成立概率,来自多标签分类的 Sigmoid 输出。
    P(r∣h,t,S)P(r \mid h, t, S)
  3. 阈值入库概率高于 θ 的三元组被写入知识库,成为知识图谱新增长量。
    P(⋅)>θ⇒(h,r,t)∈ΔKP(\cdot) > \theta \Rightarrow (h, r, t) \in \Delta \mathcal{K}

AI 应用场景

场景一:药物警戒中的不良反应信号监测

阶段:模型部署与下游应用

解决的问题:传统不良反应上报依赖医生主动填写,漏报率高、周期长;大量不良反应藏在病历叙述里无人发现。AI 自动抽取“药物-不良反应”关系,从电子病历和文献中实时发掘可疑信号,把事后统计变成事前预警。

具体案例:某药企用远程监督 + 注意力去噪模型扫描 50 万份出院小结,自动抽取“阿司匹林-消化道出血”等不良反应三元组,将新信号的发现时间从 18 个月缩短到 2 周,并提交给医学部复核。

场景二:临床决策支持系统中的用药安全审核

阶段:特征工程与在线推理

解决的问题:处方审核依赖静态药理知识库,新药和新剂量信息更新滞后。关系抽取将“药物-剂量”三元组实时从病历与处方中抽取出来,与安全范围比对,在药品发放前提示超剂量风险。

具体案例:某三甲医院 CDSS 接入关系抽取模块,在医生开具 2 倍常规剂量阿司匹林时触发拦截弹窗,药师介入核对后修正处方,避免了潜在的胃肠道出血风险。

场景三:科研知识库与疾病-症状图谱构建

阶段:数据标注与知识融合

解决的问题:循证医学需要大规模结构化的“疾病-症状”关联,人工阅读摘要费时费力且难以穷尽。关系抽取自动将文献中的零散描述转化为图谱节点与边,支撑科研人员快速检索和假设生成。

具体案例:研究团队从 10 万篇 PubMed 摘要中抽取“发热-咳嗽-肺炎”等疾病症状关联,构建罕见病辅助诊断知识图谱,帮助医生在遇到不明原因发热时快速列出候选疾病。

Python 演示

python72 行
import numpy as npfrom sklearn.linear_model import LogisticRegressionfrom sklearn.multioutput import MultiOutputClassifierfrom sklearn.metrics import precision_recall_fscore_support RELS = ["drug-dose", "drug-adr", "disease-symptom"] # 远程监督生成的句子袋: (实体对, 句子列表, 多标签0/1)# 注意第2个袋含有噪声句: aspirin 和 rash 共现但无因果关系data = [    (("aspirin", "100mg"),     ["aspirin 100mg caused a rash",      "aspirin 100mg daily for heart disease"],     [1, 0, 0]),    (("aspirin", "rash"),     ["aspirin 100mg caused a rash",      "aspirin is safe but a rash appeared after infection"],     [0, 1, 0]),    (("fever", "cold"),     ["fever and cough usually mean a cold",      "the patient had fever and then caught a cold"],     [0, 0, 1]),] # 构建词表与词袋特征words = sorted(set(w for _, sents, _ in data for s in sents for w in s.split()))w2i = {w: i for i, w in enumerate(words)} def bow(sentence):    v = np.zeros(len(words))    for w in sentence.split():        v[w2i[w]] = 1    return v # 注意力池化: 用关系原型作为查询向量, 给袋内句子加权def attention_pool(sentences, query):    features = np.array([bow(s) for s in sentences])    scores = features @ query    alpha = np.exp(scores - scores.max())    alpha = alpha / alpha.sum()    return alpha @ features, alpha # 构造一个针对 drug-adr 的关系原型(可学习查询向量的简化代替)prototype = np.zeros(len(words))for _, sents, y in data:    if y[1] == 1:        for s in sents:            prototype += bow(s)prototype /= np.linalg.norm(prototype) + 1e-9 X, Y = [], []print("=== 医学关系抽取演示: 远程监督 + 注意力去噪 ===")for (h, t), sents, y in data:    bag_vec, alpha = attention_pool(sents, prototype)    X.append(bag_vec)    Y.append(y)    print("实体对 (%s, %s) 句权重=%s 标签=%s" % (h, t, np.round(alpha, 3), y)) X = np.array(X)Y = np.array(Y) # 多标签分类: 每个关系训练一个独立的二分类器clf = MultiOutputClassifier(LogisticRegression(max_iter=800))clf.fit(X, Y)pred = clf.predict(X) # 评测指标p, r, f1, _ = precision_recall_fscore_support(Y, pred, average="micro")print("Micro 精确率=%.3f 召回率=%.3f F1=%.3f" % (p, r, f1))for j, rel in enumerate(RELS):    acc = sum(1 for i in range(len(data)) if Y[i, j] == pred[i, j])    print("%s 命中 %d/%d" % (rel, acc, len(data)))
目的:演示远程监督构建训练数据、注意力池化降噪、多标签分类器训练与评估的完整小流程,直接对应正文中的方法链条。
  1. data = [用远程监督假设手写训练袋,第 2 个袋故意混入“共现但无关”的噪声句。
  2. def attention_pool(sentences, query):注意力池化核心:按句子与关系原型的相似度给每个句子分配权重。
  3. alpha = alpha / alpha.sum()Softmax 归一化,确保权重之和为 1,权重可解释为“可信度”。
  4. prototype = np.zeros(len(words))用正例句平均构造“理想关系句”原型,是可学习查询向量的简化代替。
  5. clf = MultiOutputClassifier(LogisticRegression(max_iter=800))多标签分类:每个关系训练一个独立的二分类器。
  6. p, r, f1, _ = precision_recall_fscore_support(Y, pred, average="micro")计算精确率、召回率、F1,评估模型整体质量。

常见误区

误区远程监督用知识库自动标注,不需要人工成本,直接拿这些标签训练模型,效果应该既快又好。既然知识库都是权威的,标注还能不准吗?

正解远程监督的标签有系统性噪声:知识库里的“阿司匹林-皮疹”事实,不代表每个同时出现这两个词的句子都是不良反应。“患者对阿司匹林过敏禁用,停药后出现皮疹”就是一个典型伪证。就像线人笔记里混着假情报,直接全信会教坏模型。必须用多实例学习、注意力加权、置信度过滤等手段去噪,把“共现”筛选成“因果”。忽视噪声的模型,在真实病历上的精确率可能从 0.9 掉到 0.5。

为何常见:自动标注省时省力,人天然倾向相信“现成答案”,容易忽略标注来源本身的准确性问题。

误区反正都是分类,softmax 也能用,效果差不多。换一个激活函数而已,能有多大差别?

正解两者语义完全不同。softmax 强制所有类别概率和为 1,本质是“互斥单选题”;而临床文本中一个实体对可以同时是“药物-剂量”又是“药物-不良反应”,关系并不互斥。用 softmax 会逼模型在多个正确关系中只能选一个,导致漏报。Sigmoid 对每个关系独立输出 0 到 1 概率,互不压制,这才是多标签的正确打开方式。

为何常见:初学者接触的大多是单标签分类,习惯性把所有分类问题都套用 softmax,没有意识到“标签是否互斥”决定了输出层的设计。

误区一句话里同时出现“阿司匹林”和“皮疹”,那它肯定在描述阿司匹林导致皮疹。两个词离得这么近,关系还能跑?

正解共现只是“出现在同一场景”,距离“存在语义关系”还差着十万八千里。“患者对阿司匹林过敏禁用,停药后出现皮疹”里,阿司匹林和皮疹共同出现,却是负例。远程监督正是吃了这个亏。关系抽取必须建模上下文语义,用注意力等机制分辨因果方向,而不是数实体是否同框。侦探办案讲究证据链,不是看两个人是否出现在同一街区。

为何常见:人的直觉容易把空间邻近误认为因果关联,尤其在医学这种因果密集的领域,这种直觉错误会被放大。

误区模型上线前对比 F1,哪个高就用哪个准没错。排行榜都看 F1,这总不会错吧?

正解F1 是精确率与召回率的调和平均,但它把两者当成同等重要。实际业务中两者的代价不对称:在药物警戒中,漏报一个严重不良反应可能出人命,召回率比精确率更关键;而在用药知识库建设中,错误知识会误导临床决策,精确率又更重要。选型时应该按业务场景看 PR 曲线找平衡点,而不是单看一个 F1 数字。

为何常见:机器学习课程和排行榜都以 F1 作为标准指标,容易让人忽略指标背后的业务代价与风险偏好。

面试题

Q1. 医学关系抽取中,关系三元组的正确结构是?

单选题 · easy

  • A.(标签,特征,预测)
  • B.(头实体,关系,尾实体)← 正确答案
  • C.(文档,段落,句子)
  • D.(药物,剂量,频次)

答案:B。关系抽取把文本事实表示成 (头实体,关系,尾实体) 三元组,例如 (阿司匹林,药物-剂量,100mg)。A 是机器学习通用流程,C 是文本层级结构,D 只是某一个具体实例的展开,都不具备普遍性。

Q2. 远程监督的核心思想是?

单选题 · easy

  • A.完全依赖人工标注病历
  • B.利用知识库自动对齐生成标签← 正确答案
  • C.用聚类算法自动发现关系
  • D.用强化学习训练抽取模型

答案:B。远程监督假设:知识库中存在 (h,r,t),则所有同时包含 h 和 t 的句子都标为关系 r。它把知识库当“线人笔记”自动生成训练数据,并非人工标注、聚类或强化学习。

Q3. 多标签关系分类的输出层通常使用哪个激活函数?

单选题 · easy

  • A.Softmax 归一化输出
  • B.Sigmoid 独立概率输出← 正确答案
  • C.ReLU 线性修正单元
  • D.Tanh 双曲正切函数

答案:B。多标签分类需要每个关系独立判断,Sigmoid 将每个分数压到 0 到 1,互不压制。Softmax 强制所有概率和为 1,会把多个正确关系挤掉一个;ReLU 和 Tanh 不适合直接当作概率输出。

Q4. 远程监督自动标注最主要的噪声来源是?

单选题 · mid

  • A.实体识别模型严重过拟合
  • B.实体共现并不代表真实因果← 正确答案
  • C.训练语料规模太小导致欠拟合
  • D.模型参数量过于庞大难以收敛

答案:B。远程监督的核心假设“共现即关系”本身就是噪声源头。一句“阿司匹林过敏禁用,停药后出现皮疹”同时出现两个词,却毫无因果关系。其余选项属于模型训练层面的问题,与远程监督标注时的固有缺陷无关。

Q5. 下面哪句最可能被远程监督误判为“药物-不良反应”正例?

单选题 · mid

  • A.阿司匹林100mg导致皮疹
  • B.阿司匹林安全但出现皮疹← 正确答案
  • C.患者服用阿司匹林治头痛
  • D.二甲双胍500mg引发恶心

答案:B。B 句同时包含“阿司匹林”和“皮疹”,但皮疹与阿司匹林无因果链,远程监督只看共现会把它错标成正例。A 和 D 是真实因果描述,C 不含不良反应实体,都不是典型误标句。

Q6. 下面哪些属于本文讨论的医学关系类型?

多选题 · mid

  • A.药物与剂量关系← 正确答案
  • B.药物与不良反应关系← 正确答案
  • C.疾病与症状关系← 正确答案
  • D.作者与机构关系

答案:ABC。本文聚焦三类临床关系:药物-剂量、药物-不良反应、疾病-症状。作者与机构属于文献计量学关系,不属于临床医学关系抽取的研究范围。

Q7. 关于注意力机制在噪声处理中的作用,正确的是?

单选题 · mid

  • A.给所有句子分配相同权重
  • B.自动降低与关系无关句子权重← 正确答案
  • C.只保留一句作为袋代表
  • D.随机丢弃袋内部分句子

答案:B。注意力机制按句子与关系原型的相关度打分,softmax 归一化后,无关噪声句权重趋近 0,相关句权重增大。它不做截断也不随机丢弃,而是软性地加权。

Q8. 处理远程监督噪声的常用方法有哪些?

多选题 · hard

  • A.多实例学习方法← 正确答案
  • B.注意力加权机制← 正确答案
  • C.置信度过滤策略← 正确答案
  • D.随机删除句子

答案:ABC。多实例学习以句子袋为单位监督,注意力加权自动降低噪声句权重,置信度过滤剔除低分标签样本,都是有效去噪策略。随机删句子无差别破坏数据,不是合理方案。

Q9. 药物警戒场景中,最应优先关注哪个指标?

单选题 · hard

  • A.精确率 Precision
  • B.召回率 Recall← 正确答案
  • C.模型推理吞吐量
  • D.模型参数总量

答案:B。药物警戒的目标是“不漏过任何严重不良反应”。漏报意味着患者暴露于未知风险,代价极高;相反,多一些假报警可以由药师复核过滤。因此召回率优先于精确率,吞吐量和参数量属于工程优化而非安全指标。

Q10. 关于“远程监督+注意力去噪+多标签分类”的流程,下列说法正确的是?

多选题 · extreme

  • A.远程监督用知识库自动标注← 正确答案
  • B.注意力机制按相关度分配权重← 正确答案
  • C.Sigmoid 允许关系同时成立← 正确答案
  • D.共现实体对一定存在真实关系

答案:ABC。A、B、C 分别对应流程的三个关键认知:远程监督自动标注但可能引入噪声,注意力机制按相关度降噪,Sigmoid 支持一对多关系。D 是远程监督的经典误区:“共现不等于因果”,正是噪声的来源,因此不能选。