CNNs BiLSTM CRF

CNNs-BiLSTM-CRF: 对一个通用的神经网络架构解码,用于为句子打标签。这个项目是关于一个通用的神经网络架构,它可以为句子打便签. 所提出的系统能够用于实体命名识别,语义分割标签并且可以在给定的小的训练集分割句子. 这个项目的实现是基于Mayu和Hovy2016年发表的一篇文章。

摘要

对一个通用的神经网络架构解码,用于为句子打标签。这个项目是关于一个通用的神经网络架构,它可以为句子打便签. 所提出的系统能够用于实体命名识别,语义分割标签并且可以在给定的小的训练集分割句子. 这个项目的实现是基于Mayu和Hovy2016年发表的一篇文章。

简介

​ 目前现有的很多系统在实际使用中都是专门针对某个单一任务量身定制的,这些任务活多多少的都需要一些人工的特征工程和针对某个任务的神经网络. Collobert等人在2011年呼吁并提出了一个中心化的架构. 一旦拥有中心化的架构,可以节省开发和调试的成本. 而这个项目就有了一些进展.

目标

这个项目的目标大致有两个:

  • 减少运行时间,因为论文中作者用的theano版本代码,非常耗时。这里使用了tensorflow
  • 提供了对模型中每层做了什么的讲解,从而提高模型的可解释性

当前项目和论文中有一点点轻微不同. 论文作者使用了基于Lasagne(Theano的一个轻量级的库)的代码,而这个项目使用了Tensorflow. 初步研究表明,基于同样的系统,tensorflow版本要比theano版本快两倍. 这个项目的另一个贡献是提供了模型各个组分的可理解性. 这个模型将有下面几个部分慢慢介绍

  • 为什么用简单的方式为单词分配标签

  • 理解在Character嵌入时CNN的作用

  • 理解word嵌入层的作用

之前的工作

最近有很多论文都使用了CNN或者RNN结合LSTM和CRF的技术. 这个领域最早的论文之一是来自百度(Zhou & Xu 2015), 他们基于Collobert等人2011的工作(其中,他们讨论了关于词嵌入, CNN和CRF层的网络架构). 词嵌入解决了数据的稀疏型问题而条件随机场是监督插槽标记应用常用的方法. 然而,长期以来,用CNN包含有限的问题是很难解决长期依赖问题的. 一些研究组(Melamud 等2015, Levy & Goldberg 2015)尝试用依赖解析器去解决长期依赖问题. 百度的研究员提出了使用一个深的双向LSTM (BiLSTM, 比如两层双向LSTM)接一个CRF. 选择LSTM是因为在考虑很远的单词影响当前的单词时, 他能有效地解决梯度消失/爆炸的问题. 这个研究组之后用了一个依赖解析器,又发了一篇论文, 他们发霉了一个contex2vec(Melamud 等2016). Context2vec有一个双向的LSTM,然后再接一个MLP(多层感知机). Context2Vec有助于识别符合类似上下文的单词. 另外一个有趣的工作是CMU(Ma & Hovy 2016)提出的端到端的架构, 并且不需要人工特征.

任务描述 & 文献回顾

