NLP中的粒度问题

语言学基础知识

语音学和语音体系

  • 语音学 (Phonetics):音流无争议的物理学
  • 语音体系 (Phonology):假定了一组或多组独特的、分类的单元
    • 音素 (phoneme) 或独特的特征
    • 是一种普遍的类型学,但具有特殊的语言实现
    • 分类感知的最佳例子就是语音体系
    • 音位差异缩小,音素之间的放大

词法:词类

  • 词素 (morphemes) 是最小的语义单位
  • 深度学习中的形态学研究:
    • 递归神经网络的尝试 (Luong, Socher, & Manning 2013)
    • 处理更大词汇量的方法:大多数看不见的单词是新的形态
  • 声音本身在语言中没有意义
  • parts of words 是音素的下一级的形态学,是具有意义的最低级别
  • 替代方法:
    • 使用字符 n-grams
    • Wickelphones (Rumelhart & McClelland 1986)
    • Microsoft’s DSSM (Huang et al. 2013)
    • 使用卷积层的相关想法

书写系统中的单词

  • 书写系统在表达单词的方式上差异有大有小
    • 没有分词(如中文)
    • 大部分单词都是分开的:由单词组成句子
    • 附着词:分开的或连续的
    • 复合名词:分开的或连续的
  • 大多数深度学习NLP工作从语言的书面形式开始
    • 人类语言书写系统各不相同
    • 各种语言的字符是不同的

粒度问题

为什么需要更细粒度的模型?

  • 需要处理数量很大的开放词汇
  • 丰富的形态
  • 音译(特别是名字)
  • 非正式的拼写

粒度级别

  1. 词级别(Word-level)

    • 优点:语义明确,处理简单
    • 缺点:词表大,无法处理OOV问题
  2. 字符级别(Character-level)

    • 优点:可以处理任意词,词表小
    • 缺点:序列长,训练慢
  3. 子词级别(Subword-level)

    • 优点:平衡了词级别和字符级别的优缺点
    • 缺点:需要额外的分词算法

字符级模型

  1. 词嵌入可以由字符嵌入组成:

    • 为未知单词生成嵌入
    • 相似的拼写共享相似的嵌入
    • 解决OOV问题
  2. 连续语言可以作为字符处理:

    • 所有语言处理均建立在字符序列上
    • 不考虑word-level
    • 深度学习模型可以存储和构建来自多个字母组的含义表示

基于字符的模型构建方法

字符级构建单词级

  • Learning Character-level Representations for Part-of-Speech Tagging (Dos Santos and Zadrozny 2014)
    • 对字符进行卷积以生成单词嵌入
    • 为PoS标签使用固定窗口的词嵌入
    • 论文详解:
      • 创新点:首次提出使用字符级CNN来构建词表示
      • 模型架构:
        • 字符级嵌入层:将每个字符映射到向量空间
        • 卷积层:捕捉字符n-gram特征
        • 最大池化层:提取最显著的特征
        • 词嵌入层:将字符级特征组合成词表示
      • 实验结果:
        • 在词性标注任务上取得了state-of-the-art结果
        • 对罕见词和未知词的处理效果显著提升
        • 相比传统词嵌入方法,参数量更少

基于字符的LSTM构建单词表示

  • 使用Bi-LSTM构建单词表示
  • 可以捕捉字符级别的上下文信息
  • 论文详解:
    • 模型架构:
      • 前向LSTM:从左到右处理字符序列
      • 后向LSTM:从右到左处理字符序列
      • 双向特征拼接:结合两个方向的上下文信息
    • 优势:
      • 能够捕捉长距离依赖
      • 对词形变化有更好的建模能力
      • 可以处理任意长度的词

Character-Aware Neural Language Models

  • 动机:
    • 构建强大的、健壮的语言模型
    • 编码子单词关联性
    • 解决罕见字问题
    • 用更少参数获得可比较的表达性
  • 技术方法:
    • 字符级别嵌入输入
    • CNN + 高速网络 + LSTM
    • 使用层次化Softmax处理大词汇表
    • 使用truncated backprop through time训练
  • 论文详解:
    • 模型架构详解:
      1. 字符级嵌入层:
        • 将每个字符映射到低维向量空间
        • 使用预训练的字符嵌入或随机初始化
      2. 卷积层:
        • 使用不同大小的卷积核捕捉不同长度的字符n-gram
        • 每个卷积核输出一个特征图
      3. 高速网络(Highway Network):
        • 控制信息流动
        • 允许原始特征和转换特征之间的平衡
        • 使用门控机制调节信息流
      4. LSTM层:
        • 处理序列信息
        • 捕捉长期依赖
      5. 输出层:
        • 使用层次化Softmax减少计算复杂度
        • 支持大规模词汇表
    • 训练策略:
      • 使用truncated backprop through time
      • 采用dropout防止过拟合
      • 使用梯度裁剪防止梯度爆炸
    • 实验结果:
      • 在多个语言模型基准测试中取得优异结果
      • 对罕见词的处理效果显著提升
      • 参数量比传统词级模型少30-50%

