Embeddings from Language Models(ELMo)

Embeddings from Language Models(ELMo)

1. 概述

随着深度学习在NLP领域的发展,产生很多深度网络模型用于求解各类的NLP问题,在这众多的网络模型中,无疑都会使用到词向量的概念,这就不得不提及word2vec[1]词向量生成工具。从word2vec词向量工具的提出后,预训练的词向量成了众多NLP深度模型中的重要组成部分。然而传统的word2vec生成的词向量都是上下文无关的,其生成的词向量式固定,不会随着上下文的改变而改变,这种固定的词向量无法解决一词多义的问题。比如“bank”这个词,既可以表示“河岸”,也可以表示“银行”。Embeddings from Language Models(ELMo)[2]是2018年提出的一种基于上下文的预训练模型,研究人员认为一个好的预训练语言模型应该能够包含丰富的句法和语义信息, 并且能够对多义词进行建模。

ELMo的本质思想通过大量语料学习到每个词的一般性embedding形式,此时是与上下文无关的;当在具体的NLP任务中时,此时每个词都具有了上下文的含义,通过上下文调整学习好的词向量。

2. 算法原理

2.1. ELMo的基本原理

在ELMo的本质思想中包含了两阶段的过程,第一个阶段利用大量预料训练出与上下文无关的词向量的表达,如上述的“bank”,此时并不能知道代表的是“银行”还是“河岸”;第二阶段是在具体的下游任务中,将每个词向量放入到具体的上下文的语言环境中,对每个词向量微调,以适应具体的任务,如根据具体的上下文语境,微调得到“bank”一词的与上下文相关的向量。

2.2. 第一阶段——ELMo预训练

2.2.1. ELMo模型的结构

对于ELMo模型的网络结构如下图所示:

www.zeeklog.com  - Embeddings from Language Models(ELMo)

在ELMo的结构图中可以看到,ELMo主要分为三个部分,第一,最下方的黄色部分,词的Embedding部分,用于将离散的词映射成稠密的连续向量;第二,中间的蓝色部分,这部分是两个双层的LSTM模块,用于对词进行序列学习;第三,最上方的绿色部分,词向量的最终表征。从论文[2]中可知,这三个部分的输出代表了三个层级的含义,分别是:

  • 第一部分代表了词法特征
  • 第二部分代表了句法特征
  • 第三部分代表了语义特征

其中,在ELMo的网络结构中,用于语言模型学习的是双层的双向LSTM。

2.2.2. ELMo模型的训练

ELMo模型的预训练是在大量预料上,通过无监督的方式,其目标函数是神经语言模型[3]。假设给定的 N N N个词的序列为 ( t 1 , t 2 , ⋯ , t N ) \left ( t_1,t_2,\cdots ,t_N \right ) (t1​,t2​,⋯,tN​),先看正向的语言模型,其目标通过给定的前 k − 1 k-1 k−1个词的序列 ( t 1 , t 2 , ⋯ , t k − 1 ) \left ( t_1,t_2,\cdots ,t_{k-1} \right ) (t1​,t2​,⋯,tk−1​)预测第 k k k个词 t k t_k tk​的概率:

p ( t 1 , t 2 , ⋯ , t N ) = ∏ k = 1 N p ( t k ∣ t 1 , t 2 , ⋯ , t k − 1 ) p\left ( t_1,t_2,\cdots ,t_N \right )=\prod_{k=1}^{N}p\left ( t_k\mid t_1,t_2,\cdots ,t_{k-1} \right ) p(t1​,t2​,⋯,tN​)=k=1∏N​p(tk​∣t1​,t2​,⋯,tk−1​)

再看反向的语言模型,其目标是通过第 k k k个词 t k t_k tk​后面的词的序列 ( t k ∣ t k + 1 , t k + 2 , ⋯ , t N ) \left ( t_k\mid t_{k+1},t_{k+2},\cdots ,t_{N} \right ) (tk​∣tk+1​,tk+2​,⋯,tN​)来预测 t k t_k tk​的概率:

p ( t 1 , t 2 , ⋯ , t N ) = ∏ k = 1 N p ( t k ∣ t k + 1 , t k + 2 , ⋯ , t N ) p\left ( t_1,t_2,\cdots ,t_N \right )=\prod_{k=1}^{N}p\left ( t_k\mid t_{k+1},t_{k+2},\cdots ,t_{N} \right ) p(t1​,t2​,⋯,tN​)=k=1∏N​p(tk​∣tk+1​,tk+2​,⋯,tN​)

对于双向的LSTM模型,通过语言模型得到双向LSTM的目标函数为:

