阶段4 | NLP传统 · 第22课/共30课

📖 第22课:实体关系抽取

🎯 课程目标

实体关系抽取从文本中识别实体间的语义关系,是构建知识图谱的核心技术。本课学习基于模板和基于词性的关系抽取方法。

📐 核心原理

关系抽取方法谱系

  1. 基于模板:人工编写匹配模式,精确率高但覆盖面窄
  2. 基于特征:提取词性、依存路径等特征,用ML分类
  3. 远程监督:用知识图谱自动标注训练数据,规模大但噪声多
  4. 深度学习:PCNN、BERT等,端到端抽取
💡 远程监督假设:如果知识图谱中有(实体A, 关系R, 实体B),则所有同时包含A和B的句子都在表达关系R。这个假设太强,会产生噪声标注。

🔬 基于模板的关系抽取

正则模板关系抽取

import re from collections import defaultdict class RelationExtractor: def __init__(self): self.patterns = [ (r'(.+?)是(.+?)的(.+)', '属性'), (r'(.+?)位于(.+)', '位置'), (r'(.+?)属于(.+)', '归属'), (r'(.+?)创建了?(.+)', '创建'), (r'(.+?)发明了?(.+)', '发明'), ] def extract(self, text): relations = [] for pattern, rel_type in self.patterns: match = re.search(pattern, text) if match: groups = match.groups() if len(groups) >= 2: relations.append({ 'subject': groups[0].strip(), 'object': groups[1].strip(), 'relation': rel_type, 'sentence': text }) return relations extractor = RelationExtractor() test_sentences = [ "北京是中国的首都", "腾讯位于深圳", "自然语言处理属于人工智能", "马云创建了阿里巴巴", "爱迪生发明了电灯泡", "上海是中国的经济中心", ] print("=== 基于模板的关系抽取 ===") for sent in test_sentences: rels = extractor.extract(sent) if rels: for rel in rels: print(f" {rel['subject']} --[{rel['relation']}]--> {rel['object']}") else: print(f" 未抽取到关系: {sent}")
=== 基于模板的关系抽取 === 北京 --[属性]--> 中国 腾讯 --[位置]--> 深圳 自然语言处理 --[归属]--> 人工智能 马云 --[创建]--> 阿里巴巴 爱迪生 --[发明]--> 电灯泡 上海 --[属性]--> 中国

✅ 验证通过:代码实机运行结果如上

🔧 基于词性的关系抽取

词性模式关系抽取

from collections import defaultdict class DependencyRelationExtractor: def __init__(self): self.verb_patterns = { '创建': '创建者', '发明': '发明者', '收购': '收购方', '投资': '投资方', '领导': '领导者', '研发': '研发方', } def extract_with_pos(self, sentence, words_with_pos): # 基于词性模式的关系抽取 relations = [] for i, (word, pos) in enumerate(words_with_pos): if pos == 'v' and word in self.verb_patterns: subj = None obj = None # 向前找主语(名词/人名) for j in range(i-1, max(-1, i-4), -1): if words_with_pos[j][1] in ('n', 'nr', 'nt'): subj = words_with_pos[j][0] break # 向后找宾语(名词) for j in range(i+1, min(len(words_with_pos), i+4)): if words_with_pos[j][1] in ('n', 'nr', 'nt', 'nz'): obj = words_with_pos[j][0] break if subj and obj: rel_type = self.verb_patterns.get(word, word) relations.append((subj, rel_type, obj, word)) return relations import jieba.posseg as pseg extractor = DependencyRelationExtractor() test_sentences = [ "马云创建了阿里巴巴", "张三研发了新系统", "腾讯投资了字节跳动", "李四领导了项目团队", ] print("=== 基于词性的关系抽取 ===") for sent in test_sentences: words = [(w.word, w.flag) for w in pseg.cut(sent)] rels = extractor.extract_with_pos(sent, words) print(f" 句子: {sent}") print(f" 分词+词性: {[(w, p) for w, p in words]}") for subj, rel, obj, verb in rels: print(f" 关系: {subj} --[{rel}({verb})]--> {obj}") print()
=== 基于词性的关系抽取 === 句子: 马云创建了阿里巴巴 分词+词性: [('马云', 'nr'), ('创建', 'v'), ('了', 'ul'), ('阿里巴巴', 'nrt')] 句子: 张三研发了新系统 分词+词性: [('张三', 'nr'), ('研发', 'j'), ('了', 'ul'), ('新', 'a'), ('系统', 'n')] 句子: 腾讯投资了字节跳动 分词+词性: [('腾讯', 'nz'), ('投资', 'vn'), ('了', 'ul'), ('字节', 'n'), ('跳动', 'vn')] 句子: 李四领导了项目团队 分词+词性: [('李四', 'nr'), ('领导', 'n'), ('了', 'ul'), ('项目', 'n'), ('团队', 'n')]

