Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
D_ACMER
apachecn-dl-zh
提交
a81772b0
A
apachecn-dl-zh
项目概览
D_ACMER
/
apachecn-dl-zh
与 Fork 源项目一致
Fork自
OpenDocCN / apachecn-dl-zh
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
A
apachecn-dl-zh
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
a81772b0
编写于
1月 08, 2021
作者:
W
wizardforcel
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
2021-01-08 21:01:59
上级
e9fb3bb8
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
24 addition
and
24 deletion
+24
-24
new/handson-dl-arch-py/6.md
new/handson-dl-arch-py/6.md
+24
-24
未找到文件。
new/handson-dl-arch-py/6.md
浏览文件 @
a81772b0
...
...
@@ -26,11 +26,11 @@
如上图所示,来自先前时间点的数据进入了当前时间点的训练。 循环架构使模型可以很好地与时间序列(例如产品销售,股票价格)或顺序输入(例如文章中的单词-DNA 序列)配合使用。
假设我们在传统的神经网络中有一些输入
!
[](
img/89abe3fc-669d-415f-b6be-dc388be531b0.png
)
(其中
`t`
代表时间步长或顺序顺序),如下图所示。 假设不同
`t`
处的输入彼此独立。 可以将任何时间的网络输出写为!
[](
img/ab8c4ddc-5802-427a-b1ba-688f8c0f8fa0.png
)
,如下所示:
假设我们在传统的神经网络中有一些输入
`x[t]`
(其中
`t`
代表时间步长或顺序顺序),如下图所示。 假设不同
`t`
处的输入彼此独立。 可以将任何时间的网络输出写为
`h[t] = f(x[t])`
,如下所示:
![](
img/b84d3a24-c102-4c42-ad72-7ad5a000340f.png
)
在 RNN 中,反馈回路将当前状态的信息传递到下一个状态,如下图的网络展开版本所示。 RNN 网络在任何时间的输出都可以写成
!
[](
img/c1fb0b1b-45bd-4f39-910f-5f24a490db48.png
)
。 对序列的每个元素执行相同的任务!
[](
img/0bd9ccf4-cf74-4a99-aaa9-14a3d576b8f4.png
)
,并且输出!
[](
img/374e5ca2-4893-4ccd-a1c6-088c6160a0b8.png
)
取决于先前计算的输出!
[](
img/b0cecbb7-a627-4b43-bab8-b08f97d15ede.png
)
。 得益于这种类似链的架构,或到目前为止所计算出的额外的
*存储器*
捕获,在将 RNN 应用于时间序列和序列数据方面取得了巨大的成功。 在将 RNN 的变体应用于各种问题之前,首先,我们将了解 RNN 的历史及其演变路径:
在 RNN 中,反馈回路将当前状态的信息传递到下一个状态,如下图的网络展开版本所示。 RNN 网络在任何时间的输出都可以写成
`h[t] = f(h[t-1], x[t])`
。 对序列的每个元素执行相同的任
`f`
,并且输出
`h[t]`
取决于先前计算的输出
`h[t-1]`
。 得益于这种类似链的架构,或到目前为止所计算出的额外的
*存储器*
捕获,在将 RNN 应用于时间序列和序列数据方面取得了巨大的成功。 在将 RNN 的变体应用于各种问题之前,首先,我们将了解 RNN 的历史及其演变路径:
![](
img/1c4993f9-b13d-411a-a330-9c7a332bf4e3.png
)
...
...
@@ -92,16 +92,16 @@ RNN 可以分为*多对一*,*一对多*,*多对多*(同步)和*多对多
![](
img/0c393218-eae9-42f3-a09e-bf404ddf0682.png
)
这里,
`U`
是连接输入层和隐藏层的权重,
`V`
是隐藏层和输出层之间的权重,
`W`
是循环层,即反馈层的权重;
!
[](
img/0629c3d2-74ed-49e2-96bb-1520132d63dc.png
)
是时间步
`t`
的隐藏状态,!
[](
img/659a5e6b-9562-4e50-b27a-6e9328a9f71b.png
)
和!
[](
img/37ae4f9d-2015-4f14-8ab2-ab9ad5089969.png
)
分别是时间步
`t`
的输入和输出。
这里,
`U`
是连接输入层和隐藏层的权重,
`V`
是隐藏层和输出层之间的权重,
`W`
是循环层,即反馈层的权重;
`s[t]`
是时间步
`t`
的隐藏状态,
`x[t]`
和
`h[t]`
分别是时间步
`t`
的输入和输出。
请注意,为简便起见,我们从现在开始仅使用一个循环层,但是我们可以将多个循环层堆叠在一起,我们将很快看到。
层之间的关系可以描述如下:
*
基于当前输入
!
[](
img/2040af3e-d1dc-44dc-92dc-a3f919bd1eaa.png
)
和通过!
[](
img/562308e5-cbaa-4ff7-9b79-bd683a4011bd.png
)
的先前隐藏状态!
[](
img/383bc003-23ee-43db-9fa1-59937dbe7657.png
)
计算时间步长
`t`
和!
[](
img/54984d48-521b-41b9-9685-b73dce04345f.png
)
的隐藏状态,其中
`a`
是激活函数。 RNN 中隐藏层的激活函数的典型选择包括 tanh 和 ReLU。
*
同样,
!
[](
img/70c19fab-defe-4e68-909f-f6211104a2c7.png
)
取决于!
[](
img/c9869f70-3cd8-4f6e-93bc-550caa70f200.png
)
,依此类推。 !
[](
img/024ed476-77bb-45bd-9b60-8608e00ad27e.png
)
也依赖于!
[](
img/c9307527-4369-491f-a419-a486f8f49795.png
)
,按照惯例,该!
[](
img/c9307527-4369-491f-a419-a486f8f49795.png
)
设置为全零。
*
基于当前输入
`x[t]`
和通过
`s[t] = a(U x[t] + W s[t-1])`
的先前隐藏状态
`s[t-1]`
计算时间步长
`t`
和
`s[t]`
的隐藏状态,其中
`a`
是激活函数。 RNN 中隐藏层的激活函数的典型选择包括 tanh 和 ReLU。
*
同样,
`s[t-1]`
取决于
`s[t-2]: s[t-1] = a(U x[t] + W s[t-2])`
,依此类推。
`s[1]`
也依赖于
`s[0]`
,按照惯例,该
`s[0]`
设置为全零。
*
由于对时间步长具有这种依赖性,因此可以将隐藏状态视为网络的内存,从以前的时间步长中捕获信息。
*
将时间步长
`t`
的输出计算为
!
[](
img/450661ff-68a5-4ba1-a496-4311c409ad7e.png
)
,其中
`g`
是激活函数。 根据执行的任务,它可以是用于二进制分类的 Sigmoid 函数,用于多类分类的 softmax 函数以及用于回归的简单线性函数。
*
将时间步长
`t`
的输出计算为
`h[t] = g(V s[t])`
,其中
`g`
是激活函数。 根据执行的任务,它可以是用于二进制分类的 Sigmoid 函数,用于多类分类的 softmax 函数以及用于回归的简单线性函数。
与传统的神经网络类似,所有的权重
`U`
,
`V`
和
`W`
均使用反向传播算法进行训练。 但是不同之处在于,在当前时间
`t`
上,我们需要计算除当前时间之外的所有先前
`t-1`
个时间步的损耗。 这是因为权重由所有时间步共享,并且一个时间步的输出间接依赖于所有先前的时间步,例如权重的梯度。 例如,如果要计算时间步
`t = 5`
的梯度,则需要向后传播前四个时间步,并对五个时间步的梯度求和。 这种特殊的反向传播算法称为
**时间上的反向传播(BPTT)**
。
...
...
@@ -431,20 +431,20 @@ LSTM 的架构的神奇之处在于:在普通循环单元的顶部,增加了
在上图中从左到右,主要组成部分说明如下:
*
!
[](
img/d2eddb1c-c3ef-49c6-810f-28dc26e845eb.png
)
是
**存储单元**
,它从输入序列的最开始就存储上下文。
*
`f`
表示
**遗忘门**
,它控制来自前一存储状态
!
[](
img/ae610622-83d8-4566-a185-a21c8466adb2.png
)
的多少信息可以向前传递。 与遗忘门相关的权重包括
`W[f]`
,它与先前的隐藏状态
`S[t-1]`
连接,和
`u[f]`
,它与当前输入
`x[t]`
连接。
*
`i`
代表
**输入门**
,它确定当前输入可以通过多少信息。 权重
!
[](
img/8cd433d7-2c2f-4642-a2e8-7ddf1183a5dc.png
)
和!
[](
img/148eead3-586f-48da-aa64-d1a420cf60a2.png
)
分别将其与先前的隐藏状态和当前输入相连。
*
**tanh**
只是隐藏状态的激活函数,并且基于当前输入
!
[](
img/a1163f30-f030-4a68-bef6-f1dc1e0af040.png
)
和先前的隐藏状态!
[](
img/c3fdb075-55bf-414d-87a6-7ab49d707585.png
)
及其相应的权重!
[](
img/385579ed-f3c0-4acd-9235-470929e0ad56.png
)
和!
[](
img/55810aa2-f8f7-4e8f-a33a-ed7b829e01c1.png
)
进行计算。 它与原始 RNN 中的
`a`
完全相同。
*
`o`
用作
**输出门**
,它定义了将内部存储器中的多少信息用作整个循环单元的输出。 同样,
!
[](
img/6f080896-cb2d-48a6-8b99-1f850b583c7f.png
)
和!
[](
img/9c6a729e-ea1c-44e8-b39d-4a42a525aa43.png
)
是关联的权重。
*
`c[t]`
是
**存储单元**
,它从输入序列的最开始就存储上下文。
*
`f`
表示
**遗忘门**
,它控制来自前一存储状态
`c[t-1]`
的多少信息可以向前传递。 与遗忘门相关的权重包括
`W[f]`
,它与先前的隐藏状态
`S[t-1]`
连接,和
`u[f]`
,它与当前输入
`x[t]`
连接。
*
`i`
代表
**输入门**
,它确定当前输入可以通过多少信息。 权重
`W[i]`
和
`U[i]`
分别将其与先前的隐藏状态和当前输入相连。
*
**tanh**
只是隐藏状态的激活函数,并且基于当前输入
`x[t]`
和先前的隐藏状态
`s[t-1]`
及其相应的权重
`W[c]`
和
`U[c]`
进行计算。 它与原始 RNN 中的
`a`
完全相同。
*
`o`
用作
**输出门**
,它定义了将内部存储器中的多少信息用作整个循环单元的输出。 同样,
`W[o]`
和
`U[o]`
是关联的权重。
因此,这些组件之间的关系可以概括如下:
*
在时间步
`t`
处的遗忘门
`f`
的输出被计算为
!
[](
img/dfc4bb4b-8495-41d9-a584-5ace7802685f.png
)
。
*
将在时间步
`t`
处输入门
`i`
的输出计算为
!
[](
img/02cc7c8f-f9cc-4bbd-9829-51537291a0f0.png
)
。
*
将在时间步
`t`
处的 tanh 激活
`c'`
的输出计算为
!
[](
img/438dd210-3f36-4e25-a625-a95ab8da7b02.png
)
。
*
在时间步
`t`
处的输出门
`o`
的输出被计算为
!
[](
img/57472460-64d3-48e7-8fb8-af2371057ee6.png
)
。
*
在时间步
`t`
处的存储单元
!
[](
img/1fb2797f-7135-4aba-beb0-9fcea0fe85fb.png
)
由!
[](
img/01cf9cf7-8de2-40fc-960e-ce2e0d9d4936.png
)
更新,其中
`.*`
表示逐元素乘法。 值得注意的是,
`f`
和
`i`
中的 Sigmoid 函数将其输出转换为从
`0`
到
`1`
的范围,从而控制分别通过的先前存储器
`c[t - 1]`
和当前存储器输入
`c'`
的数据比例。
*
最后,在时间步
`t`
的隐藏状态
!
[](
img/c4c7aecc-d631-4158-82cd-b718759d5e5d.png
)
被更新为!
[](
img/4f00cc4c-ed31-48a5-932b-9590c070e0dd.png
)
。 同样,
`o`
确定用作整个单元输出的更新存储单元!
[](
img/8a8220aa-1249-47c5-a5a9-481a95a274e2.png
)
的比例。
*
在时间步
`t`
处的遗忘门
`f`
的输出被计算为
`f = sigmoid(U[f] x[t] + W[f] s[t-1])`
。
*
将在时间步
`t`
处输入门
`i`
的输出计算为
`i = sigmoid(U[i] x[t] + W[i] s[t-1])`
。
*
将在时间步
`t`
处的 tanh 激活
`c'`
的输出计算为
`c' = sigmoid(U[c] x[t] + W[c] s[t-1])`
。
*
在时间步
`t`
处的输出门
`o`
的输出被计算为
`o = sigmoid(U[o] x[t] + W[o] s[t-1])`
。
*
在时间步
`t`
处的存储单元
`c[t]`
由
`c[t] = f .* c[t-1] + i .* c'`
更新,其中
`.*`
表示逐元素乘法。 值得注意的是,
`f`
和
`i`
中的 Sigmoid 函数将其输出转换为从
`0`
到
`1`
的范围,从而控制分别通过的先前存储器
`c[t - 1]`
和当前存储器输入
`c'`
的数据比例。
*
最后,在时间步
`t`
的隐藏状态
`s[t]`
被更新为
`s[t] = o .* c[t]`
。 同样,
`o`
确定用作整个单元输出的更新存储单元
`c[t]`
的比例。
使用随时间的反向传播训练所有四组权重
`U`
和
`W`
,这与原始 RNN 相同。 通过学习三个信息门的权重,网络显式地对长期依赖关系进行建模。 接下来,我们将利用 LSTM 架构并发明更强大的文本生成器。
...
...
@@ -567,10 +567,10 @@ Epoch 251/300
上图中从左到右的关键组件说明如下:
*
`r`
表示
**复位门**
,它控制要忘记前一存储器
!
[](
img/a21e1deb-e75d-4193-9432-501b4a6ec3a9.png
)
的多少信息。 给定连接到先前隐藏状态!
[](
img/bd1fb43d-b4d5-4f34-91f4-6b4bcba74e2d.png
)
的权重!
[](
img/26a4ccef-544d-4862-823a-597620a237f3.png
)
和连接到当前输入!
[](
img/6ef9bee8-6dd8-4dfe-be58-2199ae86baf9.png
)
的!
[](
img/94f32772-c2dd-4f7f-881e-859d4af214ae.png
)
,复位门
`r`
的输出在时间步
`t`
计算为!
[](
img/6339bc02-8da3-4c8a-8d9e-be8188fa7ef3.png
)
。
*
`p`
代表
**更新门**
,它确定可以从前一个内存中传递多少信息。 将权重
!
[](
img/9b065883-35f9-4d94-877e-cd880c60465d.png
)
和!
[](
img/b6998aa5-8213-474f-a37e-b7289e045be0.png
)
分别连接到先前的存储状态和当前输入,将时间
`t`
的更新门
`p`
的输出计算为!
[](
img/db52d7e2-4126-479e-b98e-70cdada21c9a.png
)
。
*
**tanh**
是隐藏状态的激活函数,并基于当前输入
!
[](
img/654ee17e-32b3-4327-b956-ff22ebd8ef7b.png
)
和先前存储状态的重置进行计算。 给定它们的相应权重!
[](
img/d5bc4167-0b59-4e20-9a17-fff19fd23de5.png
)
和!
[](
img/747037b6-52b8-420d-b26f-50c3cc5b641a.png
)
,将当前存储器
`c'`
在时间步
`t`
的输出计算为!
[](
img/f44dabd4-8d26-47eb-b5ae-a4e899b10a11.png
)
。
*
最后,在时间步
`t`
的隐藏状态
!
[](
img/4aa12099-9314-411a-a919-5af2beae170e.png
)
被更新为!
[](
img/d105d076-6e63-4124-aa61-3318d267a0f0.png
)
。 同样,
`p`
决定用于更新当前内存的先前内存的比例–越接近
`1`
,则保留的内存就越多; 距离
`0`
越近,发生的当前存储器越多。
*
`r`
表示
**复位门**
,它控制要忘记前一存储器
`s[t-1]`
的多少信息。 给定连接到先前隐藏状态
`s[t-1]`
的权重
`W[r]`
和连接到当前输入
`x[t]`
的
`U[r]`
,复位门
`r`
的输出在时间步
`t`
计算为
`r = sigmoid(U[r] x[t] + W[r] s[t-1])`
。
*
`p`
代表
**更新门**
,它确定可以从前一个内存中传递多少信息。 将权重
`W[p]`
和
`U[p]`
分别连接到先前的存储状态和当前输入,将时间
`t`
的更新门
`p`
的输出计算为
`p = sigmoid(U[p] x[t] + W[p] s[t-1])`
。
*
**tanh**
是隐藏状态的激活函数,并基于当前输入
`x[t]`
和先前存储状态的重置进行计算。 给定它们的相应权重
`W[c]`
和
`U[c]`
,将当前存储器
`c'`
在时间步
`t`
的输出计算为
`c = tanh(U[c] x[t] + W[c] (r .* s[t-1]))`
。
*
最后,在时间步
`t`
的隐藏状态
`s[t]`
被更新为
`s[t] = (1 - p) .* c' + p .* s[t-1]`
。 同样,
`p`
决定用于更新当前内存的先前内存的比例–越接近
`1`
,则保留的内存就越多; 距离
`0`
越近,发生的当前存储器越多。
*
有趣的是,如果
`p`
是全零向量,而
`r`
是全一向量(例如我们没有明确保留任何先前的内存),则该网络只是一个普通的 RNN。
总体而言,GRU 与 LSTM 非常相似。 它们都使用光栅机制进行长期建模,并且与门相关的参数通过 BPTT 进行训练。 但是,有一些区别值得注意:
...
...
@@ -578,7 +578,7 @@ Epoch 251/300
*
LSTM 中有三个信息门,而 GRU 中只有两个。
*
GRU 中的更新门负责输入门和 LSTM 中的遗忘门。
*
GRU 中的重置门直接应用于先前的隐藏状态。
*
LSTM 显式地对存储单元
!
[](
img/61f52a9f-668d-4147-b035-94fa2cade1fb.png
)
进行建模,而 GRU 则不。
*
LSTM 显式地对存储单元
`c[t]`
进行建模,而 GRU 则不。
*
附加的非线性将应用于 LSTM 中更新的隐藏状态。
*
LSTM 于 1997 年推出,近年来已得到研究和广泛使用。 GRU 于 2014 年发明,至今尚未得到充分的探索。 这就是为什么 LSTM 比 GRU 更受欢迎的原因,即使不能保证一个 LSTM 胜过另一个。
*
通常认为,与 GSTM 相比,训练 GRU RNN 相对更快并且需要更少的数据,因为 GRU RNN 具有较少的参数。 因此,有人认为 GRU 在训练量较小的情况下效果更好。
...
...
@@ -659,7 +659,7 @@ DJIA 由 30 只大型和重要股票(例如 Apple,IBM,GE 和 Goldman Sachs
>>>
Y_test
=
Y
[
train_n
:]
```
我们现在可以开始对训练数据进行建模吗? 当然不需要-需要数据缩放或预处理。 从上图可以看出,测试数据与训练数据不成比例,更不用说将来的数据了。 回归模型无法预测超出范围的值。 为了解决这个问题,我们通常使用最大最小缩放
!
[](
img/59f9afb3-b83d-4d93-9481-eb6595fafe7d.png
)
将数据缩放到给定范围,例如 0 到 1。 但是,没有可靠的方法来预测股票的!
[](
img/c83a79f1-f415-4cce-9ff7-dfb8ea639122.png
)
(或!
[](
img/07311e70-4ece-4170-8c85-d492a7815b82.png
)
)
。 这与已知最小值和最大值(例如,图像预测中的 0 和 255)的情况不同。 为了解决这个问题,我们将每个窗口内的价格标准化。 我们只需将时间窗口中的每个价格除以最近的已知价格即可。 再次使用前面的
`T = 5`
示例,我们可以如下预处理训练样本:
我们现在可以开始对训练数据进行建模吗? 当然不需要-需要数据缩放或预处理。 从上图可以看出,测试数据与训练数据不成比例,更不用说将来的数据了。 回归模型无法预测超出范围的值。 为了解决这个问题,我们通常使用最大最小缩放
`x_scaled = (x - x_min) / (x_max / x_min)`
将数据缩放到给定范围,例如 0 到 1。 但是,没有可靠的方法来预测股票的
`x_max`
(或
`x_min`
。 这与已知最小值和最大值(例如,图像预测中的 0 和 255)的情况不同。 为了解决这个问题,我们将每个窗口内的价格标准化。 我们只需将时间窗口中的每个价格除以最近的已知价格即可。 再次使用前面的
`T = 5`
示例,我们可以如下预处理训练样本:
|
**输入**
|
**输出**
|
| --- | --- |
...
...
@@ -822,7 +822,7 @@ He said, "Machine __ combines computer science and statistics."
![](
img/4ee06bf0-c7d5-426e-a033-fff39a4b4629.png
)
在此,
!
[](
img/08f9b1f1-40af-48d3-88e3-6f77d257ca5f.png
)
和!
[](
img/d14717c4-cbb8-4ab1-91b8-b580f9d7d6b4.png
)
分别表示正向和反向递归层。 它们连接在一起,形成隐藏层!
[](
img/6272d6fe-ea90-4f70-92aa-d45bc73040c0.png
)
,并保留来自过去和将来状态的信息。
在此,
`f ->`
和
`f <-`
分别表示正向和反向递归层。 它们连接在一起,形成隐藏层
`f`
,并保留来自过去和将来状态的信息。
当需要并提供完整的上下文(包括过去和将来的信息)时,BRNN 特别有用。 例如,在词性标记,实体识别或手写识别中,可以通过了解当前单词或字母之后的单词或字母来提高性能。 其他出色的用例包括语音识别,机器翻译和图像字幕。
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录