纯字符级模型应用

句子分类

  • 使用非常深的卷积网络
  • Conneau, Schwenk, Lecun, Barrault. EACL 2017
  • 通过深度卷积堆叠获得强大结果
  • 论文详解:
    • 模型架构:
      1. 字符级嵌入层
      2. 多层卷积网络:
        • 使用小卷积核(3x3)
        • 逐层增加通道数
        • 使用残差连接
      3. 全局池化层
      4. 全连接分类层
    • 创新点:
      • 首次在文本分类中应用超深卷积网络
      • 使用残差连接解决深层网络的训练问题
      • 完全基于字符级输入,无需分词
    • 实验结果:
      • 在多个文本分类数据集上达到state-of-the-art
      • 对多语言任务有很好的泛化能力
      • 训练速度快,推理效率高

机器翻译系统

  • 初期效果不理想 (Vilaret al., 2007; Neubiget al., 2013)
  • 只有decoder初步成功 (JunyoungChung, KyunghyunCho, YoshuaBengio. arXiv 2016)
  • 后来出现不错的结果:
    • Wang Ling, Isabel Trancoso, Chris Dyer, Alan Black, arXiv 2015
    • Thang Luong, Christopher Manning, ACL 2016
    • Marta R. Costa-Jussà, José A. R. Fonollosa, ACL 2016
  • 论文详解:
    • 早期尝试(2007-2013):
      • 主要问题:序列过长,训练困难
      • 计算资源限制导致效果不理想
    • 突破性进展(2015-2016):
      1. Wang Ling et al. (2015):
        • 创新:使用字符级LSTM编码器
        • 优势:更好地处理形态丰富的语言
        • 结果:在多个语言对上取得显著提升
      2. Luong & Manning (2016):
        • 创新:纯字符级seq2seq模型
        • 技术细节:
          • 使用多层LSTM
          • 引入注意力机制
          • 采用复制机制处理罕见词
        • 结果:在WMT15英捷翻译任务中达到最佳效果
      3. Costa-Jussà & Fonollosa (2016):
        • 创新:混合字符-词级模型
        • 优势:平衡效率和效果
        • 结果:在多个语言对上取得稳定提升

English-Czech WMT 2015 Results

  • Luong和Manning测试了纯字符级seq2seq (LSTM) NMT系统
  • 在单词级基线上运行良好
  • 对于UNK,使用single word translation或copy from source
  • 字符级模型效果更好但训练慢(需要3周)
  • 序列长度变为以前的数倍(约七倍)
  • 论文详解:
    • 实验设置:
      • 数据集:WMT15英捷翻译数据集
      • 模型配置:
        • 8层LSTM编码器-解码器
        • 使用注意力机制
        • 采用残差连接
      • 训练细节:
        • 使用Adam优化器
        • 采用梯度裁剪
        • 使用dropout防止过拟合
    • 主要发现:
      1. 性能优势:
        • BLEU分数提升2-3个点
        • 对罕见词的处理效果显著提升
        • 翻译质量更加稳定
      2. 计算开销:
        • 训练时间增加(约3周)
        • 序列长度增加(约7倍)
        • 内存消耗显著增加
      3. 模型特点:
        • 无需分词
        • 可以处理任意词
        • 对形态变化有更好的建模能力

无显式分割的完全字符级神经机器翻译

  • Jason Lee, KyunghyunCho, Thomas Hoffmann. 2017
  • 编码器使用字符级输入
  • 解码器是字符级的GRU
  • 论文详解:
    • 创新点:
      • 完全基于字符的端到端翻译系统
      • 无需显式分词
      • 使用GRU替代LSTM
    • 模型架构:
      1. 编码器:
        • 字符级GRU
        • 双向处理
        • 多层堆叠
      2. 解码器:
        • 字符级GRU
        • 注意力机制
        • 复制机制
    • 技术细节:
      • 使用子词单元初始化
      • 采用课程学习策略
      • 使用beam search进行解码
    • 实验结果:
      • 在多个语言对上取得competitive结果
      • 训练速度比LSTM版本快
      • 对罕见词的处理效果显著提升

