跳转至

📖 第8章:信息抽取

信息抽取

学习时间:8小时 难度星级:⭐⭐⭐⭐ 前置知识:序列标注、文本分类、预训练模型 学习目标:掌握关系抽取、事件抽取和知识图谱构建基础


📋 目录


1. 信息抽取概述

1.1 什么是信息抽取

信息抽取(Information Extraction, IE)从非结构化文本中自动提取结构化信息。

Python
ie_tasks = {
    "实体识别(NER)": {
        "描述": "识别文本中的实体及其类型",
        "例子": "[乔布斯/PER]在[加利福尼亚/LOC]创立了[苹果公司/ORG]",
        "参考": "第5章已详细讲解",
    },
    "关系抽取(RE)": {
        "描述": "识别实体之间的语义关系",
        "例子": "(乔布斯, 创立, 苹果公司), (乔布斯, 出生于, 加利福尼亚)",
    },
    "事件抽取(EE)": {
        "描述": "识别事件及其参与者、时间、地点等",
        "例子": "事件:创立 | 主体:乔布斯 | 客体:苹果公司 | 时间:1976年 | 地点:车库",
    },
    "属性抽取": {
        "描述": "提取实体的属性信息",
        "例子": "(苹果公司, 成立时间, 1976年)",
    },
}

ie_pipeline = """
信息抽取Pipeline:

原始文本 → NER → 关系抽取 → 事件抽取 → 知识图谱
  │         │        │          │          │
  │     识别实体  实体间关系  事件结构化  结构化存储
  │                                        │
  └──────── 非结构化 ───────────→ 结构化 ──┘
"""
print(ie_pipeline)

2. 关系抽取

2.1 关系抽取的方法

Text Only
关系抽取方法分类:

├── Pipeline方法
│   ├── 先做NER,再对实体对做关系分类
│   └── 优点:模块化,缺点:误差传递
├── 联合抽取方法
│   ├── 同时抽取实体和关系
│   └── 优点:避免误差传递,缺点:更复杂
├── 远程监督方法
│   ├── 用知识库自动标注语料
│   └── 优点:无需人工标注,缺点:标签噪声
└── 大模型方法
    ├── 用Prompt让LLM直接抽取
    └── 优点:零样本能力,缺点:效率低

2.2 基于分类的关系抽取(Pipeline)

Python
import torch
import torch.nn as nn
import numpy as np

