Word Embedding/RNN/LSTM
Word Embedding
Word Embedding是一种词的向量表示,比如,对于这样的“A B A C B F G”的一个序列,也许我们最后能得到:A对应的向量为[0.1 0.6 -0.5],B对应的向量为[-0.2 0.9 0.7]。
之所以希望把每个单词变成一个向量,目的还是为了方便计算,比如“求单词A的同义词”,就可以通过“求与单词A在cos距离下最相似的向量”来做到。
那么如何进行词嵌入呢?目前主要有三种算法:
Embedding Layer
Embedding Layer是与特定自然语言处理上的神经网络模型联合学习的单词嵌入。该嵌入方法将清理好的文本中的单词进行one hot编码(热编码),向量空间的大小或维度被指定为模型的一部分,例如50、100或300维。向量以小的随机数进行初始化。Embedding Layer用于神经网络的前端,并采用反向传播算法进行监督。
被编码过的词映射成词向量,如果使用多层感知器模型MLP,则在将词向量输入到模型之前被级联。如果使用循环神经网络RNN,则可以将每个单词作为序列中的一个输入。
这种学习嵌入层的方法需要大量的培训数据,可能很慢,但是可以学习训练出既针对特定文本数据又针对NLP的嵌入模型。
Word2Vec/ Doc2Vec(Document to Vector)
Word2Vec是由Tomas Mikolov 等人在《Efficient Estimation of Word Representation in Vector Space》一文中提出,是一种用于有效学习从文本语料库嵌入的独立词语的统计方法。其核心思想就是基于上下文,先用向量代表各个词,然后通过一个预测目标函数学习这些向量的参数。
该算法给出了两种训练模型,CBOW (Continuous Bag-of-Words Model) 和 Skip-gram (Continuous Skip-gram Model)。CBOW将一个词所在的上下文中的词作为输入,而那个词本身作为输出,也就是说,看到一个上下文,希望大概能猜出这个词和它的意思。通过在一个大的语料库训练,得到一个从输入层到隐含层的权重模型;而Skip-gram它的做法是,将一个词所在的上下文中的词作为输出,而那个词本身作为输入,也就是说,给出一个词,希望预测可能出现的上下文的词。
通过在一个大的语料库训练,得到一个从输入层到隐含层的权重模型。给定xx预测xxx的模型的输入都是词的向量,然后通过中间各种深度学习DL的CNN或RNN模型预测下一个词的概率。通过优化目标函数,最后得到这些词汇向量的值。
Word2Vec虽然取得了很好的效果,但模型上仍然存在明显的缺陷,比如没有考虑词序,再比如没有考虑全局的统计信息。
Doc2Vec与Word2Vec的CBOW模型类似,也是基于上下文训练词向量,不同的是,Word2Vec只是简单地将一个单词转换为一个向量,而Doc2Vec不仅可以做到这一点,还可以将一个句子或是一个段落中的所有单词汇成一个向量,为了做到这一点,它只是将一个句子标签视为一个特殊的词。
主题模型
LSA、LDA等主题模型,建立词和主题的关系。
RNN
循环神经网络,是非线性动态系统,将序列映射到序列,主要参数有五个:$[W_{hv}, W_{hh}, W_{oh}, b_h, b_o, h_0] $,典型的结构图如下:
- 和普通神经网络一样,RNN有输入层输出层和隐含层,不一样的是RNN在不同的时间t会有不同的状态,其中t-1时刻隐含层的输出会作用到t时刻的隐含层.
- 参数意义是: \(W_{hv}\):输入层到隐含层的权重参数,\(W_{hh}\):隐含层到隐含层的权重参数,\(W_{oh}\):隐含层到输出层的权重参数,\(b_h\):隐含层的偏移量,\(b_o\)输出层的偏移量,\(h_0\):起始状态的隐含层的输出,一般初始为0.
- 不同时间的状态共享相同的权重w和偏移量b
RNN的计算方式
给定一个损失函数 \(L(z,y) = \sum_{t=1}^T{L(z_t, y_t)}\)
RNN因为加入了时间序列,因此训练过程也是和之前的网络不一样,RNN的训练使用的是BPTT(Back Prropagation Through TIme),该方法是由Werbo等人在1990年提出来的。
上面的算法也就是求解梯度的过程,使用的也是经典的BP算法,并没有什么新鲜的。但是值得一提的是,在 t-1 时刻对 \(h_{t−1}\)的求导值,也需加上t时刻的求导中对\(h_{t−1}\) 的求导值,因此BPTT也是一个链式的求导过程。
但是因为上面算法中的第10行,在训练t时刻的时候,出现了t-1的参数,因此对单个的求导就变成了对整个之前状态的求导之和。
也正是因为存在长依赖关系,BPTT无法解决长时依赖问题(即当前的输出与前面很长的一段序列有关,一般超过十步就无能为力了),因为BPTT会带来所谓的梯度消失或梯度爆炸问题(the vanishing/exploding gradient problem)。
这篇文章很好的解释了为什么会产生梯度消失和为什么会梯度爆炸的问题,其实主要问题就是因为在BPTT算法中,以w为例,其求导过程的链太长,而太长的求导链在以tanh为激活函数(其求导值在0~1之间的BPTT中,连乘就会使得最终的求导为0,这就是梯度消失问题,也就是t时刻已经学习不到t-N时刻的参数了。当然,有很多方法去解决这个问题,如LSTMs便是专门应对这种问题的,还有一些方法,比如设计一个更好的初始参数以及更换激活函数(如换成ReLU激活函数)。
参数量
model.add(Embedding(output_dim=32, input_dim=2800, input_length=380))
model.add(SimpleRNN(units=16))
model.add(Dense(uints=256, activation=relu))
...
model.summary()
#output
simple_rnn_1 (SimpleRNN) param # 784
dense_1 (Dense) param # 4352
其中:784=16+1616+1632( \(W_{hv}\) + \(W_{hh}\) + \(b_h\))
LSTM
假设我们试着去预测“I grew up in France... I speak fluent French”最后的词。当前的信息建议下一个词可能是一种语言的名字,但是如果我们需要弄清楚是什么语言,我们是需要先前提到的离当前位置很远的 France的上下文的。这说明相关信息和当前预测位置之间的间隔就肯定变得相当的大。
不幸的是,在这个间隔不断增大时,RNN会丧失学习到连接如此远的信息的能力。在理论上,RNN绝对可以处理"长期依赖"问题。人们可以仔细挑选参数来解决这类问题中的最初级形式,但在实践中,RNN 肯定不能够成功学习到这些知识。Bengio, et al.等人对该问题进行了深入的研究,他们发现一些使训练 RNN 变得非常困难的根本原因。
然而,幸运的是,LSTM 并没有这个问题!
LSTM 由Hochreiter & Schmidhuber (1997)提出,并在近期被Alex Graves进行了改良和推广。在很多问题,LSTM 都取得相当巨大的成功,并得到了广泛的使用。
LSTM 通过刻意的设计来避免长期依赖问题。记住长期的信息在实践中是 LSTM 的默认行为,而非需要付出很大代价才能获得的能力!
所有 RNN 都具有一种重复神经网络模块的链式的形式。在标准的 RNN 中,这个重复的模块只有一个非常简单的结构。
LSTM 同样是这样的结构,但是重复的模块拥有一个不同的结构。不同于单一神经网络层,以一种非常特殊的方式进行交互。
核心思想
LSTM 中的第一步是决定我们会从细胞状态中丢弃什么信息。这个决定通过一个称为忘记门层完成。
下一步是确定什么样的新信息被存放在细胞状态中。
我们把旧状态与 \(f_t\) 相乘,丢弃掉我们确定需要丢弃的信息。接着加上 \(i_t * \tilde{C}_t\)。这就是新的候选值,根据我们决定更新每个状态的程度进行变化。
最终,我们需要确定输出什么值。这个输出将会基于我们的细胞状态,但是也是一个过滤后的版本。
我们到目前为止都还在介绍正常的 LSTM。但是不是所有的 LSTM 都长成一个样子的。实际上,几乎所有包含 LSTM 的论文都采用了微小的变体。
图中最上面的一条线的状态即 s(t) 代表了长时记忆,而下面的 h(t)则代表了工作记忆或短时记忆。
参数量
model.add(Embedding(output_dim=32, input_dim=2800, input_length=380))
model.add(LSTM(32))
model.add(Dense(uints=256, activation=relu))
...
model.summary()
#output
lstm_1 (LSTM) param # 8320
其中:8320=(32+32)324+4*32( \(W_o\) + \(W_C\) + \(W_i\) + \(W_f\) + \(b_o\) + \(b_C\) + \(b_i\) + \(b_f\))。
GRU
LSTM有很多变体,其中较大改动的是Gated Recurrent Unit (GRU),这是由 Cho, et al. (2014)提出。它将忘记门和输入门合成了一个单一的 更新门。同样还混合了细胞状态和隐藏状态,和其他一些改动。最终的模型比标准的 LSTM模型要简单。效果和LSTM差不多,但是参数少了1/3,不容易过拟合。
参考:
Word Embedding/RNN/LSTM的更多相关文章
- 从Word Embedding到Bert模型—自然语言处理中的预训练技术发展史(转载)
转载 https://zhuanlan.zhihu.com/p/49271699 首发于深度学习前沿笔记 写文章 从Word Embedding到Bert模型—自然语言处理中的预训练技术发展史 张 ...
- RNN/LSTM/GRU/seq2seq公式推导
概括:RNN 适用于处理序列数据用于预测,但却受到短时记忆的制约.LSTM 和 GRU 采用门结构来克服短时记忆的影响.门结构可以调节流经序列链的信息流.LSTM 和 GRU 被广泛地应用到语音识别. ...
- zz从Word Embedding到Bert模型—自然语言处理中的预训练技术发展史
从Word Embedding到Bert模型—自然语言处理中的预训练技术发展史 Bert最近很火,应该是最近最火爆的AI进展,网上的评价很高,那么Bert值得这么高的评价吗?我个人判断是值得.那为什么 ...
- 预训练语言模型的前世今生 - 从Word Embedding到BERT
预训练语言模型的前世今生 - 从Word Embedding到BERT 本篇文章共 24619 个词,一个字一个字手码的不容易,转载请标明出处:预训练语言模型的前世今生 - 从Word Embeddi ...
- 深度学习word embedding猜测性别初探
根据用户的一些特征数据,如果能推测出用户的性别借此提高产品的服务质量.广告的精准性等都是极好的. 机器学习方法有很多,而且一般都可以达到不错的效果,比如svm或神经网络等. 本文使用的代码参考——&l ...
- Word Embedding理解
一直以来感觉好多地方都吧Word Embedding和word2vec混起来一起说,所以导致对这俩的区别不是很清楚. 其实简单说来就是word embedding包含了word2vec,word2ve ...
- 时间序列(六): 炙手可热的RNN: LSTM
目录 炙手可热的LSTM 引言 RNN的问题 恐怖的指数函数 梯度消失* 解决方案 LSTM 设计初衷 LSTM原理 门限控制* LSTM 的 BPTT 参考文献: 炙手可热的LSTM 引言 上一讲说 ...
- 建模角度理解word embedding及tensorflow实现
http://www.jianshu.com/p/d44ce1e3ec2f 1. 前言 本篇主要介绍关键词的向量表示,也就是大家熟悉的word embedding.自Google 2013 年开源wo ...
- Word Embedding与Word2Vec
http://blog.csdn.net/baimafujinji/article/details/77836142 一.数学上的“嵌入”(Embedding) Embed这个词,英文的释义为, fi ...
随机推荐
- padding和margin设置成百分比
Margin和Padding是我们在网页设计经常使用到的CSS样式,他们分别是间距和填充,一个作用于盒子外面,一个作用于盒子里面,默认的情况下,这些属性的值都会被计算在盒子的面积里面,在网页开发中的流 ...
- LOJ.6068.[2017山东一轮集训Day4]棋盘(费用流zkw)
题目链接 考虑两个\(\#\)之间产生的花费是怎样的.设这之间放了\(k\)个棋子,花费是\(\frac{k(k-1)}{2}\). 在\((r,c)\)处放棋子,行和列会同时产生花费,且花费和该行该 ...
- Android编译环境配置(Ubuntu 14.04)
常识:编译Android源代码需要在Linux系统环境下进行... 在Linux中,开发Android环境包括以下需求:Git.repo.JDK(现在一般使用OpenJDK)等:其中,Git用于下载源 ...
- npm install 提示权限不足 Error: EPERM: operation not permitted, unlink XXX
问题 使用npm install时提示权限不足 原因 这里原因有两个: 没有管理员权限访问C盘下npm路径导致下载失败. NPM官网没有下载权限. 解决方案 第一原因 这里可以使用管理员身份执行以下命 ...
- JDBC连接
jdbc是java中的数据库连接技术,功能非常强大. 数据库访问过程 1.加载数据库驱动 要通过jdbc去访问某数据库必须有相应的JDBC driver 它往往由数据库厂商提供,是链接jdbc API ...
- OpenCV3.2.0+VS2017环境配置与常见问题(巨细坑爹版)
目录 安装 常见问题 题外话:首先,配环境一定要有耐心... 本博客是本小白第一次装OpenCV成功后第一时间整理发布.用的是刚下载好的OpenCV3.2.0版,用x64编译器Debug运行(当然Re ...
- C++程序设计方法5:接口设计
一切都在变化,因此程序要适应变化: 变化分层 封装 接口与隐藏: 接口:类暴露出来的部分,是类所提供的功能: 隐藏实现的细节: UML类图 接口在哪儿? 设计思路:从上到下设计 实现类的接口 细化
- 定位bug的方法总结
把问题聚焦到某一个点上,而不是焦躁的瞎搞,这样效率极低 1,看改动的地方 2,看文档:官方文档或者接口文档. 3,google不到的话,也试试百度中文搜索. 4,看格式反常的地方 5,反思 反常的地方 ...
- boost::lockfree::queue多线程读写实例
最近的任务是写一个多线程的东西,就得接触多线程队列了,我反正是没学过分布式的,代码全凭感觉写出来的,不过运气好,代码能够work= = 话不多说,直接给代码吧,一个多消费者,多生产者的模式.假设我的任 ...
- C_求两个日期相隔的天数(闰年)
#include <stdio.h> #include <math.h> int leap_year(int year){ == || (year%== && ...