BIlstm模型
为什么使用LSTM与BiLSTM?
将词的表示组合成句子的表示,可以采用相加的方法,即将所有词的表示进行加和,或者取平均等方法,但是这些方法没有考虑到词语在句子中前后顺序。如句子“我不觉得他好”。“不”字是对后面“好”的否定,即该句子的情感极性是贬义。使用LSTM模型可以更好的捕捉到较长距离的依赖关系。因为LSTM通过训练过程可以学到记忆哪些信息和遗忘哪些信息。
但是利用LSTM对句子进行建模还存在一个问题:无法编码从后到前的信息。在更细粒度的分类时,如对于强程度的褒义、弱程度的褒义、中性、弱程度的贬义、强程度的贬义的五分类任务需要注意情感词、程度词、否定词之间的交互。举一个例子,“这个餐厅脏得不行,没有隔壁好”,这里的“不行”是对“脏”的程度的一种修饰,通过BiLSTM可以更好的捕捉双向的语义依赖。
二、BiLSTM原理简介
2.1 LSTM介绍
2.1.1 总体框架
LSTM模型是由时刻的输入词,细胞状态 ,临时细胞状态,隐层状态,遗忘门,记忆门,输出门组成。LSTM的计算过程可以概括为,通过对细胞状态中信息遗忘和记忆新的信息使得对后续时刻计算有用的信息得以传递,而无用的信息被丢弃,并在每个时间步都会输出隐层状态,其中遗忘,记忆与输出由通过上个时刻的隐层状态和当前输入计算出来的遗忘门,记忆门,输出门来控制。
总体框架如图1所示。
图1. LSTM总体框架
2.1.2 详细介绍计算过程
计算遗忘门,选择要遗忘的信息。
输入:前一时刻的隐层状态,当前时刻的输入词
输出:遗忘门的值
首先将上一时刻(t − 1 t-1t−1时刻)的 隐藏状态的信息 S t − 1 S_{t-1}*S**t*−1 与本时刻(t tt时刻)的数据共同输入Sigmoid 函数,输出的值介于0 ~ 1之间,代表该不该忘记,越接近 0 表示越应该忘记,越接近1 表示越应该记住。最后得到的这个值会与前一时刻的记忆 C t − 1 C_{t-1}*C**t*−1 做乘积运算来限制前面的记忆对后面的影响。
所以,我们可以形象地将 f t f_tf**t 称为: 【过去记忆重要程度的衡量因子】 例如:如果sigmoid 函数输出的结果是:0,就代表当前的上一时刻的隐藏层和这一时刻的输入组成的综合结果是没有任何价值的,那么这个 0 与 C t − 1 C_{t-1}C**t−1 相乘,就会导致前面的信息被遗忘。
遗忘门的运算公式:
f t = σ ( W f ⋅ [ h t − 1 , x t ] + b f ) f_t = \sigma (W_f · [h_{t-1, x_t}]+b_f)f**t=σ(W**f⋅[h**t−1,x**t]+b**f)
公式的意思就是上面文字表述的部分:先将 t tt 时刻的输入 X = [ x 1 , . . . , x t ] X = [x_1,...,x_t]X=[x1,...,x**t]与上一个隐藏层的数据 h t − 1 h_{t-1}h**t−1 进行结合(也就是 <图1> 中的 S SS ),然后再用W f W_fW**f矩阵将其调整成与t tt时刻隐藏层相同的维度,然后加一个 b f b_fb**f 偏置之后经过 s i g m o i d sigmoidsigmoid 函数进行0~1之间的分类。
图2. 计算遗忘门
计算记忆门,选择要记忆的信息。
输入:前一时刻的隐层状态,当前时刻的输入词
输出:记忆门的值,临时细胞状态
图3. 计算记忆门和临时细胞状态
计算当前时刻细胞状态
输入:记忆门的值,遗忘门的值,临时细胞状态,上一刻细胞状态
输出:当前时刻细胞状态
图4. 计算当前时刻细胞状态计算输出门和当前时刻隐层状态
输入:前一时刻的隐层状态,当前时刻的输入词 ,当前时刻细胞状态
输出:输出门的值,隐层状态
小伙伴们有没有发现,咱们这个“输入门”有两条线路组成:
左边的那条经过sigmoid(σ \sigmaσ)函数,美其名曰叫做 i t i_ti**t,但是不知道细心的你是否发现了他与 “遗忘门” 的结构几乎是一样的,那么你想这是为什么呢? 因为它同样只需要产生一个 0~1 的结果就好了,因为后面要与 C t ~ \tilde{C_t}C**t~ 作乘积,做个假设,假如sigmoid结果出来是0, 那无论 C t ~ \tilde{C_t}C**t~ 是什么,都没有输进C t {C_t}C**t 的必要了,所以用乘积的方式来代表输入当前数据的重要程度是很聪明的一种做法。所以我们把左边这条线称作为【输入的重要性因子】
右边那条线和左边那条线输入的数据都是一样的,包括“遗忘门”输入的数据都是一样的,都是 [ h t − 1 ] + x t [h_{t-1}] + x_t[h**t−1]+x**t。不同的是,右边这条线经过的激活函数不是 sigmoid 而是tanh,让我们先来看一下 sigmoid 函数和 tanh 的不同:① sigmoid:图 5 sigmoid 函数可视化图
② tanh:图 6 tanh 函数可视化图
很清楚的发现,sigmoid函数的分布范围在 0 ~ 1,而 tanh 的分布范围是沿着 y 轴对称,所以 tanh 起的作用是压缩输入tanh函数的数值,使其分布在 -1 ~ +1 以调节网络,有类似于数据中心化的效果,使得其收敛速度要比sigmoid快;所以一般再隐藏层使用 tanh 而在输出层使用 sigmoid ;最后与左边处于 0~1 的重要性衡量因子相乘,结果存入 C t C_tC**t。
输入门的运算公式:
i t = σ ( W i ⋅ [ h t − 1 , x t ] + b i ) i_t = \sigma(W_i·[h_{t-1},x_t] + b_i)i**t=σ(W**i⋅[h**t−1,x**t]+b**i)
C t ~ = t a n h ( W C ⋅ [ h t − 1 , x t ] + b C ) \tilde{C_t}=tanh(W_C·[h_{t-1},x_t]+b_C)C**t~=tan**h(W**C⋅[h**t−1,x**t]+b**C)
C t = f t ∗ C t − 1 + i t ∗ C t ~ C_t=f_tC_{t-1}+i_t\tilde{C_t}C**t=f**t∗C**t−1+i**t∗C**t~
图5. 计算输出门和当前时刻隐层状态
如 <图 8> 所示,图中红色的圆圈部分其实已经形成了“新的记忆” C t C_tC**t,C t C_tC**t 不做任何处理,直接输出到下一个单元作为下一个单元的“记忆”。但是,可以很明显的看到,h t h_th**t 与 C t C_tC**t不同,其要输出到下一个LSTM神经细胞单元需要再进行两个步骤:
① 经过 t a n h tanhtan**h函数进行调整② 与上一个时刻的隐藏状态与本时刻输入的综合数据做乘积运算
图中所示的 O t O_tO**t 还是一个介于0~1的值,由h t − 1 h{t-1}h**t−1 和 x t x_tx**t 经过sigmoid 函数算出来的、用来衡量即将要输出的C t C_tC**t 有多少输出的价值,因为毕竟这个 C t C_tC**t 说是根据 h t − 1 h{t-1}h**t−1 和 x t x_tx**t 算出来的,所以同样由这两个因素来决定到底输出多少信息到本神经单元之外。
最终,我们可以得到与句子长度相同的隐层状态序列{, , ..., }。
2.2 BiLSTM介绍
前向的LSTM与后向的LSTM结合成BiLSTM。比如,我们对“我爱中国”这句话进行编码,模型如图6所示。
图6. 双向LSTM编码句子前向的依次输入“我”,“爱”,“中国”得到三个向量{, , }。后向的依次输入“中国”,“爱”,“我”得到三个向量{, , }。最后将前向和后向的隐向量进行拼接得到{[, ], [, ], [, ]},即{, , }。
对于情感分类任务来说,我们采用的句子的表示往往是[, ]。因为其包含了前向与后向的所有信息,如图7所示。
命名实体识别
基于字的Bilstm-CRF模型
以句子为单位,将一个含有 nn 个字的句子(字的序列)记作
x=(x1,x2,...,xn)
模型的第一层是look-up层,即利用预训练的embedding矩阵将每个字的独热编码变为低维的字向量。
第二层是双向LSTM层,自动提取句子特征,