class RelationClassifier(nn.Module):  # 继承nn.Module定义网络层
    """基于BERT的关系分类器"""

    def __init__(self, hidden_dim, num_relations, dropout=0.3):
        super().__init__()  # super()调用父类方法
        # 实体标记嵌入(标记实体位置)
        self.entity_fc = nn.Linear(hidden_dim * 2, hidden_dim)
        self.classifier = nn.Sequential(
            nn.Linear(hidden_dim, hidden_dim // 2),
            nn.ReLU(),
            nn.Dropout(dropout),
            nn.Linear(hidden_dim // 2, num_relations),
        )

    def forward(self, entity1_repr, entity2_repr):
        """
        entity1_repr: 第一个实体的表示 (batch, hidden)
        entity2_repr: 第二个实体的表示 (batch, hidden)
        """
        # 拼接两个实体表示
        combined = torch.cat([entity1_repr, entity2_repr], dim=-1)  # torch.cat沿已有维度拼接张量
        combined = torch.relu(self.entity_fc(combined))
        logits = self.classifier(combined)
        return logits

# 关系定义
relation_types = {
    0: "无关系",
    1: "创立",
    2: "就职于",
    3: "出生于",
    4: "位于",
    5: "毕业于",
    6: "父/母亲",
    7: "配偶",
}

# 简单演示
hidden_dim = 256
model = RelationClassifier(hidden_dim, len(relation_types))

# 模拟实体表示
e1 = torch.randn(1, hidden_dim)
e2 = torch.randn(1, hidden_dim)
logits = model(e1, e2)
pred = logits.argmax(dim=-1).item()  # 将单元素张量转为Python数值
print(f"预测关系: {relation_types[pred]}")

2.3 基于标注的联合抽取

Python
class JointExtractionModel:
    """
    联合实体关系抽取(标注方案)

    使用特殊标注体系将关系抽取转化为序列标注:
    对于三元组(subject, relation, object):
    - 对subject用 B-SUB_关系类型, I-SUB_关系类型 标注
    - 对object用 B-OBJ_关系类型, I-OBJ_关系类型 标注
    """

    def __init__(self):
        self.relations = ["创立", "就职于", "出生于", "位于"]

    def generate_tags(self, text, triples):
        """为文本生成标签"""
        chars = list(text)
        tags = ["O"] * len(chars)

        for subj, rel, obj in triples:
            # 标注subject
            subj_start = text.find(subj)
            if subj_start >= 0:
                tags[subj_start] = f"B-SUB_{rel}"
                for i in range(1, len(subj)):
                    tags[subj_start + i] = f"I-SUB_{rel}"

            # 标注object
            obj_start = text.find(obj)
            if obj_start >= 0:
                tags[obj_start] = f"B-OBJ_{rel}"
                for i in range(1, len(obj)):
                    tags[obj_start + i] = f"I-OBJ_{rel}"

        return list(zip(chars, tags))  # zip按位置配对

    def decode_triples(self, chars, tags):
        """从标签序列解码三元组"""
        subjects = {}  # rel -> subject text
        objects = {}   # rel -> object text

        current_text = ""
        current_type = None
        current_rel = None

        for char, tag in zip(chars, tags):
            if tag.startswith("B-SUB_") or tag.startswith("B-OBJ_"):
                # 保存之前的
                if current_text and current_type and current_rel:
                    if current_type == "SUB":
                        subjects[current_rel] = current_text
                    else:
                        objects[current_rel] = current_text

                parts = tag.split("_", 1)
                current_type = "SUB" if "SUB" in parts[0] else "OBJ"
                current_rel = parts[1]
                current_text = char
            elif tag.startswith("I-"):
                current_text += char
            else:
                if current_text and current_type and current_rel:
                    if current_type == "SUB":
                        subjects[current_rel] = current_text
                    else:
                        objects[current_rel] = current_text
                current_text = ""
                current_type = None
                current_rel = None

        # 最后一个
        if current_text and current_type and current_rel:
            if current_type == "SUB":
                subjects[current_rel] = current_text
            else:
                objects[current_rel] = current_text

        # 组合三元组
        triples = []
        for rel in set(subjects.keys()) & set(objects.keys()):
            triples.append((subjects[rel], rel, objects[rel]))

        return triples

# 测试
je = JointExtractionModel()

text = "乔布斯在加利福尼亚创立了苹果公司"
triples = [("乔布斯", "创立", "苹果公司")]

tagged = je.generate_tags(text, triples)
print("联合抽取标注:")
for char, tag in tagged:
    if tag != "O":
        print(f"  {char}{tag}")

# 解码
chars = [c for c, _ in tagged]
tags = [t for _, t in tagged]
decoded = je.decode_triples(chars, tags)
print(f"\n解码三元组: {decoded}")

3. 事件抽取

3.1 事件抽取任务

Python
"""
事件抽取层次:
1. 事件检测(Event Detection): 判断句子中是否存在事件,识别触发词
2. 论元抽取(Argument Extraction): 识别事件的参与者和元素
"""

event_example = {
    "文本": "2024年3月15日,马斯克以440亿美元收购了Twitter公司",
    "事件类型": "收购",
    "触发词": "收购",
    "论元": {
        "时间": "2024年3月15日",
        "收购方": "马斯克",
        "金额": "440亿美元",
        "被收购方": "Twitter公司",
    },
}

# 事件类型体系
event_schema = {
    "商业事件": ["收购", "合并", "上市", "融资", "破产"],
    "人事事件": ["任职", "离职", "退休", "就职"],
    "司法事件": ["起诉", "判决", "逮捕", "释放"],
    "灾害事件": ["地震", "火灾", "洪水", "台风"],
    "军事事件": ["冲突", "谈判", "协议"],
}

print("事件抽取示例:")
print(f"  文本: {event_example['文本']}")
print(f"  事件类型: {event_example['事件类型']}")
print(f"  触发词: {event_example['触发词']}")
print(f"  论元:")
for role, value in event_example['论元'].items():
    print(f"    {role}: {value}")

3.2 事件抽取实现

Python
import re

class SimpleEventExtractor:
    """基于规则和模式的事件抽取器"""

    def __init__(self):
        self.event_patterns = {
            "收购": {
                "trigger": re.compile(r"收购|并购|买下"),
                "args": {
                    "收购方": re.compile(r"([\u4e00-\u9fa5·]+(?:公司|集团|科技)?)(?:以|用|花)"),
                    "被收购方": re.compile(r"收购(?:了)?([\u4e00-\u9fa5a-zA-Z]+(?:公司|集团)?)"),
                    "金额": re.compile(r"(\d+(?:\.\d+)?(?:万|亿)?(?:美元|元|人民币))"),
                    "时间": re.compile(r"(\d{4}年\d{1,2}月\d{1,2}日)"),
                },
            },
            "任职": {
                "trigger": re.compile(r"就任|担任|出任|上任"),
                "args": {
                    "人物": re.compile(r"([\u4e00-\u9fa5]{2,4})(?:就任|担任|出任)"),
                    "职位": re.compile(r"(?:就任|担任|出任)([\u4e00-\u9fa5]+)"),
                },
            },
        }

    def extract(self, text):
        """从文本中抽取事件"""
        events = []

        for event_type, pattern_info in self.event_patterns.items():
            trigger_match = pattern_info["trigger"].search(text)
            if trigger_match:
                event = {
                    "event_type": event_type,
                    "trigger": trigger_match.group(),
                    "trigger_span": (trigger_match.start(), trigger_match.end()),
                    "arguments": {},
                }

                for arg_role, arg_pattern in pattern_info["args"].items():
                    arg_match = arg_pattern.search(text)
                    if arg_match:
                        event["arguments"][arg_role] = arg_match.group(1)

                events.append(event)

        return events

# 测试
ee = SimpleEventExtractor()
texts = [
    "2024年3月15日,马斯克以440亿美元收购了Twitter公司",
    "张三就任华为公司首席技术官",
]

for text in texts:
    events = ee.extract(text)
    print(f"\n文本: {text}")
    for event in events:
        print(f"  事件类型: {event['event_type']}")
        print(f"  触发词: {event['trigger']}")
        for role, value in event['arguments'].items():
            print(f"  {role}: {value}")

4. 开放信息抽取

4.1 Open IE

Python
class OpenIE:
    """开放信息抽取:不限定关系类型"""

    def __init__(self):
        self.patterns = [
            # 主语 + 谓语 + 宾语
            re.compile(r'([\u4e00-\u9fa5]+(?:公司|大学|集团|人|先生|女士)?)'
                       r'(创立|发明|创建|开发|研究|发现|提出|设计|生产|制造)'
                       r'了?([\u4e00-\u9fa5a-zA-Z]+)'),
            # 主语 + 是 + 宾语
            re.compile(r'([\u4e00-\u9fa5]+)'
                       r'是'
                       r'([\u4e00-\u9fa5]+的[\u4e00-\u9fa5]+|[\u4e00-\u9fa5]+)'),
            # 主语 + 位于/在 + 地点
            re.compile(r'([\u4e00-\u9fa5]+)'
                       r'(?:位于|坐落于|在)'
                       r'([\u4e00-\u9fa5]+)'),
        ]

    def extract(self, text):
        """抽取开放三元组"""
        triples = []

        for pattern in self.patterns:
            matches = pattern.finditer(text)
            for match in matches:
                groups = match.groups()
                if len(groups) == 3:
                    triples.append({
                        "subject": groups[0],
                        "predicate": groups[1],
                        "object": groups[2],
                    })
                elif len(groups) == 2:
                    triples.append({
                        "subject": groups[0],
                        "predicate": "是/在",
                        "object": groups[1],
                    })

        return triples

# 测试
oie = OpenIE()
texts = [
    "乔布斯创立了苹果公司",
    "北京大学位于北京市海淀区",
    "华为公司研究5G技术",
]

for text in texts:
    triples = oie.extract(text)
    print(f"\n'{text}':")
    for t in triples:
        print(f"  ({t['subject']}, {t['predicate']}, {t['object']})")

5. 知识图谱构建

5.1 知识图谱基础

Python
class KnowledgeGraph:
    """简易知识图谱"""

    def __init__(self):
        self.entities = {}  # 实体: {类型, 属性}
        self.relations = []  # (头实体, 关系, 尾实体)

    def add_entity(self, name, entity_type, attributes=None):
        self.entities[name] = {
            "type": entity_type,
            "attributes": attributes or {},
        }

    def add_relation(self, head, relation, tail):
        self.relations.append((head, relation, tail))

    def query(self, entity=None, relation=None):
        """简单查询"""
        results = []
        for h, r, t in self.relations:
            if entity and (h == entity or t == entity):
                results.append((h, r, t))
            elif relation and r == relation:
                results.append((h, r, t))
        return results

    def get_neighbors(self, entity, hops=1):
        """获取实体的邻居"""
        visited = {entity}
        current_level = {entity}
        all_triples = []

        for _ in range(hops):
            next_level = set()
            for h, r, t in self.relations:
                if h in current_level and t not in visited:
                    next_level.add(t)
                    all_triples.append((h, r, t))
                elif t in current_level and h not in visited:
                    next_level.add(h)
                    all_triples.append((h, r, t))
            visited |= next_level
            current_level = next_level

        return all_triples

    def stats(self):
        return {
            "entities": len(self.entities),
            "relations": len(self.relations),
            "relation_types": len(set(r for _, r, _ in self.relations)),
        }

    def to_triples(self):
        """导出为三元组列表"""
        return [(h, r, t) for h, r, t in self.relations]

# 构建知识图谱
kg = KnowledgeGraph()

# 添加实体
kg.add_entity("苹果公司", "ORG", {"成立年份": "1976", "总部": "库比蒂诺"})
kg.add_entity("乔布斯", "PER", {"出生年份": "1955", "国籍": "美国"})
kg.add_entity("库克", "PER", {"出生年份": "1960", "国籍": "美国"})
kg.add_entity("加利福尼亚", "LOC", {"国家": "美国"})
kg.add_entity("iPhone", "PRODUCT")
kg.add_entity("斯坦福大学", "ORG")

# 添加关系
kg.add_relation("乔布斯", "创立", "苹果公司")
kg.add_relation("乔布斯", "出生于", "加利福尼亚")
kg.add_relation("库克", "就职于", "苹果公司")
kg.add_relation("库克", "担任CEO", "苹果公司")
kg.add_relation("苹果公司", "生产", "iPhone")
kg.add_relation("苹果公司", "位于", "加利福尼亚")
kg.add_relation("乔布斯", "辍学于", "斯坦福大学")

# 查询
print("知识图谱统计:", kg.stats())

print("\n查询'乔布斯'的关系:")
for h, r, t in kg.query(entity="乔布斯"):
    print(f"  ({h}, {r}, {t})")

print("\n查询'苹果公司'的1跳邻居:")
for h, r, t in kg.get_neighbors("苹果公司", hops=1):
    print(f"  ({h}, {r}, {t})")

print("\n查询'苹果公司'的2跳邻居:")
for h, r, t in kg.get_neighbors("苹果公司", hops=2):
    print(f"  ({h}, {r}, {t})")

5.2 知识图谱嵌入

Python
class TransE(nn.Module):
    """TransE知识图谱嵌入模型

    核心思想:h + r ≈ t
    """

    def __init__(self, num_entities, num_relations, embedding_dim=50, margin=1.0):
        super().__init__()
        self.entity_embeddings = nn.Embedding(num_entities, embedding_dim)
        self.relation_embeddings = nn.Embedding(num_relations, embedding_dim)
        self.margin = margin

        # 初始化
        nn.init.xavier_uniform_(self.entity_embeddings.weight)
        nn.init.xavier_uniform_(self.relation_embeddings.weight)

    def forward(self, h, r, t):
        """计算三元组得分: ||h + r - t||"""
        h_emb = self.entity_embeddings(h)
        r_emb = self.relation_embeddings(r)
        t_emb = self.entity_embeddings(t)

        # L2距离
        score = torch.norm(h_emb + r_emb - t_emb, p=2, dim=-1)
        return score

    def loss(self, pos_h, pos_r, pos_t, neg_h, neg_r, neg_t):
        """Margin-based loss"""
        pos_score = self.forward(pos_h, pos_r, pos_t)
        neg_score = self.forward(neg_h, neg_r, neg_t)

        loss = torch.relu(self.margin + pos_score - neg_score).mean()
        return loss

# 创建TransE模型
transe = TransE(num_entities=100, num_relations=10, embedding_dim=50)
print(f"TransE参数量: {sum(p.numel() for p in transe.parameters()):,}")

6. 远程监督

Python
class DistantSupervision:
    """远程监督关系抽取

    核心假设:如果知识库中存在关系(e1, r, e2),
    那么包含e1和e2的句子都表达了关系r
    """

    def __init__(self):
        # 知识库中的事实
        self.kb_facts = {
            ("乔布斯", "创立", "苹果公司"),
            ("马化腾", "创立", "腾讯"),
            ("马云", "创立", "阿里巴巴"),
            ("任正非", "创立", "华为"),
        }

    def auto_label(self, sentences):
        """自动标注语料"""
        labeled_data = []

        for sent in sentences:
            for e1, rel, e2 in self.kb_facts:
                if e1 in sent and e2 in sent:
                    labeled_data.append({
                        "sentence": sent,
                        "entity1": e1,
                        "entity2": e2,
                        "relation": rel,
                        "confidence": "distant",  # 远程监督标注
                    })

        return labeled_data

# 测试
ds = DistantSupervision()
sentences = [
    "乔布斯与好友沃兹尼亚克一起在车库创立了苹果公司",
    "在乔布斯的带领下苹果公司推出了革命性的产品",
    "马化腾在深圳创立了腾讯公司",
    "马云退休后辞去了阿里巴巴董事长的职务",
]

labeled = ds.auto_label(sentences)
print("远程监督自动标注结果:")
for item in labeled:
    print(f"\n  句子: {item['sentence']}")
    print(f"  三元组: ({item['entity1']}, {item['relation']}, {item['entity2']})")
    print(f"  标注来源: {item['confidence']}")

print("\n⚠️ 远程监督的问题:")
print("  - '马云退休后辞去了阿里巴巴董事长的职务'被标注为'创立'关系 → 标签噪声!")
print("  - 解决:多实例学习(MIL)、降噪方法、注意力机制选择可靠句子")

7. 实战:构建领域知识图谱

Python
"""
实战项目:从新闻文本构建科技领域知识图谱
"""

class TechKGBuilder:
    """科技领域知识图谱构建器"""

    def __init__(self):
        self.kg = KnowledgeGraph()
        self.ner_extractor = self._build_ner()
        self.re_extractor = self._build_re()

    def _build_ner(self):
        """构建NER提取器(基于规则)"""
        import re
        patterns = {
            "ORG": re.compile(r'([\u4e00-\u9fa5]+(?:公司|集团|科技|研究院|大学|实验室))'),
            "PER": re.compile(r'([\u4e00-\u9fa5]{2,4})(?:表示|说|认为|指出|创立|担任|就任)'),
            "PRODUCT": re.compile(r'([\u4e00-\u9fa5]*[a-zA-Z]+[\u4e00-\u9fa5a-zA-Z0-9]*)'),
        }
        return patterns

    def _build_re(self):
        """构建关系提取器"""
        import re
        patterns = {
            "创立": re.compile(r'([\u4e00-\u9fa5]+)创立了?([\u4e00-\u9fa5]+(?:公司|集团))'),
            "发布": re.compile(r'([\u4e00-\u9fa5]+(?:公司|集团))发布了?([\u4e00-\u9fa5a-zA-Z0-9]+)'),
            "收购": re.compile(r'([\u4e00-\u9fa5]+(?:公司|集团))收购了?([\u4e00-\u9fa5a-zA-Z]+(?:公司)?)'),
            "投资": re.compile(r'([\u4e00-\u9fa5]+(?:公司|集团))投资了?([\u4e00-\u9fa5a-zA-Z]+)'),
        }
        return patterns

    def process_text(self, text):
        """处理单条文本,提取知识"""
        extracted = {"entities": [], "relations": []}

        # NER
        for etype, pattern in self.ner_extractor.items():
            for match in pattern.finditer(text):
                entity = match.group(1)
                if len(entity) >= 2:
                    extracted["entities"].append({"name": entity, "type": etype})
                    self.kg.add_entity(entity, etype)

        # 关系抽取
        for rel_type, pattern in self.re_extractor.items():
            for match in pattern.finditer(text):
                head = match.group(1)
                tail = match.group(2)
                extracted["relations"].append((head, rel_type, tail))
                self.kg.add_relation(head, rel_type, tail)

        return extracted

    def build_from_texts(self, texts):
        """从文本集合构建知识图谱"""
        all_extracted = []
        for text in texts:
            result = self.process_text(text)
            all_extracted.append(result)
        return all_extracted

# 构建知识图谱
builder = TechKGBuilder()

news_texts = [
    "马斯克创立了SpaceX公司和特斯拉公司",
    "苹果公司发布了iPhone15和MacBook新品",
    "微软公司收购了暴雪公司",
    "腾讯公司投资了快手科技",
]

results = builder.build_from_texts(news_texts)

print("="*50)
print("科技领域知识图谱构建结果")
print("="*50)

for text, result in zip(news_texts, results):
    print(f"\n📰 {text}")
    if result["entities"]:
        print(f"   实体: {[(e['name'], e['type']) for e in result['entities']]}")
    if result["relations"]:
        print(f"   关系: {result['relations']}")

print(f"\n📊 知识图谱统计: {builder.kg.stats()}")
print(f"\n所有三元组:")
for h, r, t in builder.kg.to_triples():
    print(f"  ({h}, {r}, {t})")

8. 面试要点

🔑 面试高频考点

考点1:Pipeline vs 联合抽取的优缺点?

Text Only
✅ 标准答案要点:
Pipeline (分步):
- 流程:先NER → 再对实体对做关系分类
- 优点:模块化,每个子任务可以独立优化
- 缺点:误差传递(NER错误会影响RE)

联合抽取 (Joint):
- 流程:同时抽取实体和关系
- 优点:避免误差传递,实体和关系互相增强
- 缺点:模型更复杂,训练更难

实际选择:
- 数据少/类型简单 → Pipeline
- 追求最佳效果 → 联合抽取
- 零样本/少样本 → 大模型Prompt

考点2:远程监督的噪声问题如何解决?

Text Only
✅ 标准答案要点:
1. 多实例学习(MIL):将同一实体对的多个句子看作一个bag
2. 注意力降噪:AT-LEAST-ONE假设 + 句子级注意力选择可靠句子
3. 强化学习选择:用RL agent选择有用训练句子
4. 知识蒸馏:用大模型标注数据替代远程监督

考点3:知识图谱有哪些下游应用?

Text Only
✅ 标准答案要点:
1. 知识问答(KBQA):基于知识图谱回答问题
2. 推荐系统:利用图谱中的关系增强推荐
3. 搜索引擎:Google Knowledge Panel
4. 辅助NLP任务:实体链接、指代消解
5. RAG增强:为大模型提供结构化知识

9. 练习题

📝 基础题

  1. 解释关系抽取中Pipeline方法和联合方法的区别。

答案Pipeline方法:分步串行——先NER识别实体,再对实体对做关系分类。优点是各模块独立训练、灵活可替换;缺点是误差传播(NER错误传递到关系抽取)、无法利用任务间交互信息。联合方法:一个模型同时学习实体识别和关系抽取,共享底层表示。优点是能捕捉实体和关系的相互依赖(如知道有"出生于"关系有助于判断实体类型),减少误差传播;缺点是模型设计复杂、训练难度大。目前联合方法是主流趋势。

  1. 什么是远程监督?它的核心假设和局限性是什么?

答案远程监督利用已有知识库(如Wikidata)对齐原始文本来自动标注关系训练数据。核心假设:若知识库中存在三元组(实体A, 关系r, 实体B),则任何同时提到A和B的句子都表达关系r。局限性:①假设过强:同时提到两实体的句子不一定表达该关系,导致大量噪声标签;②知识库不完整:导致假阴例;③关系偏置:高频实体对容易被过度关联。缓解方法包括多实例学习、注意力去噪等。

💻 编程题

  1. 实现一个完整的中文关系抽取系统(使用规则或BERT)。
  2. 从给定的新闻语料中构建一个小型知识图谱。
  3. 实现TransE知识图谱嵌入模型的训练。

🔬 思考题

  1. 在大模型时代,传统的信息抽取方法还有必要吗?大模型在IE任务中的优劣势是什么?

答案:仍有必要。大模型优势:零样本/少样本能力强;Prompt灵活定义抽取schema;理解复杂语境。大模型劣势:①结构化输出不稳定,可能格式不一致或产生幻觉;②大规模文档抽取成本和延迟高;③垂直领域精度不及专用微调模型;④难以严格遵循预定义schema。最佳实践:大模型适合快速原型和少样本场景;生产系统用专用模型保证精度和效率,大模型辅助数据标注和难例处理。


✅ 自我检查清单

Text Only
□ 我理解信息抽取的主要任务
□ 我知道Pipeline和联合抽取方法的区别
□ 我能实现简单的关系抽取
□ 我理解事件抽取的框架
□ 我知道知识图谱的构建流程
□ 我理解远程监督的原理和问题
□ 我完成了至少3道练习题

📚 延伸阅读

  1. Distant Supervision for Relation Extraction
  2. TransE论文: Translating Embeddings for Modeling Multi-relational Data
  3. OpenIE综述
  4. 中文开放知识图谱OpenKG

下一篇09-问答系统 — 从检索式到生成式问答