∑ k = 1 N ( l o g p ( t k ∣ t 1 , ⋯ , t k − 1 ; Θ x , Θ → L S T M , Θ s ) + l o g p ( t k ∣ t k + 1 , ⋯ , t N ; Θ x , Θ ← L S T M , Θ s ) ) \sum_{k=1}^{N}\left ( log\; p\left ( t_k\mid t_1,\cdots ,t_k-1;\Theta _x,\overrightarrow{\Theta }_{LSTM},\Theta _s \right )+log\; p\left ( t_k\mid t_{k+1},\cdots ,t_N;\Theta _x,\overleftarrow{\Theta }_{LSTM},\Theta _s \right ) \right ) k=1∑N​(logp(tk​∣t1​,⋯,tk​−1;Θx​,Θ   LSTM​,Θs​)+logp(tk​∣tk+1​,⋯,tN​;Θx​,Θ   LSTM​,Θs​))

此时需要求解上述目标函数的最大值,其中 Θ x \Theta _x Θx​表示的是词的上下文无关向量, Θ → L S T M \overrightarrow{\Theta }_{LSTM} Θ   LSTM​和 Θ ← L S T M \overleftarrow{\Theta }_{LSTM} Θ   LSTM​分别为正向和反向的LSTM模型的参数, Θ s \Theta _s Θs​为softmax层的参数。

通过上述模型的训练,最终得到了多个向量,可以表示为:

R k = { x k L M , h → k , j L M , h ← k , j L M ∣ j = 1 , ⋯ , L } = { h k , j L M ∣ j = 1 , ⋯ , L } R_k=\left \{ \mathbf{x}_k^{LM},\overrightarrow{\mathbf{h}}_{k,j}^{LM},\overleftarrow{\mathbf{h}}_{k,j}^{LM}\mid j=1,\cdots ,L \right \}=\left \{ \mathbf{h}_{k,j}^{LM}\mid j=1,\cdots ,L \right \} Rk​={xkLM​,h   k,jLM​,h   k,jLM​∣j=1,⋯,L}={hk,jLM​∣j=1,⋯,L}

其中, h k , 0 L M \mathbf{h}_{k,0}^{LM} hk,0LM​表示的是上图中的黄色部分,表示的是与上下文无关的词的向量, h k , j L M = [ h → k , j L M ; h ← k , j L M ] \mathbf{h}_{k,j}^{LM}=\left [ \overrightarrow{\mathbf{h}}_{k,j}^{LM};\overleftarrow{\mathbf{h}}_{k,j}^{LM} \right ] hk,jLM​=[h   k,jLM​;h   k,jLM​]表示的是每一层的LSTM的输出。通过将这多个向量合并成一个向量便得到最终的向量表示:

E L M o k = E ( R k ; Θ e ) \mathbf{ELMo}_k=E\left ( R_k;\mathbf{\Theta }_e \right ) ELMok​=E(Rk​;Θe​)

2.3. 第二阶段——具体任务微调

通过ELMo的预训练得到了上述一系列的向量 E L M o k \mathbf{ELMo}_k ELMok​,根据下游的不同任务,选择不同的向量,其目的是将生成的向量带入到上下文中,对向量做微调。对于不同的任务,需要选择的向量不同,如在参考文献[2]中提及只使用最顶层的输出,即 E ( R k ) = h k , j L M E\left ( R_k \right )=\mathbf{h}_{k,j}^{LM} E(Rk​)=hk,jLM​。更为一般的,可以由下式表示:

E L M o k t a s k = E ( R k ; Θ t a s k ) = γ t a s k ∑ j = 0 L s j t a s k h k , j L M \mathbf{ELMo}_k^{task}=E\left ( R_k;\Theta ^{task} \right )=\gamma ^{task}\sum_{j=0}^{L}s_j^{task}\mathbf{h}_{k,j}^{LM} ELMoktask​=E(Rk​;Θtask)=γtaskj=0∑L​sjtask​hk,jLM​

其中,向量 s t a s k \mathbf{s}^{task} stask用于对向量归一化, γ t a s k \gamma ^{task} γtask用于对具体任务中的向量缩放。

3. 总结

ELMo通过大量语料训练出与上下文无关的一系列向量表示,不同层级的向量带有不同的语言,包括了词法信息,句法信息以及语义信息,通过不同的组合,并在具体的上下文环境中微调得到带有上下文的词向量表示,并能够应用到具体的下游任务中。

参考文献

[1] Mikolov T , Chen K , Corrado G , et al. Efficient Estimation of Word Representations in Vector Space[J]. Computer Science, 2013.

