循环神经网络 RNN
之前描述的全连接神经网络(FCN)和卷积神经网络(CNN),其目标数据的样本是不分先后的。
比如下面这句话:
既然“天气不错”,那么做出 “去打球” 这个决策的可能性应该高于“睡懒觉”。
为了获取这一类序列特征,在此基础上,具备记忆机制的循环网络模型,逐渐演进到现在,成为更有效的循环神经网络模型(RNN)。
RNN 是一种特别适合识别带有时间先后顺序的数据的算法模型(比如像是文本、语音信息,还有一些具有前后因果关系的图像数据)。
我们平常用的很多中英文翻译软件(如微信的语音转文字),就使用到了这个算法。 ?
单层RNN
早上好天气,适合(去打球\睡懒觉)。
输入到 RNN 中,会被切分成依次排成的序列:
-
[
早
,
上
,
好
,
天
,
气
,
适
,
合
,
?
?
?
]
[早,上,好,天,气,适,合,···]
[早,上,好,天,气,适,合,???] -
[
x
1
,
x
2
,
?
?
?
,
x
t
]
[x_{1},x_{2},···,x_{t}]
[x1?,x2?,???,xt?]
P.S. 如果有做分词的,那
x
1
x_{1}
x1? 对应的不是一个字,而是一个词。
- 输出:
[
去
,
打
,
球
]
[去,打,球]
[去,打,球]
上图中,
h
t
h_{t}
ht? 组成的一条竖线,称为一个 “时间步”。
-
h
t
h_{t}
ht?:第 t 层元素的激活值(a)
-
x
t
x_{t}
xt?:第 t 个元素
-
W
h
x
W_{hx}
Whx?:x 作为输入来计算 h 时的参数
-
W
h
h
W_{hh}
Whh?:上一步 h 作为输入来计算 h 时的参数
-
W
h
y
W_{hy}
Why?:上一步 h 作为输入来计算 y 时的参数
-
h
0
h_{0}
h0?:一般初始化为零向量,是人为添加的
-
h
1
=
f
(
W
h
x
x
1
+
W
h
h
h
0
+
b
)
h_{1}=f(W_{hx}x_{1}+W_{hh}h_{0}+b)
h1?=f(Whx?x1?+Whh?h0?+b)
-
h
2
=
f
(
W
h
x
x
2
+
W
h
h
h
1
+
b
)
h_{2}=f(W_{hx}x_{2}+W_{hh}h_{1}+b)
h2?=f(Whx?x2?+Whh?h1?+b)
- ···
-
h
t
=
f
(
W
h
x
x
t
+
W
h
h
h
t
?
1
+
b
)
h_{t}=f(W_{hx}x_{t}+W_{hh}h_{t-1}+b)
ht?=f(Whx?xt?+Whh?ht?1?+b)
-
y
t
=
W
h
y
h
t
+
b
y
y_{t}=W_{hy}h_{t}+b_{y}
yt?=Why?ht?+by?
第 1 次处理过程输入是
h
0
、
x
1
h_{0}、x_{1}
h0?、x1?,得到激活值
h
1
h_{1}
h1?。
第 2 次处理过程输入是
h
1
、
x
2
h_{1}、x_{2}
h1?、x2?,得到激活值
h
2
h_{2}
h2?。
也就是说,网络再对第 2 个字(
x
2
x_{2}
x2?)预测的时候,会参考第 1 个字(
x
1
x_{1}
x1?)的信息。
这样一次处理过程,也叫一个时间步,每次输入不同,但后一个时间步的输入是前一个时间步的输出。 ?
双向RNN
如果遇到,下文反过来推理上文的场景就需要双向 RNN,例如:
- 早上难得好天气,适合(去打球/睡懒觉),可别叫醒我。
综合上下文,既然有 “别叫醒我” 跟在后面,显然 “睡懒觉” 的可能性大幅提高。
在这一类需要结合上下文,在正序、倒序两个方向上做推理的场景中,可以通过双向 RNN 结构,加入逆向推理机制。
-
h
i
h_{i}
hi?:表示正向
-
h
i
′
h'_{i}
hi′?:表示反向
同正方向序列上的权值参数一样,逆序列也有权参
W
h
x
′
、
W
h
h
′
、
W
h
y
′
W'_{hx}、W'_{hh}、W'_{hy}
Whx′?、Whh′?、Why′?,相应的参数量和隐藏节点个数扩展到单向模型的两倍。
俩者的区别只在于,计算激活值的方向不同,
h
i
h_{i}
hi? 是从
1
1
1 到
t
t
t,
h
i
′
h'_{i}
hi′? 是从
t
t
t 到
i
i
i。
-
h
t
′
=
f
(
W
h
x
′
x
t
+
W
h
h
′
h
t
?
1
′
+
b
′
)
h'_{t}=f(W'_{hx}x_{t}+W'_{hh}h'_{t-1}+b')
ht′?=f(Whx′?xt?+Whh′?ht?1′?+b′)
- ···
-
h
2
′
=
f
(
W
h
x
′
x
2
+
W
h
h
′
h
1
′
+
b
′
)
h'_{2}=f(W'_{hx}x_{2}+W'_{hh}h'_{1}+b')
h2′?=f(Whx′?x2?+Whh′?h1′?+b′)
-
h
1
′
=
f
(
W
h
x
′
x
1
+
W
h
h
′
h
0
′
+
b
′
)
h'_{1}=f(W'_{hx}x_{1}+W'_{hh}h'_{0}+b')
h1′?=f(Whx′?x1?+Whh′?h0′?+b′)
-
y
t
=
W
h
y
′
h
t
′
+
W
h
y
h
t
+
b
y
y_{t}=W'_{hy}h'_{t}+W_{hy}h_{t}+b_{y}
yt?=Why′?ht′?+Why?ht?+by?
双向 RNN 就不能实现实时检测了,需待整个序列输入完毕后才能预测。 ?
多层RNN
如果遇到更复杂的序列信息,还有什么更进一步的措施来捕捉更丰富的数据特征呢?
CNN 卷积神经网络模型,是靠增加卷积核个数或者增加 Conv-Pool 单元的数量,用更深的卷积过滤器,以及层级更多的网络处理层来捕捉更丰富的特征。
与之对应,RNN 的多层模型,可以通过组合叠加更多的隐藏层来抽取深层的序列特征。
下图是,一个三层四个时间步的 RNN:
-
h
1
=
f
(
W
h
x
x
1
+
W
h
h
h
0
+
b
)
h_{1}=f(W_{hx}x_{1}+W_{hh}h_{0}+b)
h1?=f(Whx?x1?+Whh?h0?+b)
- ···
-
h
1
′
=
f
(
W
h
x
′
x
1
+
W
h
h
′
h
0
′
+
b
′
)
h'_{1}=f(W'_{hx}x_{1}+W'_{hh}h'_{0}+b')
h1′?=f(Whx′?x1?+Whh′?h0′?+b′)
- ···
-
h
t
′
′
=
f
(
W
h
x
′
′
h
t
′
+
W
h
h
′
′
h
t
?
1
′
′
+
b
′
′
)
h''_{t}=f(W''_{hx}h'_{t}+W''_{hh}h''_{t-1}+b'')
ht′′?=f(Whx′′?ht′?+Whh′′?ht?1′′?+b′′)
-
y
t
=
W
h
y
h
t
′
′
+
b
y
y_{t}=W_{hy}h''_{t}+b_{y}
yt?=Why?ht′′?+by?
?
前向传播
前向传播:根据一个输入 x 和一个输入 h(激活值)会生成一个激活值 h 和预测值 y。
-
z
t
=
W
h
x
x
t
+
W
h
h
h
t
?
1
+
b
z_{t}=W_{hx}x_{t}+W_{hh}h_{t-1}+b
zt?=Whx?xt?+Whh?ht?1?+b
-
h
t
=
t
a
n
h
(
z
t
)
h_{t}=tanh(z_{t})
ht?=tanh(zt?)
第 l 层输出:
-
z
t
l
=
W
h
x
l
h
t
l
?
1
+
W
h
h
l
h
t
?
1
+
b
l
z^{l}_{t}=W^{l}_{hx}h^{l-1}_{t}+W^{l}_{hh}h_{t-1}+b^{l}
ztl?=Whxl?htl?1?+Whhl?ht?1?+bl
最后一层输出:
-
y
t
=
f
(
W
h
y
h
t
L
+
b
y
L
)
y_{t}=f(W_{hy}h^{L}_{t}+b^{L}_{y})
yt?=f(Why?htL?+byL?)
以上就是前向传播所有表达式。
将
W
h
x
、
W
h
h
W_{hx}、W_{hh}
Whx?、Whh? 合二为一,拼接成一个新的
W
W
W 权值参数矩阵。
-
W
h
=
[
W
h
x
?
W
h
h
]
W_{h}=[W_{hx}-W_{hh}]
Wh?=[Whx??Whh?]
如
z
t
=
W
h
x
x
t
+
W
h
h
h
t
?
1
+
b
z_{t}=W_{hx}x_{t}+W_{hh}h_{t-1}+b
zt?=Whx?xt?+Whh?ht?1?+b,可以改成
z
t
=
W
[
x
t
,
?
h
t
?
1
]
+
b
z_{t}=W[x_{t},~h_{t-1}]+b
zt?=W[xt?,?ht?1?]+b。 ?
反向传播
每一个时间步都有自己的损失,整个序列的损失就是将每一个时间步的损失累计起来。
反向传播具体图示:在原图上所有箭头,反向,就是反向传播。
?
LSTM 记忆增强
RNN 记性不好,无法记住间隔远的时间步,这就导致无法根据上下文信息来生成语法正确的句子。
记性不好的原因,在于梯度消失(很深的神经网络就容易造成梯度爆炸、消失)。
随着 RNN 的时间步越来越多,就会产生梯度爆炸、消失。
- 梯度爆炸:用梯度修剪即可
- 梯度消失:需要通过 LSTM、GRU 来增强记忆力
LSTM:Long Short Term Memory,长短期记忆。
因为一层比一层的激活值大,那层数深了,积累到一定程度就会发生梯度爆炸。
而如果我们能让前面的激活值直接传递到后面去,就可以避免梯度消失。
LSTM 的方法:在计算激活值时,会引入一些开关,让这些开关来控制当前激活值是否需要被传递到后面去。
RNN 传递的状态只有
h
t
h_{t}
ht?,LSTM 在此基础上,引入了
c
t
c_{t}
ct?。
在每个时间步上,先求
z
z
z:
-
z
=
W
x
x
t
+
W
h
h
t
?
1
+
b
z=W_{x}x_{t}+W_{h}h_{t-1}+b
z=Wx?xt?+Wh?ht?1?+b
再把
z
z
z 拆分为:
- 输入门
i
=
σ
(
z
i
)
i=\sigma(z_{i})
i=σ(zi?)
- 遗忘门
f
=
σ
(
z
f
)
f=\sigma(z_{f})
f=σ(zf?)
- 输出门
o
=
σ
(
z
o
)
o=\sigma(z_{o})
o=σ(zo?)
- 准单元
g
=
t
a
n
h
(
z
g
)
g=tanh(z_{g})
g=tanh(zg?)
最后,计算单元状态和隐状态:
- 单元状态:
c
t
=
f
?
c
t
?
1
+
i
?
g
c_{t}=f*c_{t-1}+i*g
ct?=f?ct?1?+i?g
- 隐状态:
h
t
=
o
?
t
a
n
h
(
c
t
)
h_{t}=o*tanh(c_{t})
ht?=o?tanh(ct?)
整个控制过程,是一系列公式:
-
c
~
t
=
t
a
n
h
(
W
c
[
h
t
?
1
,
?
x
t
]
+
b
c
)
\widetilde{c}_{t}=tanh(W_{c}[h_{t-1},~x_{t}]+b_{c})
c
t?=tanh(Wc?[ht?1?,?xt?]+bc?)
-
Γ
u
=
σ
(
W
u
[
h
t
?
1
,
?
x
t
]
+
b
u
)
\Gamma_{u}=\sigma(W_{u}[h_{t-1},~x_{t}]+b_{u})
Γu?=σ(Wu?[ht?1?,?xt?]+bu?)
-
Γ
f
=
σ
(
W
f
[
h
t
?
1
,
?
x
t
]
+
b
f
)
\Gamma_{f}=\sigma(W_{f}[h_{t-1},~x_{t}]+b_{f})
Γf?=σ(Wf?[ht?1?,?xt?]+bf?)
-
Γ
o
=
σ
(
W
o
[
h
t
?
1
,
?
x
t
]
+
b
o
)
\Gamma_{o}=\sigma(W_{o}[h_{t-1},~x_{t}]+b_{o})
Γo?=σ(Wo?[ht?1?,?xt?]+bo?)
-
c
t
=
Γ
u
?
c
~
t
+
Γ
f
?
c
t
?
1
c_{t}=\Gamma_{u}*\widetilde{c}_{t}+\Gamma_{f}*c_{t-1}
ct?=Γu??c
t?+Γf??ct?1?
-
h
t
=
Γ
o
?
t
a
n
h
?
c
t
h_{t}=\Gamma_{o}*tanh~c_{t}
ht?=Γo??tanh?ct?
逐个解释:
-
c
~
t
=
t
a
n
h
(
W
c
[
a
t
?
1
,
?
x
t
]
+
b
c
)
\widetilde{c}_{t}=tanh(W_{c}[a_{t-1},~x_{t}]+b_{c})
c
t?=tanh(Wc?[at?1?,?xt?]+bc?):RNN 计算激活值公式,输入是前一时间步的激活值
h
h
h、本时间步的输入
x
x
x,与参数
w
、
b
w、b
w、b 运算后,得出本时间步的激活值。
但为了提高 RNN 的记性,不能直接做成激活值,还需要经过三个公式的判断,或成为激活值,或忽略。
-
Γ
u
=
σ
(
W
u
[
h
t
?
1
,
?
x
t
]
+
b
u
)
\Gamma_{u}=\sigma(W_{u}[h_{t-1},~x_{t}]+b_{u})
Γu?=σ(Wu?[ht?1?,?xt?]+bu?)
-
Γ
f
=
σ
(
W
f
[
h
t
?
1
,
?
x
t
]
+
b
f
)
\Gamma_{f}=\sigma(W_{f}[h_{t-1},~x_{t}]+b_{f})
Γf?=σ(Wf?[ht?1?,?xt?]+bf?)
-
Γ
o
=
σ
(
W
o
[
h
t
?
1
,
?
x
t
]
+
b
o
)
\Gamma_{o}=\sigma(W_{o}[h_{t-1},~x_{t}]+b_{o})
Γo?=σ(Wo?[ht?1?,?xt?]+bo?)
这三个变量,又称为:
那 LSTM 是如何控制激活值是否被传递到下一时间步到呢?俩个公式:
-
c
t
=
Γ
u
?
c
~
t
+
Γ
f
?
c
t
?
1
c_{t}=\Gamma_{u}*\widetilde{c}_{t}+\Gamma_{f}*c_{t-1}
ct?=Γu??c
t?+Γf??ct?1?
-
h
t
=
Γ
o
?
t
a
n
h
?
c
t
h_{t}=\Gamma_{o}*tanh~c_{t}
ht?=Γo??tanh?ct?
某些情况下
c
t
?
1
c_{t-1}
ct?1? 代表前一时间步的激活值(
h
t
?
1
h_{t-1}
ht?1?)。
如果此时更新门为
0
0
0,记忆门、输出门为1,那
h
t
=
c
t
?
1
h_{t}=c_{t-1}
ht?=ct?1?,等同
h
t
=
h
t
?
1
h_{t}=h_{t-1}
ht?=ht?1?。
本时间步激活值 = 前一时间步激活值,相当于,前面时间步激活值传递到了下一时间步,且激活值没有增大,就避免了梯度消失。
神经网络通过控制
w
、
b
w、b
w、b 来控制三个门,会决定激活值传递情况:
- 更新门全部打开,记忆门全部关闭,那本时间步就不会与前一时间步的激活值有任何瓜葛
- 更新门、记忆门都各自打开一半,本时间步激活值就是本时间步激活值的一半 + 前一时间步激活值的一半。
LSTM 单个时间步的模型结构:
上图是单个时间步的结构图,多个时间步排列在一起就构成了 RNN。
通过这样的机制,就可以把前面的激活值传递到后面。
比如,小明今天他去打球了,小明和小黑今天他们去打球了。
因为 RNN 记性不好,那他就忘了今天谁去打球了,一个人用他,俩个人用他们,那到底是他还是他们?通过逻辑门的控制,就可以把小明、小明和小黑的激活值直接传送到后面,就知道用他、他们了。 ?
GRU 记忆增强
GRU 其实是 LSTM 的简化版,计算量会少些,但灵活性没 LSTM 好。
LSTM 公式:
-
c
~
t
=
t
a
n
h
(
W
c
[
h
t
?
1
,
?
x
t
]
+
b
c
)
\widetilde{c}_{t}=tanh(W_{c}[h_{t-1},~x_{t}]+b_{c})
c
t?=tanh(Wc?[ht?1?,?xt?]+bc?)
-
Γ
u
=
σ
(
W
u
[
h
t
?
1
,
?
x
t
]
+
b
u
)
\Gamma_{u}=\sigma(W_{u}[h_{t-1},~x_{t}]+b_{u})
Γu?=σ(Wu?[ht?1?,?xt?]+bu?)
-
Γ
f
=
σ
(
W
f
[
h
t
?
1
,
?
x
t
]
+
b
f
)
\Gamma_{f}=\sigma(W_{f}[h_{t-1},~x_{t}]+b_{f})
Γf?=σ(Wf?[ht?1?,?xt?]+bf?)
-
Γ
o
=
σ
(
W
o
[
h
t
?
1
,
?
x
t
]
+
b
o
)
\Gamma_{o}=\sigma(W_{o}[h_{t-1},~x_{t}]+b_{o})
Γo?=σ(Wo?[ht?1?,?xt?]+bo?)
-
c
t
=
Γ
u
?
c
~
t
+
Γ
f
?
c
t
?
1
c_{t}=\Gamma_{u}*\widetilde{c}_{t}+\Gamma_{f}*c_{t-1}
ct?=Γu??c
t?+Γf??ct?1?
-
h
t
=
Γ
o
?
t
a
n
h
?
c
t
h_{t}=\Gamma_{o}*tanh~c_{t}
ht?=Γo??tanh?ct?
GRU 公式:
-
c
~
t
=
t
a
n
h
(
W
c
[
Γ
r
?
c
t
?
1
,
?
x
t
]
+
b
c
)
\widetilde{c}_{t}=tanh(W_{c}[\Gamma_{r}*c_{t-1},~x_{t}]+b_{c})
c
t?=tanh(Wc?[Γr??ct?1?,?xt?]+bc?)
-
Γ
u
=
σ
(
W
u
[
c
t
?
1
,
?
x
t
]
+
b
u
)
\Gamma_{u}=\sigma(W_{u}[c_{t-1},~x_{t}]+b_{u})
Γu?=σ(Wu?[ct?1?,?xt?]+bu?)
-
Γ
r
=
σ
(
W
r
[
c
t
?
1
,
?
x
t
]
+
b
r
)
\Gamma_{r}=\sigma(W_{r}[c_{t-1},~x_{t}]+b_{r})
Γr?=σ(Wr?[ct?1?,?xt?]+br?)
-
c
t
=
Γ
u
?
c
~
t
+
(
1
?
Γ
u
)
?
c
t
?
1
c_{t}=\Gamma_{u}*\widetilde{c}_{t}+(1-\Gamma_{u})*c_{t-1}
ct?=Γu??c
t?+(1?Γu?)?ct?1?
-
h
t
=
c
t
h_{t}=c_{t}
ht?=ct?
对比俩者,发现控制逻辑门的公式少了一个,逻辑门的数量也从 3 个变成了 2 个,GRU 传递的是
c
c
c,而不是
h
h
h,但最后的公式指明了俩者相等。 ?
意念打字
脑控打字至少要分成3步:1.采集并翻译脑电信号;2.转换成指令;3.打字。
RNN 解决的是第 2 步。
在训练的时候,研究人员会请受试者大声阅读大量的句子,比如说读一些小孩子的故事书,像《睡美人》《爱丽丝梦游仙境》这些经典小人书,而后他们把脑电信号和语言的转化工作分成两步。
当数据有复杂时间结构的时候,RNN 绝对是个利器。
放在这里,RNN 可以解码声道咬合关节运动,把这些运动转化成句子。
?
自然语言处理
?
词嵌入
让神经网络理解词之间的关系,如男人和女人、苹果和橘子、汽车和卡车。
我们会用到一种叫词嵌入,会赋予词汇属性,如性别、高贵、年龄、食物。
- man (男人)性别特性为 -1
- woman(女人)性别特性为 1
- king(皇帝)性别特性为 -0.95(女皇帝很少如武则天)
- Queen(皇后)性别特性为 0.97(有变性)
- apple(苹果)性别特性为 0(中性)
通过这些特性,我们就可以发现关系紧密的词。
词嵌入让神经网络举一反三。如:
- Robert Lin is an apple farmer.(Robert Lin 是一个种苹果的农民)
- Sally Johnson is a durian cultivator.(Sally Johnson是一个榴莲培育家)
但是神经网络词汇表里没有 Sally Johnson 这个词,神经网络不知道是人名,还是公司名。
但通过前一句 Robert Lin 是一个种苹果的农民,神经网络就可以根据苹果和榴莲都是水果的关系,推断出 Sally Johnson 是一个人名。
具体来说,迁移学习 + 词嵌入技术。
我们在网上下载训练完成的词嵌入模型,再通过迁移学习应用到自己的项目中。 ?
类比推理
创造类比本身就是难度很高的活动,一般人做不来:
于是,创造一个 “精妙的类比” 是很非常复杂的过程,所花费的精力不知要比听者理解所需要的精力多不知道多少倍…… 极为恰当的类比,常常只不过是 “妙手偶得之”,而想要再找一个 “旗鼓相当” 的就几乎不可能了。
要说信息储备,神经网络在这方面独一无二,那我们用词嵌入实现类推:
词嵌入模型眼中词与词之间的关系变得更深了,以至于你可以做一些逻辑上的加减法运算。比如说
你猜等于什么?罗马。
巴黎跟法国的最常见关系是法国的首都,巴黎 - 法国,大约就是去除法国元素但是保留首都元素;再加上意大利,那就是首都加意大利,也就是意大利首都罗马。
类似的例子还有
如果我们用:
- 男人 - 女人 =
[
?
2
,
?
0
,
?
0
,
?
0
]
[-2,~0,~0,~0]
[?2,?0,?0,?0]
- 皇帝 - 皇后 =
[
?
2
,
?
0
,
?
0
,
?
0
]
[-2,~0,~0,~0]
[?2,?0,?0,?0]
发现俩个向量式子的结果一样,这也就是类比的逻辑所在。
第 1 个元素代表性别,也就是说,男人和女人、皇帝和皇后最大的区别在于性别。
所以,就产生了:
矩阵表
在没有词嵌入前,我们会整理一份词典,所有词都有一个索引位置。
如 man 是 5391,woman 是 9853,king 是 4914。
这种一对一的对应的词汇关系,存储和访问是最优的,但无法向词嵌入那样表示词语之间的相似性。
神经网络已经知道:
I want a glass of orange juice.
之后再给神经网络一个句子:
I want a glass of apple __.
咱肯定想到也可以填 juice 啊,因为你知道 orange 与 apple 都是水果,TA们在某种意义上有相似性。
但如果我们使用的是 one-hot 形式(以上形式)对词进行编码的话,我们完全无法根据词向量来计算词与词之间的相似性,而两个 one-hot 词向量的内积永远也等于 0。
词嵌入就在此基础上,引入了特性来描述不同词汇之间的相似性。
立场对人工智能来说,只是一组多维度的坐标值(向量)而已。
简单来说就是把个体所有的属性全部列出来打分,好比吃甜豆腐脑 = 10,吃咸豆腐脑 = -10,民主党 = 10,共和党 = -10 等等,而且这个立场向量不需要手工录入,只要把您所有的言行,写过的文章给机器学习一下,就能得出比咱们自己的感知更细致的立场。
这个过程就是建立一个矩阵表。
词嵌入是这么建立矩阵表的:
-
o
1
o_{1}
o1?:one-hot 向量编号,每个单词对应一个 one-hot 向量,如 I 对应 9665。
- E 是嵌入矩阵表,可以通过构建自然语言模型,运用梯度下降算法得到。最开始矩阵表的特性都是随机值,这些特性会被神经网络不断训练。
- e 是词嵌入向量,每一个 one-hot 向量与词嵌入矩阵表运算后,得到对应的词嵌入向量。
这些词嵌入向量会传递给后面的神经网络,最终通过 softmax 来预测结果。
如果预测错了,损失就大,神经网络就会调整参数 w、b 以及矩阵表 E 来使损失越来越小。 ?
Word2Vec
Word2Vec:把单词转换为词嵌入向量的模型。
转换的基本原理,就是上面的。
具体实现 Word2Vec 有俩种方法:
假设算例是:I want a glass of orange juice.
如果我们要预测 juice,那需要将前 4 个单词 a glass of orange 输入到模型中训练。
- 这 4 个单词称为上下文词的 context words
Skip gram 独特一些,是从句子中随机选取一个单词作为 context words,如 orange。
再从 orange 附近随机选,假设选了 juice。
- 输入x:orange(context)
- 标签y:juice(target)
附近的选取范围是自定义的,如设置为 4,就是在 orange 前后 4 个单词内随机选取。
context-target 不仅仅会有 orange-juice,还有很多词对,orange-glass 等等。
- context word:句子中选一个词
- target word:词周围选一个词
有了大量的词对后,就用之前的方法训练词嵌入矩阵。
-
o
i
?
?
>
?
E
?
?
>
?
e
i
?
?
>
?
s
o
f
t
m
a
x
?
?
>
?
y
^
o_{i} ~->~E ~->~e_{i} ~->~softmax ~->~\hat{y}
oi???>?E??>?ei???>?softmax??>?y^?
我们将 content word 对应的 one-hot 向量
o
i
o_{i}
oi? 作为输入 x,这个向量会与词嵌入矩阵表 E 进行矩阵相乘,而后得到相应的词嵌入向量
e
i
e_{i}
ei?。
最终 softmax 会给出预测值,如果这个预测值与 target word 不一致,模型就会更新矩阵表数值。
不断学习下,最终词嵌入矩阵表每个单词都有合理的特性。 ?
负采样
输入一个 context word,softmax 来预测词库中每个单词是 target word 的概率。
softmax 计算量很大,我们可以用 sigmoid 代替 softmax。
构建出一个词对后,用 sigmoid 判断这对词是否有关联,如 orange-juice。
如果存在关联,标签
y
y
y 是1,反之,为 0。
标签为 1 的词对称为正采样,为 0 称为负采样。
如何选取负样本?
- 一般小数据集,选择 5-20 个负采样。
- 一般大数据集,选择 2-5 个负采样。
?
GLOVE模型
GLOVE 也是训练词嵌入向量的模型,词与词之间共现的统计数据可作为训练词嵌入向量的重要依据。
- 先用语料库统计词的共现矩阵
- 再基于共现矩阵和模型学习词向量
共现矩阵是啥呢?
设共现矩阵为 X,其元素为
X
i
j
X_{i}{j}
Xi?j。
X
i
j
X_{ij}
Xij?:在语料库中,单词
i
i
i 和 单词
j
j
j 共同出现在一个窗口中的次数。 ?
情感分类
情感分类任务就是看一段文本,然后分辨这个人是否喜欢他们在讨论的这个东西,这是NLP中最重要的模块之一,经常用在许多应用中。
情感分类一个最大的挑战就是可能标记的训练集没有那么多,但是有了词嵌入,即使只有中等大小的标记的训练集,你也能构建一个不错的情感分类器,让我们看看是怎么做到的。
输入x是一段文本,而输出y是你要预测的相应情感。比如餐馆评价:
-
“The dessert is excellent.”(甜点很棒),并给出了四星的评价; -
“Service was quite slow”(服务太慢),两星评价; -
“Good for a quick meal but nothing special”(适合吃快餐但没什么亮点),三星评价; -
“Completely lacking in good taste, good service and good ambiance.”(完全没有好的味道,好的服务,好的氛围),给出一星评价。
如果你能训练一个从x到y的映射,基于这样的标记的数据集,那么你就可以用来搜集大家对你运营的餐馆的评价。
咱们来看看是怎么实现情感分类的:
每个单词的 one-hot 向量与词嵌入矩阵相乘后,得到词嵌入向量。
对所有词嵌入向量求平均值,再输入到 softmax 中,softmax 会给出 5 份概率(1-5星)。
但平均值有个缺点,忽略句子中词汇的顺序。
如 Completely lacking in good taste, good service and good ambiance.(完全没有好的味道,好的服务,好的氛围),给出一星评价。
虽然也有 lacking(缺乏),但句子中出现多个 good,所以整个句子的平均值就会偏好评。
为了解决这个问题,我们会配合对能识别顺序的 RNN 一起。
将句子中的每个词一步步的输入到 RNN 中去,这个模型就学会在 good 前面还有一个 lacking。 ?
序列模型和注意力机制
基础模型
从最基础的模型 seq2seq 开始,seq2seq 是 RNN 后面再接一个 RNN。
比如,我们把法文翻译成英文:
- 法文:Jane visite I’Afrique en septembre.
- 英文:Jane is visiting Africa in September.
我们用 seq2seq 模型实现翻译。
?
?
|