LSTM seq2seq模型中的深度影响

  • Revisiting Character-Based Neural Machine Translation with Capacity and Compression. 2018
  • 在LSTM-seq2seq模型中,随着深度增加,特征越强
  • 在捷克语等复杂语言中效果明显,英语和法语收效甚微
  • 模型较小时,word-level更佳
  • 模型较大时,character-level更佳
  • 论文详解:
    • 研究目标:
      • 探索模型深度对字符级NMT的影响
      • 比较不同语言对上的表现差异
      • 分析模型规模与粒度的关系
    • 实验设计:
      1. 模型变体:
        • 浅层(4层)vs 深层(8层)
        • 字符级 vs 词级
        • 不同参数规模
      2. 语言对:
        • 英语-捷克语(形态丰富)
        • 英语-法语(相对简单)
      3. 评估指标:
        • BLEU分数
        • 训练时间
        • 推理速度
    • 主要发现:
      1. 深度影响:
        • 深层模型特征提取能力更强
        • 残差连接对训练至关重要
        • 注意力机制效果随深度增加而提升
      2. 语言特性:
        • 形态丰富语言受益更多
        • 简单语言差异不明显
      3. 规模效应:
        • 小模型:词级更高效
        • 大模型:字符级优势明显
    • 实践建议:
      • 根据语言特性选择粒度
      • 考虑计算资源限制
      • 平衡模型规模和训练效率

子词模型Subword Models

为什么需要?

在自然语言处理中,我们经常遇到以下问题:

  • 词表大小问题:语言中的词汇量非常大,如果使用词级别的模型,词表会变得非常庞大
    • 例如:英语词典通常包含超过100,000个词
    • 专业领域(如医学、法律)可能有更多专业术语
    • 新词不断产生(如网络用语、新科技词汇)
  • 未知词(OOV)问题:测试集中可能出现训练集中没有的词
    • 例如:训练集中有”running”,但测试集出现”jogging”
    • 新出现的网络用语或流行语
    • 专业术语或罕见词
  • 词形变化问题:同一个词可能有多种形式(如:run, runs, running)
    • 时态变化:walk, walked, walking
    • 单复数变化:book, books
    • 词性变化:happy, happiness, happily

子词模型通过将词分解成更小的单元来解决这些问题。

两种趋势

1.与 word 级模型相同的架构

  • 但是使用更小的单元: word pieces
  • [Sennrich, Haddow, Birch, ACL’16a], [Chung, Cho, Bengio, ACL’16].
    2.混合架构
  • 主模型使用单词,其他使用字符级
  • [Costa-Jussà& Fonollosa, ACL’16], [Luong & Manning, ACL’16].

常见子词模型

Byte Pair Encoding (BPE)

概念

BPE是一种数据压缩算法,在NLP中用于构建子词单元。其工作流程:

  1. 初始化:将所有词分解成字符序列

    • 例如:”low” → “l o w”
    • 每个字符作为一个基本单元
  2. 迭代:

    • 统计所有相邻字符对的出现频率
    • 将最频繁出现的字符对合并成一个新的子词单元
    • 更新词表

BPE的优势:

  • 可以处理未见过的词
  • 能够捕捉常见的词根和词缀
  • 词表大小可控

