Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenDocCN
d2l-zh
提交
cf6a8dc5
D
d2l-zh
项目概览
OpenDocCN
/
d2l-zh
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
d2l-zh
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
cf6a8dc5
编写于
8月 22, 2018
作者:
M
muli
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
update lstm
上级
d538969f
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
21 addition
and
48 deletion
+21
-48
chapter_recurrent-neural-networks/lstm.md
chapter_recurrent-neural-networks/lstm.md
+21
-48
未找到文件。
chapter_recurrent-neural-networks/lstm.md
浏览文件 @
cf6a8dc5
...
...
@@ -6,13 +6,12 @@
## 长短期记忆
我们先介绍长短期记忆的设计。它修改了循环神经网络隐藏状态的计算方式,并引入了
与隐藏状态形状相同的记忆细胞(某些文献把记忆细胞当成一种特殊的隐藏状态),从而记录额外的历史信息。
LSTM 中引入了三个门:输入门(input gate)、遗忘门(forget gate)和输出门(output gate);以及
与隐藏状态形状相同的记忆细胞(某些文献把记忆细胞当成一种特殊的隐藏状态),从而记录额外的历史信息。
### 输入门、遗忘门和输出门
同门控循环单元中的重置门和更新门一样,如图6.7所示,长短期记忆的输入门(input gate)、遗忘门(forget gate)和输出门(output gate)均由输入为当前时间步输入$
\b
oldsymbol{X}_t$与上一时间步隐藏状态$
\b
oldsymbol{H}_{t-1}$,且激活函数为sigmoid函数的全连接层计算得出。如此一来,这三个门元素的值域均为$[0,1]$。
同门控循环单元中的重置门和更新门一样,如图6.7所示,LSTM的门均由输入为当前时间步输入$
\b
oldsymbol{X}_t$与上一时间步隐藏状态$
\b
oldsymbol{H}_{t-1}$,且激活函数为sigmoid函数的全连接层计算得出。如此一来,这三个门元素的值域均为$[0,1]$。
![
长短期记忆中输入门、遗忘门和输出门的计算。
](
../img/lstm_0.svg
)
...
...
@@ -67,11 +66,6 @@ $$\boldsymbol{H}_t = \boldsymbol{O}_t \odot \text{tanh}(\boldsymbol{C}_t).$$
![
长短期记忆中隐藏状态的计算。这里的乘号是按元素乘法。
](
../img/lstm_3.svg
)
### 输出层
在时间步$t$,长短期记忆的输出层计算和之前描述的循环神经网络输出层计算一样:我们只需将该时刻的隐藏状态$
\b
oldsymbol{H}_t$传递进输出层,从而计算时间步$t$的输出。
## 实验
和前几节中的实验一样,我们依然使用周杰伦歌词数据集来训练模型作词。
...
...
@@ -88,11 +82,9 @@ import gluonbook as gb
from mxnet import nd
import zipfile
with zipfile.ZipFile('../data/jaychou_lyrics.txt.zip', 'r') as zin:
zin.extractall('../data/')
with open('../data/jaychou_lyrics.txt', encoding='utf-8') as f:
corpus_chars = f.read()
with zipfile.ZipFile('../data/jaychou_lyrics.txt.zip') as zin:
with zin.open('jaychou_lyrics.txt') as f:
corpus_chars = f.read().decode('utf-8')
corpus_chars = corpus_chars.replace('\n', ' ').replace('\r', ' ')
corpus_chars = corpus_chars[0:20000]
idx_to_char = list(set(corpus_chars))
...
...
@@ -106,41 +98,24 @@ vocab_size = len(char_to_idx)
以下部分对模型参数进行初始化。超参数
`num_hiddens`
定义了隐藏单元的个数。
```
{.python .input n=3}
ctx = gb.try_gpu()
input_dim = vocab_size
num_inputs = vocab_size
num_hiddens = 256
output_dim = vocab_size
num_outputs = vocab_size
ctx = gb.try_gpu()
def get_params():
# 输入门参数.
W_xi = nd.random_normal(scale=0.01, shape=(input_dim, num_hiddens),
ctx=ctx)
W_hi = nd.random_normal(scale=0.01, shape=(num_hiddens, num_hiddens),
ctx=ctx)
b_i = nd.zeros(num_hiddens, ctx=ctx)
# 遗忘门参数。
W_xf = nd.random_normal(scale=0.01, shape=(input_dim, num_hiddens),
ctx=ctx)
W_hf = nd.random_normal(scale=0.01, shape=(num_hiddens, num_hiddens),
ctx=ctx)
b_f = nd.zeros(num_hiddens, ctx=ctx)
# 输出门参数。
W_xo = nd.random_normal(scale=0.01, shape=(input_dim, num_hiddens),
ctx=ctx)
W_ho = nd.random_normal(scale=0.01, shape=(num_hiddens, num_hiddens),
ctx=ctx)
b_o = nd.zeros(num_hiddens, ctx=ctx)
# 候选细胞参数。
W_xc = nd.random_normal(scale=0.01, shape=(input_dim, num_hiddens),
ctx=ctx)
W_hc = nd.random_normal(scale=0.01, shape=(num_hiddens, num_hiddens),
ctx=ctx)
b_c = nd.zeros(num_hiddens, ctx=ctx)
_one = lambda shape: nd.random.normal(scale=0.01, shape=shape, ctx=ctx)
_three = lambda : (_one((num_inputs, num_hiddens)),
_one((num_hiddens, num_hiddens)),
nd.zeros(num_hiddens, ctx=ctx))
W_xi, W_hi, b_i = _three() # 输入门参数。
W_xf, W_hf, b_f = _three() # 遗忘门参数。
W_xo, W_ho, b_o = _three() # 输出门参数。
W_xc, W_hc, b_c = _three() # 候选细胞参数。
# 输出层参数。
W_hy = nd.random_normal(scale=0.01, shape=(num_hiddens, output_dim),
ctx=ctx)
W_hy = _one((num_hiddens, output_dim))
b_y = nd.zeros(output_dim, ctx=ctx)
# 创建梯度。
params = [W_xi, W_hi, b_i, W_xf, W_hf, b_f, W_xo, W_ho, b_o, W_xc, W_hc,
b_c, W_hy, b_y]
for param in params:
...
...
@@ -153,11 +128,9 @@ def get_params():
下面根据长短期记忆的计算表达式定义模型。
```
{.python .input n=4}
def lstm_rnn(inputs,
state_h, state_c
, *params):
def lstm_rnn(inputs,
H, C
, *params):
[W_xi, W_hi, b_i, W_xf, W_hf, b_f, W_xo, W_ho, b_o, W_xc, W_hc, b_c,
W_hy, b_y] = params
H = state_h
C = state_c
outputs = []
for X in inputs:
I = nd.sigmoid(nd.dot(X, W_xi) + nd.dot(H, W_hi) + b_i)
...
...
@@ -173,7 +146,7 @@ def lstm_rnn(inputs, state_h, state_c, *params):
### 训练模型并创作歌词
设置好超参数后,我们将训练模型并跟据前缀“分开”和“不分开”分别创作长度为
10
0个字符的一段歌词。我们每过30个迭代周期便根据当前训练的模型创作一段歌词。训练模型时采用了相邻采样。
设置好超参数后,我们将训练模型并跟据前缀“分开”和“不分开”分别创作长度为
5
0个字符的一段歌词。我们每过30个迭代周期便根据当前训练的模型创作一段歌词。训练模型时采用了相邻采样。
```
{.python .input n=5}
get_inputs = gb.to_onehot
...
...
@@ -184,7 +157,7 @@ lr = 0.25
clipping_theta = 5
prefixes = ['分开', '不分开']
pred_period = 30
pred_len =
10
0
pred_len =
5
0
gb.train_and_predict_rnn(lstm_rnn, False, num_epochs, num_steps, num_hiddens,
lr, clipping_theta, batch_size, vocab_size,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录