从 ECMo、Bert 看 Word Embedding

ECMo = embeddings from a conversation model

ECMo是一种基于多轮对话上下文关系的Embedding模型 发表于 Improving Matching Models with Contextualized Word Representations for Multi-turn Response Selection in Retrieval-based Chatbots C. Tao et al. 2018

虽然这篇文章没有发布在各大会议上 只是贴在Arxiv上面 但Motivation和Bert一致 可以看出想法还是好的

然后这篇文章的三作 是上次回来讲 XiaoIce 的学长 羡慕

自从word2Vec发布之后 NLP任务 就被定义为 两步 一步词向量 一步后续模型

但是word2Vec跑的模型是不包含上下文信息 只是单向的

这个时候就想为啥不能像后续模型一样 通过交互把 把句子间的关系也反映出来

当是词级别的Embedding 很容易造成词向量本身带有 歧义

于是这个时候就想能把 Pre-Train 过程做的像后面一样

实际上如果你跑过QA模型的时候 就会发现 Accurate大头都在Embedding过程

比如如果把后面全部去掉 只做一个Embedding 然后直接Cosine Similarity 可能只掉5.6个点

所以Embedding好坏决定了 决定了模型的 下限

在讲ECMo之前需要复(yu)习一下 word2Vec

我想大部分人对word2Vec肯定不陌生 起码会掉gensim的包

但不一定会其原理熟悉

word2Vec 思路其实和我们之前用到的大部分模型一致

就是在当前word 和 下一个word 之间 找一个映射关系f

而这个f代表了当前word的属性 把映射关系f的参数拿来 作为当前word的词向量

在这里并不关心预测结果 只关心训练完的副产物 模型参数 第一个这么做的还不是word2vec 而是 nlp almost from scratch R Collobert et al.2011

输入 和 输出不一定只有一个词

  • 一个输入 多个输出 Skip-gram
  • 多个输入 一个输出 Cbow

那么就有一个问题 word2Vec的输入值怎么确定?

首先肯定不是Word2Vec值 那是中间产物

在genism中采用的是random N维向量 丢进去 然后 慢慢摩擦 摩擦 得到了我们需要的Embedding值

当然你可以可以用one-hot(就是 出现的词 那一维度 置为1 未出现置为0)

可以看出初始值是什么 与结果怎么样关系不大 只和收敛epochs有关

然后word2Vec跑的是 Hierarchical log bilinear language model 只不过把回归函数进行简化

P ( w n = w w 1 , , w n 1 ) = σ ( v w i = 1 n 1 C i v w i + b w ) P(w_n=w|w_1,\cdots,w_{n-1})=\sigma(v_w \cdot \sum\limits_{i=1}^{n-1} C_i v_{w_i} + b_w) 简化为 P ( w n = w w 1 , , w n 1 ) = σ ( 1 n 1 v w i = 1 n 1 v ~ w i ) P(w_n=w|w_1,\cdots,w_{n-1})=\sigma(\frac{1}{n-1} v_w \cdot \sum\limits_{i=1}^{n-1} \tilde{v}_{w_i})

这样改进 可以大幅度提升运行效率

另外word2Vec还引入了Negative sample

负采样 是解决SoftMax维数太大 计算效率低的问题 在计算SoftMax的时候除了一个正例之外 随机采样几个负样本 只要模型能中这几个样本中训练出正例就行了

log σ ( v w 0 T v w I ) + i = 1 K E w i [ log σ ( v w i T v w I ) ] \log\sigma(v^{T}_{w_0}v_{w_I})+\sum\limits_{i=1}^KE_{w_i}[\log\sigma(-v^{T}_{w_i}v_{w_I})]

其中 v w 0 v'_{w_0} 为正例, v w i v'_{w_i} 为负例 k个 σ \sigma 为sigmoid函数 即极大正例似然 极小负例似然

这样word2Vec在运算效率就比之前的一些Embedding效果好很多

再加上那个 King - man = queen - woman 的例子 导致了被广泛应用于NLP pre-train过程

然后还有一点就是word2Vec的过程 相当于矩阵分解的过程 是一个全局PPMI(共现)矩阵的分解

我们在做word2Vec得到的结果是其实是两个向量 一个是所需要的词向量word 还有一个本应该输出的记过向量reply

word2vec的过程 对于每一个不同的word 生成一个相对应的reply 就相当于 把一个矩阵 分解为word×reply

证明详见 Neural word embedding as implicit matrix factorization Levy et al. NIPS 2014 Word embedding revisited: A new representation learning and explicit matrix factorization perspective Li Yitan et al. IJCAI 2015

