终其一生,我们只不过在寻找自己

0%

CS224n-12 Subword Models 解决OOV问题

  • Subword Models 解决OOV问题

OOV: out-of-vocabulary即单词不在词汇库里的情况
之前的模型都是基于单词层面的,但是对于一个新单词“asd”没有解决方案。一个朴素的想法就是“拆分”,把长单词拆成几个单词的组合。相对于中文来说,就是一个新的词组去按照每个字的意思去理解单词的意思。
下面是解决方案。

Character-Level Model

  • 字符级别操作,直接把每个字母当做基本单元,然后训练单词的Embedding。

但是其输入的序列更长了,使得数据更稀疏且长程的依赖关系更难学习,训练速度也会降低。下面是几种具体的方案。

CNN


CNN相当于把连续的几个字符,全部枚举,拼起来,然后Embedding。

BLSTM


双向RNN遍历字符,直接输出Embedding,简单粗暴。

字母单词同时Embedding


详细介绍:https://www.hankcs.com/nlp/cs224n-character-aware-neural-language-models.html
字符级别的CNN+Highway Network可以提取丰富的语义和结构信息。这个模型将其他网络当成积木一样,构建了更好的语言模型。

LSTM+BGRU

和上面那个好像。
Fully Character-Level Neural Machine Translation without Explicit Segmentation中利用了多层的convolution, pooling与highway layer来解决这一问题,其中encoder的结构如下图所示:

输入的字符先被映射到character embedding。然后与窗口大小不同的卷积核进行卷积操作再将输出联结起来,例如上图中有三种窗口大小分别为3,4,5的卷积核,相当于学习了基于字符的trigram, 4-grams, 5-grams。然后对卷积的输出进行max pooling操作,相当于选择最显著的特征产生segment embedding。由此我们从最基础的输入的character embedding得到了系统中认为语言学上有意义的segment embedding。然后将这些特征经过Highway Network(有些类似于Residual network,方便深层网络中信息的流通,不过加入了一些控制信息流量的gate)和双向的GRU,这样得到最终的encoder output。之后decoder再利用Attention机制以及character level GRU进行decode。

实验结果显示,基于字符的模型能更好的处理OOV的问题,而且对于多语言场景,能更好的学习各语言间通用的词素。

字母组合

字母的的暴力组合可以优化的思路就是,只选有意义的(高频)的当做组合。

Byte Pair Encoding

基本单元介于字符与单词之间的模型称作Subword Model。那么Subword如何选择呢?一种方法是Byte Pair Encoding,简称BPE。 BPE最早是一种压缩算法,基本思路是把经常出现的byte pair用一个新的byte来代替,例如假设(‘A’, ’B‘)经常顺序出现,则用一个新的标志’AB’来代替它们。

给定了文本库,我们的初始词汇库仅包含所有的单个的字符,然后不断的将出现频率最高的n-gram pair作为新的ngram加入到词汇库中,直到词汇库的大小达到我们所设定的某个目标为止。

例如,假设我们的文本库中出现的单词及其出现次数为 {‘l o w’: 5, ‘l o w e r’: 2, ‘n e w e s t’: 6, ‘w i d e s t’: 3},我们的初始词汇库为{ ‘l’, ‘o’, ‘w’, ‘e’, ‘r’, ‘n’, ‘w’, ‘s’, ‘t’, ‘i’, ‘d’},出现频率最高的ngram pair是(‘e’,’s’) 9次,所以我们将’es’作为新的词汇加入到词汇库中,由于’es’作为一个整体出现在词汇库中,这时文本库可表示为 {‘l o w’: 5, ‘l o w e r’: 2, ‘n e w es t’: 6, ‘w i d es t’: 3},这时出现频率最高的ngram pair是(‘es’,’t’) 9次,将’est’加入到词汇库中,文本库更新为{‘l o w’: 5, ‘l o w e r’: 2, ‘n e w est’: 6, ‘w i d est’: 3},新的出现频率最高的ngram pair是(‘l’,’o’)7次,将’lo’加入到词汇库中,文本库更新为{‘lo w’: 5, ‘lo w e r’: 2, ‘n e w est’: 6, ‘w i d est’: 3}。以此类推,直到词汇库大小达到我们所设定的目标。这个例子中词汇量较小,对于词汇量很大的实际情况,我们就可以通过BPE逐步建造一个较小的基于subword unit的词汇库来表示所有的词汇。

SentencePiece

谷歌的NMT模型用了BPE的变种,称作wordpiece model,BPE中利用了n-gram count来更新词汇库,而wordpiece model中则用了一种贪心算法来最大化语言模型概率,即选取新的n-gram时都是选择使得perplexity减少最多的ngram。进一步的,sentencepiece model将词间的空白也当成一种标记,可以直接处理sentence,而不需要将其pre-tokenize成单词。下面是解决方案。

Hybrid Model:只对新词character level

character level本来是解决word Embedding的OOV问题的,直接重新打破word Embedding 有点亏,就单纯对新词进行Embedding就好了。

其结构如下图所示,大部分还是依赖于比较高效的word level模型,但遇到例子中的”cute”这样的OOV词汇,我们就需要建立一个character level的表示,decode时遇到这个表示OOV的特殊标记时,就需要character level的decode,训练过程是end2end的,不过损失函数是word部分与character level部分损失函数的加权叠加。

其他思路:FastText embeddings

对于任何一个单词,把他内部的可能全枚举出来,然后在word embeddings的过程中都生成一个向量。相当于扩充了单词集。

其基本思路是将每个word表示成bag of character n-gram以及单词本身的集合,例如对于where这个单词和n=3的情况,它可以表示为 _, ,_其中”<”,”>”为代表单词开始与结束的特殊标记。假设对于word $w$ ,其n-gram集合用 $=G_W$ 表示,每个n-gram的矢量表示为 [公式] ,则每个单词可以表示成其所有n-gram的矢量和的形式,而center word $w$ 与context word $c$ 的分数就可表示成 [公式] 的形式,之后就可以按照经典的word2vec算法训练得到这些特征向量。
这种方式既保持了word2vec计算速度快的优点,又解决了遇到training data中没见过的oov word的表示问题,可谓一举两得。

参考: 知乎这篇

-------------    你的留言  是我更新的动力😊    -------------