1. 名词:ELMO:哈工大LTP 开发的动态词向量。
问题一:何为动态词向量: 普通的词向量,是静态的,也就是一个词代表一个N维向量,这种向量不随着语境的变化而变化,不管在任何语境下embedding的值都是不变的; elmo词向量,是基于深度学习神经网络的词向量。是动态的。elmo的output随着语境的变化而变化,在不同的句子里面有不同的表现。比如:“我今天吃的苹果很好吃”;“苹果手机非常好用”。这两个句子里面的“苹果”,在elmo里面的embdding值一定是不同的。这也更符合语义层面的NLP项目。
2.ELMO实现:
一.原版实现
EMBBEDDING LAYER (词向量层) )->(cnn/lstm)
ENCODEING LAYER(编码层)-> (lstm/elmo)
(1)ltp提供的中文版词向量的embedding层是这样的(cnn):
(2) encoding层是这样的(elmo):
(3)ltp提供的词向量的embdding层是cnn的,若是一个双层的LSTM加一个linear,若是encoding层相同
二.轻量级基于feed评论的训练及实现
EMBBEDDING LAYER(词向量层) ->(emb)
ENCODING LAYER (编码层) ->(lstm 单层)
轻量级的 elmo,就是一个简单的embedding映射,再加一个单层的lstm,只是loss的设计思路借鉴elmo的ltp代码。 轻量级考量原因:1. 网络结构简单好上线; 2. 显存限制(使用轻量级的结构,在序列长度限制在100以内的情况下,已经是7-8G,足够将一个显卡打满了)3. 大道至简。(个人认为elmo的设计亮点在loss,而前面的网络结构简单或复杂,不会带来效果根本性的差异。
3. ELMO的输出维及loss计算原理:
(1)结论1: elmo的输出维就是词典的大小,与Word2vec的设计相似。
(2)结论2: elmo的设计思路就是从前面的词预测后面的词,loss也就是前面序列的output与后面序列output的softmax值做crossentropy(交叉熵)
从这个图中可以将loss的原理简单阐述清楚:
该图画的是一个batch的output计算loss的原理图。看源码也可以:
4.遇到的问题:显存泄露 (out of memory)
解决: 该网络中,影响显存的因素有 seqlen(序列长度), batch_size, input_dim(输入维),hidden_dim (隐藏层),字典大小(输出维),简单计算一下memory与这些因子之前的关系:
embedding layer : mem_embedding = seqlen * batch_size * input_dim
lstm layer: mem_lstm = seqlen * input_dim * hidden_dim *4
connect layer and loss :mem_connact = hidden_dim * output_dim * seqlen
综上可以得出 memory = mem_embedding + mem_lstm+ mem_connact = seqlen(batch_size * input_dim + 4input_dim * hidden_dim + hidden_dim *output), 显存与seqlen序列长度是倍数影响关系,其他影响按重要性排序分别是input dim,output dim,hidden dim,也就是要减小显存,首先要保证seqlen不要太大。
经过笔者的实验,seqlen序列长度设置为500会有明显的out of memory, 控制在100,显存8G左右,也满足目前的工程需求。
5. 实验的效果
elmo训练方式 | 召回 | 准确 | auc
input 长度:128; loss计算方式:前20与后20 |36.40% | 85% | 0.977
input 长度:50,loss计算方式:前后去掉一个词的全序列 |36.7% | 85% |0.987
非elmo预训练 |34.4% |85% |0.973