这里是对一些任务的高度总结(主要关注在NER). 当考虑实体标记问题时, 这里有几个直接可以帮助我们建立一个良好的语言模型.

  • (Morphological information)形态信息(比如单词的前缀或者后缀) 它提供了次的类型的初步提示 (Ma 和Hovy 2016 使用单词的characters水平的CNN对这进行建模)

  • 名称通常会跨越几个单词,所以建模必须由多个标记共同完成(比如底层智能) 线性的条件随机场通常是一个选择(Ma 和 Hovy 2016; Lample 等2016; Zhou & Xu 2015). 它一般是用一个转换概率(比如 给定B-GRG->I-ORG的概率)以及发射概率(也就是 给定tag i-ORG 的单词概率)通过最大几率来产生输出的tag. 通过LC-CRF, NER 语法规则 (比如I-ORG 后面不能跟I-PER或者I-PER后面不能更B-LOC)隐式地编码到模型中

  • (Orthographic evidence)拼写证据: 这是指看起来像一个名称的内在特征. 比如,在一些项目的名字中(往往是缩写), 比如QAS或者LUNA,u会跟在L后面而a跟在Q后面. 在非人称单词里, Q后面通常跟u. Lample 等(2016)在character水平上通过Bi-LSTM对这进行了建模. 这对于那些在已知单词外的单词,尽管很少文本涉及他们,单还是可以对其进行建模.

  • (Distributional evidence)分布证据: 正如第五个方法提到的那样, 追溯到1950s, 想要了解一个单词必须要通过上下文来知道. 之前的一年内, 很多文章(Melamud 等2016; Hovy, 2016; Lample 等2016; Zhou &Xu, 2015)都使用了双向LSTM来解决这个问题. BiLSTM为一个单词提供了上下文信息.

  • (Data sparsity)数据的稀疏型: 这是另一个问题, 这已经通过使用一个预先训练的embedding模型解决并且可以对手上数据进一步的私人订制.

  • 其他特征,比如大小写也是一个很不错的指标.

然而,所有这些特征并不会存在与所有的例子中. 有些名称听起来像常规的单词,比如关键词识别. 有时候其他的情况可能只有首字母大写. 因此,很多文章(Ma & Hovy, 2016; Lample 等 2016; Zhou & Xu, 2015) 报到了使用dropout来解决这个问题,并且也解决了过拟合的问题.

方法

网络架构

网络的高级架构可以在文章中很清晰的看到. 这里使用的方法和之前很像,不过有一些改动.

数据集: ConLL 2003 NER 数据集(train:dev:test = 14041:3247:3450) (words)

词嵌入: 读取60亿从维基百科和网页(开源的)提前训练的向量. 对训练集词汇中的每个单词, 如果之前读取的向量中不存在, 就对它进行随机初始化. 词向量的维度是100.

字符表示: 对词汇中每个字符随机生成嵌入的向量. 嵌入的维度设置为30. 同时, 我们加入一个dropout层(p=0.5)来防止过拟合. 字符表示需要转行成单词形式, 这样才能送到卷积神经网络中(滤波器宽度30, 滑动窗口宽度3).激活函数用tanh. 这里使用一维卷积, 全填充9.

合并层: 词嵌入和字符表示会合并到一起, 然后通过一个dropout层(p=0.5).

BiLSTM: 这里使用一个标准的LSTM架构(Hchreiter和Schmidhuber 1997提出). LSTM 隐藏层的维度为200. 这里加入第三个dropout层(p=0.5).

模型架构

网络形状

网络主要由三个模块组成. 根据输出的形状每个模块如下(每层的输入和输出代码中也有描述):

  • 模块1: 这一个模块有字符表示和词嵌入组成.

    • 字符表示层: [batch_size, max_char_per_word * sequence_length, char_embedd_dim]

    • 词嵌入层: [batch_size, sequence_length, word_embedd_dim]

  • 模块2: 前向和反向LSTM(BiLSTM) 和 线性密集层(压扁输出)

    • 右LSTM: [batch_size, sequence_length, Hidden_Unit_Size]
    • 左LSTM: [batch_size, sequence_length, Hidden_Unit_Size]
    • BiLSTM: [batch_size, sequence_length, 2 * Hidden_Unit_Size]
    • 线性连接层: [batch_size, sequence_length]
  • 模块3: CRF层

    • CRF: [batch_size, sequence_length]

实验变量

