美文网首页
ELMo词向量

ELMo词向量

作者: Luuuuuua | 来源:发表于2019-06-29 20:28 被阅读0次

    ELMo词向量出自于论文《Deep contextualized word representations》

    什么是ELMo?

    ELMo的全称是Embeddings from Language Models,中文意思是基于语言模型的词向量,它是一个上下文词向量/动态词向量,同一单词在不同的上下文中具有不同的含义,而ELMo词向量能表示出这种不同。
    实现过程可以简单描述为:将不同的句子输入模型,模型会实时产生上下文词向量。

    ELMo是如何实现的?

    1. 构建一个双向语言模型,给定一个包含N个tokens(t_1,t_2,...,t_N)的序列
      前向语言模型,给定前面的tokens(t_1,t_2,...,t_{k-1})求下一个token是t_k的概率:
      p(t_1,t_2,...,t_N)=\prod_{k=1}^{N}p(t_k|t_1,t_2,...,t_{k-1})
      反向语言模型,与前向语言模型相反,知道后边的token,求前面的token:
      p(t_1,t_2,...,t_N)=\prod_{k=1}^{N}p(t_k|t_{k+1},t_{k+2},...,t_N)
      那么,双向语言模型可以表示为:
      \sum_{k=1}^N \log (p(t_k|t_1,t_2,...,t_{k-1};\Theta_x;\stackrel{\rightarrow}\Theta_{LSTM},\Theta_s)+p(t_k|t_{k+1},t_{k+2},...,t_N);\Theta_x; \stackrel{\leftarrow} \Theta_{LSTM},\Theta_s)
      其中,\Theta_x是输入层单词表示的参数,\Theta_{LSTM} 是LSTM参数,\Theta_s是Softmax层的参数。

    2. 结合网络各层的双向语言模型的表达
      对于tokent_k,通过一个由L层双向语言模型构成的网络,可以得到2L+1个表示:
      R_k=\{x_k^{LM},\stackrel{\rightarrow}h_{k,j}^{LM},\stackrel{\leftarrow} h_{k,j}^{LM}|j=1,2,...,L\} =\{h_{k,j}^{LM}|j=0,1,...,L\}
      h_{k,0}^{LM}是对token直接编码的结果(可以使用word2vec,Glove,或者将字符通过CNN进行编码),h_{k,j}^{LM}是每个biLSTM层输出的结果。
      在下游任务中,可以组合不同层的单词的表示进行使用:
      ELMo_k^{task}=E(R_k,\Theta^{task})=\gamma^{task}\sum_{j=0}^{L}s_j^{task}h_{h,j}^{LM}
      其中,\gamma^{task}是任务相关的scale参数,不同的任务要设置不同的数值,s_j是一个softmax的结果,可以在训练的过程中学习。

    ELMo是如何训练的?

    网络结构共三层

    • 第一层是普通的word embedding 可以用wrod2vec或者glove来得到,或者使用character level得到token embedding。 这部分是general embedding,上下文无关。文中使用的是character level的CNN+Highway。
    • 后面两层是两个biLSTM 去encode 输入(同时也有残差连接), 每一层LSTM得到的输出(隐状态) 作为每个词的上下文相关的word vectors。

    ELMo和Glove的区别

    • Glove 词向量是固定的词向量。同一单词在不同的语句中具有相同的表示。

    • ELMo的基本输入单元为句子,每个词没有固定的词向量,是根据词的上下文环境来动态产生当前词的词向量,可以较好地解决一词多义的问题。

    • ELMo 的输入是字母而不是单词。因此,他们可以利用子字词单元来计算有意义的表示,即使对于词典外的词(如 FastText这个词)也是如此。

    • ELMo 是 biLMs 几层激活的串联。语言模型的不同层对单词上的不同类型的信息进行编码(如在双向LSTM神经网络中,词性标注在较低层编码好,而词义消歧义用上层编码更好)。连接所有层可以自由组合各种文字表示,以提高下游任务的性能。

    实践参考代码

    哈工大改写的多国语言版:https://github.com/HIT-SCIR/ELMoForManyLangs

    Pytorch版ELMo(Allennlp)

    from allennlp.commands.elmo import ElmoEmbedder
    elmo = ElmoEmbedder(options_file='../data/elmo_options.json', weight_file='../data/elmo_weights.hdf5', cuda_device=0)
    context_tokens = [['I', 'love', 'you', '.'], ['Sorry', ',', 'I', 'don', "'t", 'love', 'you', '.']]
    elmo_embedding, elmo_mask = elmo.batch_to_embeddings(context_tokens)
    print(elmo_embedding)
    print(elmo_mask)
    
    1. 导入ElmoEmbedder类
    2. 实例化ElmoEmbedder. 3个参数分别为参数配置文件, 预训练的权值文件, 想要用的gpu编号, 这里两个文件我是直接下载好的, 如果指定系统默认自动下载会花费一定的时间, 下载地址
       
        DEFAULT_OPTIONS_FILE = "https://s3-us-west-2.amazonaws.com/allennlp/models/elmo/2x4096_512_2048cnn_2xhighway/elmo_2x4096_512_2048cnn_2xhighway_options.json"
        DEFAULT_WEIGHT_FILE = "https://s3-us-west-2.amazonaws.com/allennlp/models/elmo/2x4096_512_2048cnn_2xhighway/elmo_2x4096_512_2048cnn_2xhighway_weights.hdf5"
        
    3. 输入是一个list的token序列, 其中外层list的size即内层list的个数就是我们平时说的batch_size, 内层每个list包含一个你想要处理的序列(这里是一句话, 你可以一篇文章或输入任意的序列, 因为这里预训练的模型是在英文wikipidia上训的, 所以输入非英文的序列肯定得到的结果没什么意义).
    4. 通过batch_to_embeddings对输入进行计算的到tokens的embedding结果以及我们输入的batch的mask信息(自动求mask)
    
        Variable containing:
        ( 0  , 0  ,.,.) = 
          0.6923 -0.3261  0.2283  ...   0.1757  0.2660 -0.1013
         -0.7348 -0.0965 -0.1411  ...  -0.3411  0.3681  0.5445
          0.3645 -0.1415 -0.0662  ...   0.1163  0.1783 -0.7290
                   ...             ⋱             ...          
          0.0000  0.0000  0.0000  ...   0.0000  0.0000  0.0000
          0.0000  0.0000  0.0000  ...   0.0000  0.0000  0.0000
          0.0000  0.0000  0.0000  ...   0.0000  0.0000  0.0000
          
                ⋮  
    
        ( 1  , 2  ,.,.) = 
         -0.0830 -1.5891 -0.2576  ...  -1.2944  0.1082  0.6745
         -0.0724 -0.7200  0.1463  ...   0.6919  0.9144 -0.1260
         -2.3460 -1.1714 -0.7065  ...  -1.2885  0.4679  0.3800
                   ...             ⋱             ...          
          0.1246 -0.6929  0.6330  ...   0.6294  1.6869 -0.6655
         -0.5757 -1.0845  0.5794  ...   0.0825  0.5020  0.2765
         -1.2392 -0.6155 -0.9032  ...   0.0524 -0.0852  0.0805
        [torch.cuda.FloatTensor of size 2x3x8x1024 (GPU 0)]
    
        Variable containing:
            1     1     1     1     0     0     0     0
            1     1     1     1     1     1     1     1
        [torch.cuda.LongTensor of size 2x8 (GPU 0)]
    
    输出两个Variable, 第一个是2*3*8*1024的embedding信息, 第二个是mask. 
    其中2是batch_size, 3是两层biLM的输出加一层CNN对character编码的输出, 8是最长list的长度(对齐), 1024是每层输出的维度
    mask的输出2是batch_size, 8实在最长list的长度, 第一个list有4个tokens, 第二个list有8个tokens, 所以对应位置输出1.
    

    参考资料
    http://shomy.top/2019/01/01/elmo-1/
    https://cstsunfu.github.io/2018/06/ELMo/
    https://blog.csdn.net/sinat_26917383/article/details/81913790

    相关文章

      网友评论

          本文标题:ELMo词向量

          本文链接:https://www.haomeiwen.com/subject/xbfwtctx.html