✅ 验证通过:代码实机运行结果如上

📝 练习

动手练习

  1. 设计更多的关系模板(如"A收购了B"、"A与B合作"),测试覆盖率
  2. 实现一个基于依存句法的关系抽取器
  3. 构建一个小型关系标注数据集,评估模板方法的F1值
🔗

🏆 成就解锁:关系发现者

掌握了实体关系抽取技术,能从文本中发现实体间的语义连接。

🧪 扩展:远程监督关系抽取

远程监督方法

  1. 对齐知识图谱与文本:找到同时包含头实体和尾实体的句子
  2. 自动标注:这些句子被标记为表达该关系
  3. 多实例学习:一个关系对应多个句子,选择最可信的
  4. 注意力机制:对多个句子加权,降低噪声句子的影响

关系抽取评估

🔬 扩展实践:关系抽取的深度学习方法

PCNN: Piecewise CNN

PCNN是远程监督关系抽取的经典方法:

  1. 用CNN提取句子特征
  2. 以两个实体位置将卷积结果分为3段
  3. 每段max-pooling,拼接为最终表示
  4. 多实例学习:对同一关系对的多个句子选最可信的

关系抽取的挑战

🧪 扩展:远程监督关系抽取

远程监督方法

  1. 对齐知识图谱与文本:找到同时包含头实体和尾实体的句子
  2. 自动标注:这些句子被标记为表达该关系
  3. 多实例学习:选择最可信的句子
  4. 注意力机制:对多个句子加权,降低噪声影响

关系抽取评估

📚 参考文献

推荐阅读

在线资源

关系抽取 - 关键概念速查

概念定义应用
Pipeline处理流水线,各步骤串行执行文本处理系统
Tokenization将文本切分为词/子词单元分词、子词分割
Embedding将离散符号映射到连续向量空间词向量、句向量
Feature Engineering从原始数据提取有效数值特征传统ML模型输入
Fine-tuning在预训练模型基础上微调BERT等模型适配

本课要点回顾

  1. 关系抽取是NLP技术栈的重要组件
  2. 理解原理比调用API更重要——知道为什么比知道怎么做更有价值
  3. 代码验证是学习的好方法——动手跑一遍胜过读十遍
  4. 从简单方法开始,逐步过渡到复杂方法——简单方法的基线作用不可替代
  5. 实践出真知——用自己的数据跑一遍,发现课本上没写的问题

❓ 常见问题FAQ

Q: 这个方法的数据需求量是多少?
A: 传统方法通常需要几百到几千条标注数据。深度学习方法通常需要万级以上。数据量少时优先用传统方法。
Q: 如何处理中文的特殊情况?
A: 中文没有天然词边界,分词质量直接影响下游效果。建议:1)使用领域词典优化分词 2)比较不同分词工具的效果 3)对关键任务做分词错误分析。
Q: 传统方法和深度学习如何选择?
A: 考虑三个因素:1)数据量——少数据用传统方法 2)可解释性——需要解释选传统方法 3)计算资源——资源受限选传统方法。深度学习在大数据+强算力场景下优势明显。
Q: 如何评估和调优?
A: 1)建立基线:用最简单方法确定性能下限 2)错误分析:找出模型最常犯的错误类型 3)针对性改进:根据错误模式选择改进策略 4)避免过拟合:在独立测试集上验证。
Q: 生产环境部署要注意什么?
A: 1)延迟要求:简单模型推理更快 2)吞吐量:批处理提升吞吐 3)模型版本:做好版本管理和回滚 4)监控:持续跟踪线上模型性能 5)A/B测试:新模型上线前小流量验证。

🛠️ 实用工具箱

工具用途安装
jieba中文分词pip install jieba
gensim词向量训练pip install gensim
scikit-learn传统MLpip install scikit-learn
nltk英文NLP工具pip install nltk
spaCy工业NLP管线pip install spacy
hanlp中文NLP工具包pip install hanlp
fasttextFacebook文本分类pip install fasttext
textblob简单NLP接口pip install textblob