[2] Peters M , Neumann M , Iyyer M , et al. Deep Contextualized Word Representations[J]. 2018.

[3] Y Bengio∗, Ducharme R , Vincent P . A Neural Probabilistic Language Model. 2001.

Read more

爬虫工具篇 - 必会用的 6 款 Chrome 插件

爬虫工具篇 - 必会用的 6 款 Chrome 插件

点击“简说Python”,选择“置顶/星标公众号” 福利干货,第一时间送达! 本文授权转载自AirPython,禁二次转载 作者:星安果 阅读文本大概需要 3 分钟。 在日常 PC 端的爬虫过程工作中,Chrome 浏览器是我们常用的一款工具。 鉴于 Chrome 浏览器的强大,Chrome 网上应用商店很多强大的插件可以帮助我们快速高效地进行数据爬虫。 今天推荐的 6 款 Chrome 插件,可以大大提升我们的爬虫效率。 EditThisCookie EditThisCookie 是一个 Cookie 管理器,可以很方便的添加,删除,编辑,搜索,锁定和屏蔽 Cookies。 可以将登录后的 Cookies 先保存到本地,借助 cookielib 库,直接爬取登录后的数据。 避免了抓包和模拟登录,帮助我们快速地进行爬虫。

By Ne0inhk
我背着女朋友,用 Python 偷偷抓取了她的行踪

我背着女朋友,用 Python 偷偷抓取了她的行踪

点击“简说Python”,选择“置顶/星标公众号” 福利干货,第一时间送达! 本文授权转载自AirPython,禁二次转载 作者:星安果 阅读文本大概需要 5 分钟。 1 目 标 场 景 有时候女朋友一个人在外面玩耍,问她在哪个地方,就是不告诉我。但是,你又很想知道女朋友的「位置」,这该如何是好? 其实你可以这样套路女朋友,假装自己在家很无聊,可以帮她修图,让她微信发原图给你,拿到「微信原图」后,你就可以利用 Python 快速获取到女友的具体位置了。 2 准 备 工 作 首先,在虚拟环境中安装识别图片元数据的库。 pip3 install exifread 然后,进入高德开放平台,申请一个 Web

By Ne0inhk
Python爬取京东笔记本电脑,来看看那个牌子最棒

Python爬取京东笔记本电脑,来看看那个牌子最棒

点击“简说Python”,选择“置顶/星标公众号” 福利干货,第一时间送达! @图片自制by小si 一、前言 二、知识要求三、过程分析1.观察主页面和每个电脑界面的网址2.寻找每个电脑的id3.找到存放电脑的价格和评论数的信息4.爬取信息的思路四、urllib模块爬取京东笔记本电脑的数据、并对其做一个可视化实战五、可视化结果1.运行结果2.可视化结果          // 本文作者 王豪:行路难,多歧路,今安在,埋头苦改bug会有时,直到bug改完才吃饭。 // 阅读文本大概需要 5 分钟。 一、前言 作为一个程序员,笔记本电脑是必不可少的,我这里对京东上的前2页的笔记本的好评论数,价格,店铺等信息进行爬取,并做一个可视化,根据可视化的图,大家可以清晰的做出预测,方便大家购买划算的电脑。当然,我这里前2页的数据是远远不够的,如果大家想要预测的更精准一些,可以改一下数字,获取更多页面的数据,这样,预测结果会更精确。

By Ne0inhk
Python内置函数tuple()详解 tuple()函数的基本用法 Tuple()与元组字面量 元组的不可变性 应用场景 总结——《跟老吕学Python编程》

Python内置函数tuple()详解 tuple()函数的基本用法 Tuple()与元组字面量 元组的不可变性 应用场景 总结——《跟老吕学Python编程》

Python内置函数tuple详解 tuple函数的基本用法 Tuple与元组字面量 元组的不可变性 应用场景 总结——《跟老吕学Python编程》 * * Python内置函数tuple()详解 在Python编程语言中,tuple()是一个内置函数,用于将一个可迭代对象(如列表、字符串、集合等)转换为一个元组。元组是一种不可变的数据结构,这意味着一旦元组被创建,其内容就不能被修改。这种特性使得元组在需要不变数据集合的场景中非常有用,比如作为字典的键或用作不可变的数据存储。 tuple()函数的基本用法 tuple()函数可以接受一个可迭代对象作为参数,并返回一个包含该对象元素的元组。如果Tuple()函数不接受任何参数,它将返回一个空元组。 # 使用列表创建元组 my_list = [1, 2, 3, 4, 5] my_tuple = tuple(my_list) print(my_Tuple) # 输出: (1, 2, 3,

By Ne0inhk