详细实现

  1. 预处理阶段:

    • 将所有词转换为字符序列
    • 在词尾添加特殊标记(如</w>
    • 统计词频
  2. 合并过程:

    • 计算所有相邻字符对的频率
    • 选择频率最高的对进行合并
    • 更新词表和所有词的表示
    • 重复直到达到预设的合并次数或词表大小
  3. 应用阶段:

    • 对新词进行贪婪匹配
    • 从最长子词开始匹配
    • 如果无法完全匹配,回退到字符级
  4. 优化策略:

    • 使用优先队列加速频率统计
    • 采用哈希表存储合并规则
    • 实现增量更新机制
  5. 应用场景:

    • 机器翻译:处理未知词和罕见词
    • 文本分类:提高对罕见词的处理能力
    • 词向量:生成更细粒度的词表示

具体示例

  1. 假设我们有以下训练数据:
1
2
3
4
"low" 出现5次
"lower" 出现2次
"newest" 出现6次
"widest" 出现3次
  1. 初始词表(字符级):
1
l, o, w, e, r, n, s, t, i, d
  1. 统计相邻字符对频率:
1
2
3
4
5
6
7
8
9
10
lo: 7次 (low:5 + lower:2)
ow: 7次 (low:5 + lower:2)
we: 2次 (lower:2)
er: 2次 (lower:2)
ne: 6次 (newest:6)
es: 9次 (newest:6 + widest:3)
st: 9次 (newest:6 + widest:3)
wi: 3次 (widest:3)
id: 3次 (widest:3)
de: 3次 (widest:3)
  1. 第一次合并(选择频率最高的”es”):
1
2
3
4
5
6
词表更新:l, o, w, e, r, n, s, t, i, d, es
词更新:
"low" → "l o w"
"lower" → "l o w e r"
"newest" → "n e w es t"
"widest" → "w i d es t"
  1. 第二次合并(选择频率最高的”st”):
1
2
3
4
5
6
词表更新:l, o, w, e, r, n, s, t, i, d, es, st
词更新:
"low" → "l o w"
"lower" → "l o w e r"
"newest" → "n e w es st"
"widest" → "w i d es st"
  1. 第三次合并(选择频率最高的”lo”):
1
2
3
4
5
6
词表更新:l, o, w, e, r, n, s, t, i, d, es, st, lo
词更新:
"low" → "lo w"
"lower" → "lo w e r"
"newest" → "n e w es st"
"widest" → "w i d es st"

最终词表包含:

  • 原始字符:l, o, w, e, r, n, s, t, i, d
  • 合并的子词:es, st, lo

这样,我们就得到了一个可以处理未知词的子词词表。例如,如果遇到新词”lowest”,它可以被分解为”lo w es st”,这些子词都在我们的词表中。


WordPiece

概念

WordPiece是BERT等模型使用的子词模型,与BPE的主要区别:

  • 使用语言模型分数而不是频率来决定合并
    • 计算合并后的语言模型似然度
    • 选择使似然度最大的合并
  • 使用”##”标记表示子词是词的一部分
    • 帮助模型识别子词的位置
    • 区分词首和词中/词尾

具体示例

  1. 假设我们有以下训练数据:
1
2
3
4
"playing" 出现10次
"played" 出现8次
"player" 出现6次
"playful" 出现4次
  1. 初始词表(字符级):
1
p, l, a, y, i, n, g, e, d, r, f, u
  1. 计算语言模型分数:
1
2
3
4
5
原始似然度:
P("playing") = P(p) * P(l) * P(a) * P(y) * P(i) * P(n) * P(g)
P("played") = P(p) * P(l) * P(a) * P(y) * P(e) * P(d)
P("player") = P(p) * P(l) * P(a) * P(y) * P(e) * P(r)
P("playful") = P(p) * P(l) * P(a) * P(y) * P(f) * P(u) * P(l)
  1. 第一次合并(选择”play”):
1
2
3
4
5
6
词表更新:p, l, a, y, i, n, g, e, d, r, f, u, play
词更新:
"playing" → "play ##ing"
"played" → "play ##ed"
"player" → "play ##er"
"playful" → "play ##ful"
  1. 第二次合并(选择”ing”):
1
2
3
4
5
6
词表更新:p, l, a, y, i, n, g, e, d, r, f, u, play, ing
词更新:
"playing" → "play ##ing"
"played" → "play ##ed"
"player" → "play ##er"
"playful" → "play ##ful"
  1. 第三次合并(选择”ed”):
1
2
3
4
5
6
词表更新:p, l, a, y, i, n, g, e, d, r, f, u, play, ing, ed
词更新:
"playing" → "play ##ing"
"played" → "play ##ed"
"player" → "play ##er"
"playful" → "play ##ful"

最终词表包含:

  • 原始字符:p, l, a, y, i, n, g, e, d, r, f, u
  • 合并的子词:play, ing, ed

这样,我们就得到了一个可以处理未知词的子词词表。例如,如果遇到新词”playable”,它可以被分解为”play ##able”,其中”play”是词首,”able”是词中/词尾。

WordPiece的特点:

  • 更适合处理形态丰富的语言
  • 能够更好地处理前缀和后缀
  • 在预训练语言模型中表现优异

WordPiece的详细实现:

  1. 初始化:

    • 将所有词分解为字符
    • 计算字符级语言模型
    • 建立初始词表
  2. 合并策略:

    • 计算每对相邻子词的合并分数
    • 分数 = 合并后的似然度 - 合并前的似然度
    • 选择分数最高的对进行合并
  3. 训练过程:

    • 使用最大似然估计训练语言模型
    • 采用期望最大化算法优化合并规则
    • 动态调整词表大小
  4. 应用特点:

    • 优先匹配最长子词
    • 使用特殊标记处理未知字符
    • 支持多语言处理
  5. 性能优化:

    • 使用缓存加速匹配过程
    • 实现并行处理机制
    • 支持增量更新
  6. 应用场景:

    • 预训练语言模型(如BERT、RoBERTa)
    • 多语言处理
    • 跨语言迁移学习

FastText

论文

官网

FastText是Facebook AI Research (FAIR)开发的模型,它也是一种子词模型,但采用了不同的方法:

基本概念

  • 用于高效学习词向量和文本分类
  • 主要特点:
    • 子词信息:将单词分解为字符n-gram
    • 考虑单词的形态学特征
    • 能够处理罕见词和新词
    • 支持多种语言
    • 训练速度快
    • 内存效率高
  1. 向量计算:
    • 单词向量 = 所有子词向量的和
    • 使用哈希技巧减少内存使用
    • 共享子词表示

详细实现

  1. 子词生成:

    • 使用滑动窗口生成n-gram
    • 支持不同长度的n-gram(3-6)
    • 添加词边界标记
  2. 向量计算:

    • 使用哈希函数映射n-gram
    • 计算n-gram向量
    • 聚合得到词向量
  3. 训练优化:

    • 使用负采样加速训练
    • 实现层次化softmax
    • 支持多线程训练
  4. 内存优化:

    • 使用哈希技巧减少内存
    • 实现稀疏矩阵存储
    • 支持模型压缩
  5. 多语言支持:

    • 统一的字符编码
    • 语言特定的预处理
    • 跨语言迁移学习
  6. 应用场景:

    • 文本分类:
      • 情感分析
      • 主题分类
      • 垃圾邮件检测
    • 词向量:
      • 语义相似度计算
      • 词类比任务
      • 跨语言迁移
    • 性能特点:
      • 训练速度快
      • 内存效率高
      • 支持多语言
  7. 实际应用:

    • 预训练模型:
      • 支持157种语言
      • 提供预训练词向量
      • 可用于迁移学习
    • 工具支持:
      • 提供Python接口
      • 支持命令行工具
      • 易于集成到现有系统

具体示例

  1. 假设我们有以下单词:
1
2
3
"where" 出现10次
"there" 出现8次
"here" 出现6次
  1. 生成3-gram子词:
1
2
3
4
5
6
7
8
9
10
11
"where"的3-gram:
- <wh, whe, her, ere, re>
- 加上词边界:<where, wh, whe, her, ere, re, </where>

"there"的3-gram:
- <th, the, her, ere, re>
- 加上词边界:<there, th, the, her, ere, re, </there>

"here"的3-gram:
- <he, her, ere, re>
- 加上词边界:<here, he, her, ere, re, </here>
  1. 构建词向量:
1
2
3
4
5
6
7
8
"where"的词向量 = 所有子词向量的和:
v("where") = v(<where>) + v(<wh>) + v(<whe>) + v(<her>) + v(<ere>) + v(<re>) + v(</where>)

"there"的词向量 = 所有子词向量的和:
v("there") = v(<there>) + v(<th>) + v(<the>) + v(<her>) + v(<ere>) + v(<re>) + v(</there>)

"here"的词向量 = 所有子词向量的和:
v("here") = v(<here>) + v(<he>) + v(<her>) + v(<ere>) + v(<re>) + v(</here>)
  1. 共享子词表示:
1
2
3
4
5
6
注意到"where"、"there"和"here"共享一些子词:
- "her":出现在所有三个词中
- "ere":出现在所有三个词中
- "re":出现在所有三个词中

这使得这些词在向量空间中更接近,因为它们共享相同的子词特征。
  1. 处理未知词:
1
2
3
4
5
6
7
8
9
10
假设遇到新词"everywhere":
1. 生成3-gram:
<ev, eve, ver, ery, ryw, ywh, whe, her, ere, re>
加上词边界:<everywhere, ev, eve, ver, ery, ryw, ywh, whe, her, ere, re, </everywhere>

2. 计算词向量:
v("everywhere") = 所有子词向量的和

3. 由于"everywhere"与"where"共享子词"whe"、"her"、"ere"、"re",
它的向量表示会与"where"有一定的相似性。

这种方法的优势:

  1. 可以处理未知词:通过共享子词表示
  2. 捕捉形态学特征:相似的词会有相似的子词
  3. 内存效率高:通过共享子词表示减少参数量
  4. 训练速度快:可以并行处理子词

对比

  • FastText vs BPE:

    • FastText使用固定长度的n-gram
    • BPE动态学习子词单元
    • FastText更适合处理形态学特征
    • BPE更适合处理未知词
  • FastText vs WordPiece:

    • FastText不考虑子词的位置信息
    • WordPiece使用特殊标记表示位置
    • FastText训练更快
    • WordPiece在预训练模型中表现更好

混合字符与词粒度的模型

混合NMT

  • 混合高效结构
  • 翻译大部分是单词级别
  • 只在需要时进入字符级别
  • 使用复制机制,产生超过2个点的BLEU改进
  • 单词级别(4层)
  • 端到端训练8层LSTM

二级解码

  • 单词级别的集束搜索
  • 字符级别的集束搜索(遇到UNK时)
  • 混合模型与字符级模型比较:
    • 纯字符级模型能有效使用字符序列作为条件上下文
    • 混合模型提供字符级隐层表示,但未获得更低级表示

English - Czech Results

  • 使用WMT’15数据训练(12M句子对)
  • 新闻测试2015
  • 30倍数据
  • 3个系统
  • 大型词汇+复制机制
  • 达到先进效果

Sample English-czech translations

  • 翻译效果很好
  • 基于字符:错误的名称翻译
  • 基于单词:对齐不正确
  • 基于字符的混合:diagnóze的正确翻译
  • 基于单词:特征复制失败
  • 混合:正确,11-year-old-jedenactileta
  • 错误:Shani Bartova

单词嵌入中的字符应用

  • 用于单词嵌入和单词形态学的联合模型(Cao and Rei 2016)
  • 与w2v目标相同,但使用字符
  • 双向LSTM计算单词表示
  • 模型试图捕获形态学
  • 模型可以推断单词的词根



指代消解Coreference Resolution

语言学基础

基本概念

  1. 共指(Coreference)

    • 两个指代指向同一实体
    • 例如:”Barack Obama”和”Obama”
  2. 回指(Anaphora)

    • 下文的词返指或代替上文的词
    • anaphor的解释依赖于antecedent(先行词)
    • 例如:”Barack Obama said he would sign the bill”

指代类型

  1. 前指代(Anaphora)

    • 通常先行词在回指词之前
  2. 后指代(Cataphora)

    • 先行词在回指词之后
  3. 桥接回指(Bridging Anaphora)

    • 例如:”We went to see a concert last night. The tickets were really expensive.”

概念

定义

指代消解是识别文本中所有指向同一现实世界实体的指代(mentions)的任务。例如:

1
小明昨天买了一本书。他很喜欢它。

这里”他”指代”小明”,”它”指代”书”。

类型

  1. 代词指代:

    • 人称代词:他、她、它
    • 指示代词:这、那
    • 关系代词:谁、什么
  2. 名词指代:

    • 同义表达:总统、国家元首
    • 上位词:狗、宠物
    • 部分指代:车轮、车
  3. 零指代:

    • 省略主语:去吃饭了(省略了”我”)
    • 省略宾语:把书放在桌子上(省略了”它”)

具体示例:

  1. 代词指代示例:
1
2
3
4
5
6
小明昨天买了一本书。他很喜欢它。
- "他"指代"小明"
- "它"指代"一本书"

李华和王芳是好朋友。她们经常一起逛街。
- "她们"指代"李华和王芳"
  1. 名词指代示例:
1
2
3
4
5
美国总统拜登访问了中国。这位领导人受到了热烈欢迎。
- "这位领导人"指代"美国总统拜登"

小明养了一只金毛。这只宠物非常聪明。
- "这只宠物"指代"金毛"
  1. 零指代示例:
1
2
3
4
5
小明去图书馆了。(省略了"小明")
- 零指代:"去"的主语是"小明"

把书放在桌子上。(省略了"把"的宾语"书")
- 零指代:"把"的宾语是"书"

挑战

  1. 语言歧义:

    • 代词可能指向多个可能的先行词
    • 上下文信息的重要性
  2. 长距离依赖:

    • 指代词和先行词可能相距很远
    • 需要理解整个文档的上下文
  3. 隐式指代:

    • 零指代(省略主语)
    • 部分指代

具体示例:

  1. 语言歧义示例:
1
2
3
4
小明和小红是好朋友。他经常帮助她。
- "他"可能指代"小明"
- "她"可能指代"小红"
- 需要根据上下文确定具体指代关系
  1. 长距离依赖示例:
1
2
3
4
小明昨天去图书馆借了一本书。他花了一个小时挑选。最后,他选择了这本小说。回到家后,他开始阅读它。
- "它"指代"这本小说"
- "这本小说"指代"书"
- 指代关系跨越了多个句子
  1. 隐式指代示例:
1
2
3
去吃饭了。(省略了主语"我")
把书放在桌子上。(省略了宾语"它")
- 需要根据上下文推断省略的成分

指代消解的两个步骤

  1. 指代检测(Mention Detection)

    • 相对简单的任务
    • 识别文本中的指代项
    • 包括代词、命名实体和名词短语的检测
  2. 指代聚类(Coreference Clustering)

    • 较难的任务
    • 将指向同一实体的指代项聚类
    • 需要理解语义关系和上下文

具体示例:

  1. 指代检测示例:
1
2
3
4
5
小明昨天买了一本书。他很喜欢它。
检测到的指代项:
- 命名实体:"小明"
- 名词短语:"一本书"
- 代词:"他"、"它"
  1. 指代聚类示例:
1
2
3
4
小明昨天买了一本书。他很喜欢它。
聚类结果:
- 聚类1:{"小明", "他"}
- 聚类2:{"一本书", "它"}

指代消解模型

传统方法:霍布斯朴素算法

  1. 基于规则的代词回指消解
  2. 使用句法树结构
  3. 按照特定规则遍历树结构寻找先行词

具体示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
输入文本:
小明昨天买了一本书。他很喜欢它。

1. 构建句法树:
- 第一句:小明(主语) 昨天(时间) 买了(谓语) 一本书(宾语)
- 第二句:他(主语) 很(程度) 喜欢(谓语) 它(宾语)

2. 应用规则:
- 规则1:代词"他"优先指代前一句的主语
- 规则2:代词"它"优先指代前一句的宾语

3. 消解结果:
- "他" → "小明"
- "它" → "一本书"

指代对模型(Mention Pair Model)

  1. 训练二元分类器
  2. 为每对指代分配相关概率
  3. 使用阈值和传递闭包进行聚类

具体示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
输入文本:
小明昨天买了一本书。他很喜欢它。

1. 检测指代项:
- m1: "小明"
- m2: "一本书"
- m3: "他"
- m4: "它"

2. 计算指代对概率:
P(m1, m3) = 0.9 # 小明-他
P(m2, m4) = 0.8 # 一本书-它
P(m1, m4) = 0.1 # 小明-它
P(m2, m3) = 0.2 # 一本书-他

3. 应用阈值(假设阈值为0.5):
- 保留:m1-m3, m2-m4
- 丢弃:m1-m4, m2-m3

4. 聚类结果:
- 聚类1:{"小明", "他"}
- 聚类2:{"一本书", "它"}

指代排序模型(Mention Ranking Model)

  1. 为每个指代预测一个最佳先行词
  2. 使用softmax确保概率和为1
  3. 只添加得分最高的共指链接

具体示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
输入文本:
小明昨天买了一本书。他很喜欢它。

1. 检测指代项:
- m1: "小明"
- m2: "一本书"
- m3: "他"
- m4: "它"

2. 计算每个指代的最佳先行词:
P(m3|m1) = 0.9 # 他-小明
P(m3|m2) = 0.1 # 他-一本书
P(m4|m1) = 0.2 # 它-小明
P(m4|m2) = 0.8 # 它-一本书

3. 选择最佳先行词:
- m3("他") → m1("小明")
- m4("它") → m2("一本书")

4. 聚类结果:
- 聚类1:{"小明", "他"}
- 聚类2:{"一本书", "它"}

基于聚类的模型

  1. 使用自下而上的聚类方法
  2. 为每个指代对生成向量表示
  3. 使用模型评分聚类合并

具体示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
输入文本:
小明昨天买了一本书。他很喜欢它。

1. 初始聚类:
- 聚类1:{"小明"}
- 聚类2:{"一本书"}
- 聚类3:{"他"}
- 聚类4:{"它"}

2. 计算聚类间相似度:
sim(聚类1, 聚类3) = 0.9 # 小明-他
sim(聚类2, 聚类4) = 0.8 # 一本书-它
sim(聚类1, 聚类4) = 0.1 # 小明-它
sim(聚类2, 聚类3) = 0.2 # 一本书-他

3. 合并最相似的聚类:
- 合并聚类1和聚类3
- 合并聚类2和聚类4

4. 最终聚类:
- 聚类1:{"小明", "他"}
- 聚类2:{"一本书", "它"}

神经模型方法

  1. 端到端神经指代消解
    • 使用双向LSTM编码文本
    • 使用注意力机制捕捉指代关系
    • 端到端训练,无需特征工程

具体示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
输入文本:
小明昨天买了一本书。他很喜欢它。

1. 文本编码:
- 使用BiLSTM编码每个词
- 得到每个词的上下文表示

2. 指代检测:
- 识别可能的指代项
- 计算每个指代项的表示

3. 指代关系预测:
- 使用注意力机制计算指代间关系
- 预测每个指代对的共指概率

4. 聚类结果:
- 聚类1:{"小明", "他"}
- 聚类2:{"一本书", "它"}
  1. 基于Transformer的模型
    • 使用预训练语言模型(如BERT)编码
    • 利用自注意力机制捕捉长距离依赖
    • 在OntoNotes数据集上取得最佳效果

具体示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
输入文本:
小明昨天买了一本书。他很喜欢它。

1. BERT编码:
- 输入:[CLS] 小明 昨天 买了 一本 书 [SEP] 他 很 喜欢 它 [SEP]
- 得到每个词的上下文表示

2. 指代检测:
- 识别可能的指代项
- 计算每个指代项的表示

3. 指代关系预测:
- 使用自注意力机制计算指代间关系
- 预测每个指代对的共指概率

4. 聚类结果:
- 聚类1:{"小明", "他"}
- 聚类2:{"一本书", "它"}
  1. 基于图神经网络的模型
    • 将指代关系建模为图结构
    • 使用GNN进行指代聚类
    • 能够更好地处理全局信息

具体示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
输入文本:
小明昨天买了一本书。他很喜欢它。

1. 构建图:
- 节点:每个可能的指代项
- 边:指代间的关系

2. 图表示:
- 节点特征:指代项的表示
- 边特征:指代间的关系表示

3. GNN处理:
- 消息传递
- 节点更新
- 边更新

4. 聚类结果:
- 聚类1:{"小明", "他"}
- 聚类2:{"一本书", "它"}

评估方法

评估指标

  1. MUC (Message Understanding Conference)

    • 基于链接的评估方法
    • 计算系统预测的链接与标准答案的匹配程度
    • 对长距离指代敏感
    • 公式:
      $MUC = \frac{\sum_{i=1}^{n} (|C_i| - |P_i|)}{\sum_{i=1}^{n} (|C_i| - 1)}$
      其中:
      • $C_i$ 是第i个标准聚类
      • $P_i$ 是系统预测的聚类
      • $|C_i|$ 表示聚类中的提及数量
      • $|P_i|$ 表示预测聚类中的提及数量
  2. CEAF (Constrained Entity-Alignment F-Measure)

    • 基于实体提及的评估方法
    • 使用最优二分图匹配计算相似度
    • 对实体边界敏感
    • 公式:
      $CEAF = \frac{2 \times P \times R}{P + R}$
      其中:
      • $P = \frac{\sum_{i=1}^{n} |C_i \cap P_i|}{\sum_{i=1}^{n} |P_i|}$ (精确率)
      • $R = \frac{\sum_{i=1}^{n} |C_i \cap P_i|}{\sum_{i=1}^{n} |C_i|}$ (召回率)
      • $|C_i \cap P_i|$ 表示正确匹配的提及数量
  3. LEA (Link-based Entity-Aware)

    • 基于链接的实体感知评估
    • 考虑实体提及的重要性
    • 对实体类型敏感
    • 公式:
      $LEA = \frac{\sum_{i=1}^{n} \frac{|C_i \cap P_i|}{|C_i|} \times w_i}{\sum_{i=1}^{n} w_i}$
      其中:
      • $w_i$ 是第i个聚类的权重
      • $|C_i \cap P_i|$ 是正确匹配的提及数量
      • $|C_i|$ 是标准聚类中的提及数量
  4. BCUBED

    • 基于提及的评估方法
    • 分别计算精确率和召回率
    • 对聚类质量敏感
    • 公式:
      $B^3 = \frac{2 \times P_{B^3} \times R_{B^3}}{P_{B^3} + R_{B^3}}$
      其中:
      • $P_{B^3} = \frac{1}{n} \sum_{i=1}^{n} \frac{|C_i \cap P_i|}{|P_i|}$ (精确率)
      • $R_{B^3} = \frac{1}{n} \sum_{i=1}^{n} \frac{|C_i \cap P_i|}{|C_i|}$ (召回率)
      • $n$ 是聚类的总数
  5. BLANC (Bilingual Evaluation Understudy)

    • 基于链接的评估方法
    • 考虑非共指关系
    • 对负例敏感
    • 公式:
      $BLANC = \frac{2 \times P_{BLANC} \times R_{BLANC}}{P_{BLANC} + R_{BLANC}}$
      其中:
      • $P_{BLANC} = \frac{TP}{TP + FP}$ (精确率)
      • $R_{BLANC} = \frac{TP}{TP + FN}$ (召回率)
      • TP:正确预测的非共指关系数
      • FP:错误预测的非共指关系数
      • FN:未预测的非共指关系数

实践工具

  1. Stanford CoreNLP

    • http://corenlp.run/
    • 在Annotations中选择coref
    • 使用示例:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      from stanfordcorenlp import StanfordCoreNLP
      nlp = StanfordCoreNLP('http://localhost:9000')
      text = "小明昨天买了一本书。他很喜欢它。"
      result = nlp.coref(text)
      print(result)
      # 输出:
      # {
      # "小明": ["他"],
      # "一本书": ["它"]
      # }
  2. Hugging Face

    • https://huggingface.co/coref/
    • 使用示例:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      from transformers import pipeline
      coref = pipeline("coref")
      text = "小明昨天买了一本书。他很喜欢它。"
      result = coref(text)
      print(result)
      # 输出:
      # {
      # "clusters": [
      # ["小明", "他"],
      # ["一本书", "它"]
      # ]
      # }
  3. AllenNLP

    • 提供预训练的指代消解模型
    • 支持自定义模型训练
    • 使用示例:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      from allennlp.predictors.predictor import Predictor
      predictor = Predictor.from_path("model.tar.gz")
      result = predictor.predict(document="小明昨天买了一本书。他很喜欢它。")
      print(result)
      # 输出:
      # {
      # "clusters": [
      # ["小明", "他"],
      # ["一本书", "它"]
      # ],
      # "document": ["小明", "昨天", "买了", "一本", "书", "。", "他", "很", "喜欢", "它", "。"]
      # }