下面是一个实验中可调节的变量操作:

  • 梯度剪切: 开始时, 随着迭代的深入常常会遇到梯度爆炸问题(返回NaN). 我试过全局的梯度剪切(绝对值和相对值的剪切), BiLSTM之后在剪切. 发现BiLSTM之后的绝对值剪切效果最好. 因此,下面就这样操作.
  • Dropout: 文章中贯穿整个网络架构提到了三个Dropout层. 我尝试在BiLSTM后在加一层Dropout, 精度将下降10个百分点.

  • 优化算法: 文章中用了SGD算法, 也提到了一些其他的优化算法(给出差不多的结果). 这边我挣扎了很久,然后换到了Adam优化算法. 这个小小的变化大大地提高了我的精确度.

  • Batch Size: 好的结果往往倾向小的batch size(10-64之间).

  • 滤波器大小和滤波器数量: 改变这些值并没有改变P/R.

解释性

上下文决定某个单词标签往往通过修改一些操作获得:

  • Ribeiro 等2016 配合CRF函数来编码
  • 采取CRF维特比算法解码输出概率得分

算法选择一个句子,通过移除屌某些单词来产生变化(如图2所示). 每个变化都会通过预测函数传递.预测函数读取句子和目标单词,然后输出结构的概率(目标单词属于18个类的概率). 训练集中有17类, 同时在模型构建时就加入一个未知类. 现在, 预测器的输出和句子的标签都传递到一个岭回归. 岭回归器会为每个上下文单词分配权重.

评测

我们比较关心F1得分. F1计算公式如下:

神经网络的损失函数是CRF损失的几率对数的负值(论文中有详细描述).

结果和讨论

Tensorflow 实现

Tensorflow 实现的架构大概用了8小时(theano: 36小时, 同样的机器). 我尝试同时使用梯度下降和Adam优化, 发现Adam优化效果比SGD更好. 另外 , 我还对整个网络进行梯度剪切(论文只对LSTM剪切). 同时,我也尝试改变一些参数,比如学习率,衰减率等, 发现论文中的参数已经是最好了. 整个实现可以在github得到.

精准率 & 召回率

对于测试集,整个统计信息似乎都不太好.

可解释性

字符嵌入层

这里是一些单词, 训练集和development集都没有的, 称之为 Out of Unsupervised Vocabulary.

字符嵌入层组合成单词(和上面采用同样的模式). 这样有利于对未知单词分类.

词嵌入层

原始的预训练的词嵌入通过语义组合到一起. 通过在网络中使用这些词嵌入, 词嵌入层现在经过优化可以将属于同一类别的分组,如下表所示:

值得注意的是很多单词属于多个类别,比如第一个单词 “Commission: E-ORG: 32; S-ORG: 11; B-MISC: 4; I-ORG: 2” 在32例子中属于E-ORG类别. 单词”Commission”属于哪个类别往往取决于它的上下文. 上面的表显示了每个单词通常属于哪个类.

调试CRF层

解释CRF层的结果如下:

  • 句子: Australian Tom Moody took six for 82 but Chris Adams, 123 and Tim O’Gorman, 109, took Derbyshire

    • 目标词是 “O’Gorman” (tag: E-PER), 这个系统从未见过. 模型显示Tim的存在,B-PER对给O’Gorman标为E-PER有很大贡献.
  • 句子: Anthony Hill (Australia) beat Dan Jenson (Australia) 15-9 15-8

    • 同样的,在这个例子中目标单词是Hill(E-PER).模型描述是: Anthony(B-PER)和”O”类单词(比如”beat”, “(“, “)”)的存在会对复制E-PER给Hill有很大贡献.
  • 句子: West Indian all-rounder Phil Simmons took four for 38 on Friday as Leicestershire beat Somerset by an innings and 39 runs in two days to take over.

    • 这里目标单词是”Indian” (E-MISC). “West”(B-MISC)的存在贡献了这个预测.

挑战&机会

我们需要一个更好的方式来可视化LSTM和CRF的结果. 当前的实现是有点hacky, 因为CRF解码并没有真正输出概率. 我会在看看文献探索下,希望让这个模型更健壮.

人艰不拆,生活不易