明白了word2Vec的原理 那么 对于利用模型进行Word Embedding的合理性应该就清楚了

在ECMo中利用了一个叫分层编码-解码hierarchical encoder-decoder (HED)的模型进行训练

首先是一个词语级的处理 经过一层双向GRU(BiGRUs) 然后对每个词进行最大池化处理 结果作为第二层的输入

第二层是一个上下文级别的处理 经过另外一个GRU 然后最后一层输出到解码阶段

解码阶段利用一个RNN进行反向推测 由前一个词 u n + 1 u_{n+1} 推测下一个词 u n u_{n}

p ( u n + 1 u 1 , . . . , u n ) = p ( w n + 1 , 1 h n s ) t = 2 T n + 1 p ( w n + 1 , t h n s , w n + 1 , 1 , . . . , w n + 1 , t 1 ) p(u_{n+1}|u_1,...,u_n)=p(w_{n+1,1}|h^s_n)\prod\limits_{t=2}^{T_{n+1}}p(w_{n+1,t}|h^s_n,w_{n+1,1},...,w_{n+1,t-1})

其中 p ( w n + 1 , t h n s , w n + 1 , 1 , . . . , w n + 1 , t 1 ) = I I w n + 1 , t . s o f t m a x ( h t d , e n + 1 , t 1 ) p(w_{n+1,t}|h^s_n,w_{n+1,1},...,w_{n+1,t-1})=II_{w_{n+1,t}}.softmax(h^d_t,e_{n+1,t-1})

h t d = G R U d ( h t 1 d , e n + 1 , t 1 ) h^d_t=GRU_d(h^d_{t-1},e_{n+1,t-1}) , I I w n + 1 , t II_{w_{n+1,t}} 为one-hot

而word Embedding值 即ECMo就是HED中的 h i s h_i^s

文章中在Ubuntu和Douban两个dataset上面做了测试

其中优化函数选择Adam 学习率 1 e 3 1e^{-3} 所有GRU及RNN的隐层数为300 取最大session为10 最大utterance为50

bert已然是当今学界的热点

那么为啥Bert效果那么好

Bert相当于在预处理阶段 把dataset中 字符级别、词级别、句子级别 甚至句子间所有特征抓取到

这样在处理特定NLP任务的时候 只需要对输出向量进行些许处理即可

那么究竟是如何操作的呢

深度双向Encoding在后续模型中早就被广泛采用

但在模型的Pre-train阶段很少有做到如此复杂的处理 像word2vec仅仅是单向线性

效果已经很好ELMo也仅仅是两个方向的RNN 分别进行操作 然后直接加和

Bert为了达到这种深层双向Encoding的功能 做了一件我们从小都在做的事情 完形填空

把遮住上下文中任意一个单词 通过训练出这个地方应该是什么单词

可以想象的出来 这个复杂度 不是一般的高 很羡慕有TPU的了

但这样就会在Encoding的时候也会把标记也Encoding 于是作者想了一个办法

[mask]

这样让模型学习到 这个地方有一个空

然后用Transformer 来做encoding 首先TPU对transform支持更好

其次transform相较于RNN系 有更好的并行性 和 长时间记忆性

为了保证位置信息 在bert中 训练一个position Embedding 在论文中直接用了一个one-hot作为输入

然后 慢慢训练 (我错了 有TPU的是快快训练)

于是加上这些 就变成了24层multi-head attention block 每个block 16个抽头 1024个隐层 瑟瑟发抖:fearful:

然后上面只获得了词级别的特征 对于句粒度的任务效果不会太好

在这里Bert很疯狂的把word2vec中负采样 拿到这边

只不过变成了句子粒度的

同样是跑transform 得到一个 segment Embedding

然后把它和前面的词级别的 token embedding + 位置信息 position embedding 直接加和在一起

然后 对于任何NLP任务只需要在这之后 做一些简单的操作就行了 比如说MLP 什么的

跑过Bert 除了确实比较慢之外 全量数据可能要200多天 但效果真的好 1%数据在测试集上的准确率就达到0.567 还用的是base版

不得不佩服Google Brain 就是没钱 qiong

可以看到随着NLP研究的推进 随着硬件 软件 的成熟化发展

Embedding从最开始的One-hot 到从NN中间参数获取的word2Vec 再到双向Encoding的ELMo 最后到全能的Bert

对预处理越来越重视 也认识到预处理过程 对整个模型的重要性

当然更重要的是 对自己没钱 没本事的认识 呜呜呜

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章