过拟合及欠拟合
模型误差
训练误差(training error)指模型在训练数据集上表现出的误差;泛化误差(generalization error)指模型在任意一个测试数据样本上表现出的误差的期望,并常常通过测试数据集上的误差来近似。计算训练误差和泛化误差可以使用之前介绍过的损失函数,例如线性回归用到的平方损失函数和softmax回归用到的交叉熵损失函数。机器学习模型应关注降低泛化误差。
模型选择
验证数据集: 从严格意义上讲,测试集只能在所有超参数和模型参数选定后使用一次。不可以使用测试数据选择模型,如调参。由于无法从训练误差估计泛化误差,因此也不应只依赖训练数据选择模型。鉴于此,我们预留一部分在训练数据集和测试数据集以外的数据来进行模型选择。这部分数据被称为验证数据集,简称验证集(validation set)。例如,我们可以从给定的训练集中随机选取一小部分作为验证集,而将剩余部分作为真正的训练集。
K折交叉验证: 由于验证数据集不参与模型训练,当训练数据不够用时,预留大量的验证数据显得太奢侈。一种改善的方法是K折交叉验证(K-fold cross-validation)。所谓K折交叉验证,就是将数据集等比例划分成K份,以其中的一份作为测试数据,其他的K-1份数据作为训练数据。然后,这样算是一次实验,而K折交叉验证只有实验K次才算完成完整的一次,也就是说交叉验证实际是把实验重复做了K次,每次实验都是从K个部分选取一份不同的数据部分作为测试数据(保证K个部分的数据都分别做过测试数据),剩下的K-1个当作训练数据,最后把得到的K个实验结果进行平分。
过/欠拟合
模型训练中经常出现的两类典型问题:
- 一类是模型无法得到较低的训练误差,我们将这一现象称作欠拟合(underfitting);
- 另一类是模型的训练误差远小于它在测试数据集上的误差,我们称该现象为过拟合(overfitting)。
在实践中,我们要尽可能同时应对欠拟合和过拟合。虽然有很多因素可能导致这两种拟合问题,在这里我们重点讨论两个因素:模型复杂度和训练数据集大小。
模型复杂度
为了解释模型复杂度,我们以多项式函数拟合为例。给定一个由标量数据特征
x
x
x和对应的标量标签
y
y
y组成的训练数据集,多项式函数拟合的目标是找一个
K
K
K阶多项式函数:
y
^
=
b
+
∑
k
=
1
K
x
k
w
k
\hat{y} = b + \sum_{k=1}^K x^k w_k
y^=b+k=1∑Kxkwk
来近似
y
y
y。在上式中,
w
k
w_k
wk是模型的权重参数,
b
b
b是偏差参数。与线性回归相同,多项式函数拟合也使用平方损失函数。特别地,一阶多项式函数拟合又叫线性函数拟合。给定训练数据集,模型复杂度和误差之间的关系:
训练集大小
影响欠拟合和过拟合的另一个重要因素是训练数据集的大小。一般来说,如果训练数据集中样本数过少,特别是比模型参数数量(按元素计)更少时,过拟合更容易发生。 此外,泛化误差不会随训练数据集里样本数量增加而增大。因此,在计算资源允许的范围之内,我们通常希望训练数据集大一些,特别是在模型复杂度较高时,例如层数较多的深度学习模型。
多项式函数拟合实验
import torch
import numpy as np
import d2lzh_pytorch as d2l
import matplotlib.pyplot as plt
n_train, n_test, true_w, true_b = 100, 100, [1.2, -3.4, 5.6], 5
features = torch.randn((n_train + n_test, 1))
poly_features = torch.cat((features, torch.pow(features, 2), torch.pow(features, 3)), 1)
labels = (true_w[0] * poly_features[:, 0] + true_w[1] * poly_features[:, 1]
+ true_w[2] * poly_features[:, 2] + true_b)
labels += torch.tensor(np.random.normal(0, 0.01, size=labels.size()), dtype=torch.float)
print(features[:2], poly_features[:2], labels[:2])
def semilogy(x_vals, y_vals, x_label, y_label, x2_vals=None, y2_vals=None,
legend=None, figsize=(3.5, 2.5)):
# d2l.set_figsize(figsize)
d2l.plt.xlabel(x_label)
d2l.plt.ylabel(y_label)
d2l.plt.semilogy(x_vals, y_vals)
if x2_vals and y2_vals:
d2l.plt.semilogy(x2_vals, y2_vals, linestyle=':')
d2l.plt.legend(legend)
num_epochs, loss = 100, torch.nn.MSELoss()
def fit_and_plot(train_features, test_features, train_labels, test_labels):
# 初始化网络模型
net = torch.nn.Linear(train_features.shape[-1], 1)
# 通过Linear文档可知,pytorch已经将参数初始化了,所以我们这里就不手动初始化了
# 设置批量大小
batch_size = min(10, train_labels.shape[0])
dataset = torch.utils.data.TensorDataset(train_features, train_labels) # 设置数据集
train_iter = torch.utils.data.DataLoader(dataset, batch_size, shuffle=True) # 设置获取数据方式
optimizer = torch.optim.SGD(net.parameters(), lr=0.01) # 设置优化函数,使用的是随机梯度下降优化
train_ls, test_ls = [], []
for _ in range(num_epochs):
for X, y in train_iter: # 取一个批量的数据
l = loss(net(X), y.view(-1, 1)) # 输入到网络中计算输出,并和标签比较求得损失函数
optimizer.zero_grad() # 梯度清零,防止梯度累加干扰优化
l.backward() # 求梯度
optimizer.step() # 迭代优化函数,进行参数优化
train_labels = train_labels.view(-1, 1)
test_labels = test_labels.view(-1, 1)
train_ls.append(loss(net(train_features), train_labels).item()) # 将训练损失保存到train_ls中
test_ls.append(loss(net(test_features), test_labels).item()) # 将测试损失保存到test_ls中
print('final epoch: train loss', train_ls[-1], 'test loss', test_ls[-1])
semilogy(range(1, num_epochs + 1), train_ls, 'epochs', 'loss',
range(1, num_epochs + 1), test_ls, ['train', 'test'])
print('weight:', net.weight.data,
'\nbias:', net.bias.data)
plt.figure(1)#正常
fit_and_plot(poly_features[:n_train, :], poly_features[n_train:, :], labels[:n_train], labels[n_train:])
plt.figure(2)#欠拟合
fit_and_plot(features[:n_train, :], features[n_train:, :], labels[:n_train], labels[n_train:])
plt.figure(3)#过拟合
fit_and_plot(poly_features[0:2, :], poly_features[n_train:, :], labels[0:2], labels[n_train:])
plt.show()
权重衰减
方法
权重衰减等价于 L 2 L_2 L2 范数正则化(regularization)。正则化通过为模型损失函数添加惩罚项使学出的模型参数值较小,是应对过拟合的常用手段。
L2 范数正则化(regularization)
L
2
L_2
L2范数正则化在模型原损失函数基础上添加
L
2
L_2
L2范数惩罚项,从而得到训练所需要最小化的函数。
L
2
L_2
L2范数惩罚项指的是模型权重参数每个元素的平方和与一个正的常数的乘积。以线性回归中的线性回归损失函数为例
ℓ
(
w
1
,
w
2
,
b
)
=
1
n
∑
i
=
1
n
1
2
(
x
1
(
i
)
w
1
+
x
2
(
i
)
w
2
+
b
−
y
(
i
)
)
2
\ell(w_1, w_2, b) = \frac{1}{n} \sum_{i=1}^n \frac{1}{2}\left(x_1^{(i)} w_1 + x_2^{(i)} w_2 + b - y^{(i)}\right)^2
ℓ(w1,w2,b)=n1i=1∑n21(x1(i)w1+x2(i)w2+b−y(i))2
其中
w
1
,
w
2
w_1, w_2
w1,w2是权重参数,
b
b
b是偏差参数,样本
i
i
i的输入为
x
1
(
i
)
,
x
2
(
i
)
x_1^{(i)}, x_2^{(i)}
x1(i),x2(i),标签为
y
(
i
)
y^{(i)}
y(i),样本数为
n
n
n。将权重参数用向量
w
=
[
w
1
,
w
2
]
\boldsymbol{w} = [w_1, w_2]
w=[w1,w2]表示,带有
L
2
L_2
L2范数惩罚项的新损失函数为
ℓ
(
w
1
,
w
2
,
b
)
+
λ
2
n
∣
w
∣
2
,
\ell(w_1, w_2, b) + \frac{\lambda}{2n} |\boldsymbol{w}|^2,
ℓ(w1,w2,b)+2nλ∣w∣2,
其中超参数
λ
>
0
\lambda > 0
λ>0。当权重参数均为0时,惩罚项最小。当
λ
\lambda
λ较大时,惩罚项在损失函数中的比重较大,这通常会使学到的权重参数的元素较接近0。当
λ
\lambda
λ设为0时,惩罚项完全不起作用。上式中
L
2
L_2
L2范数平方
∣
w
∣
2
|\boldsymbol{w}|^2
∣w∣2展开后得到
w
1
2
+
w
2
2
w_1^2 + w_2^2
w12+w22。
有了
L
2
L_2
L2范数惩罚项后,在小批量随机梯度下降中,我们将线性回归一节中权重
w
1
w_1
w1和
w
2
w_2
w2的迭代方式更改为
w
1
←
(
1
−
η
λ
∣
B
∣
)
w
1
−
η
∣
B
∣
∑
i
∈
B
x
1
(
i
)
(
x
1
(
i
)
w
1
+
x
2
(
i
)
w
2
+
b
−
y
(
i
)
)
,
w
2
←
(
1
−
η
λ
∣
B
∣
)
w
2
−
η
∣
B
∣
∑
i
∈
B
x
2
(
i
)
(
x
1
(
i
)
w
1
+
x
2
(
i
)
w
2
+
b
−
y
(
i
)
)
.
\begin{aligned} w_1 &\leftarrow \left(1- \frac{\eta\lambda}{|\mathcal{B}|} \right)w_1 - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}}x_1^{(i)} \left(x_1^{(i)} w_1 + x_2^{(i)} w_2 + b - y^{(i)}\right),\\ w_2 &\leftarrow \left(1- \frac{\eta\lambda}{|\mathcal{B}|} \right)w_2 - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}}x_2^{(i)} \left(x_1^{(i)} w_1 + x_2^{(i)} w_2 + b - y^{(i)}\right). \end{aligned}
w1w2←(1−∣B∣ηλ)w1−∣B∣ηi∈B∑x1(i)(x1(i)w1+x2(i)w2+b−y(i)),←(1−∣B∣ηλ)w2−∣B∣ηi∈B∑x2(i)(x1(i)w1+x2(i)w2+b−y(i)).
可见,
L
2
L_2
L2范数正则化令权重
w
1
w_1
w1和
w
2
w_2
w2先自乘小于1的数,再减去不含惩罚项的梯度。因此,
L
2
L_2
L2范数正则化又叫权重衰减。权重衰减通过惩罚绝对值较大的模型参数为需要学习的模型增加了限制,这可能对过拟合有效。
def l2_penalty(w):
return (w**2).sum() / 2
def fit_and_plot(lambd):
w, b = init_params()
train_ls, test_ls = [], []
for _ in range(num_epochs):
for X, y in train_iter:
# 添加了L2范数惩罚项
l = loss(net(X, w, b), y) + lambd * l2_penalty(w)
l = l.sum()
if w.grad is not None:
w.grad.data.zero_()
b.grad.data.zero_()
l.backward()
d2l.sgd([w, b], lr, batch_size)
train_ls.append(loss(net(train_features, w, b), train_labels).mean().item())
test_ls.append(loss(net(test_features, w, b), test_labels).mean().item())
d2l.semilogy(range(1, num_epochs + 1), train_ls, 'epochs', 'loss',
range(1, num_epochs + 1), test_ls, ['train', 'test'])
print('L2 norm of w:', w.norm().item())
简洁实现:
def fit_and_plot_pytorch(wd):
# 对权重参数衰减。权重名称一般是以weight结尾
net = nn.Linear(num_inputs, 1)
nn.init.normal_(net.weight, mean=0, std=1)
nn.init.normal_(net.bias, mean=0, std=1)
optimizer_w = torch.optim.SGD(params=[net.weight], lr=lr, weight_decay=wd) # 对权重参数衰减
optimizer_b = torch.optim.SGD(params=[net.bias], lr=lr) # 不对偏差参数衰减
train_ls, test_ls = [], []
for _ in range(num_epochs):
for X, y in train_iter:
l = loss(net(X), y).mean()
optimizer_w.zero_grad()
optimizer_b.zero_grad()
l.backward()
# 对两个optimizer实例分别调用step函数,从而分别更新权重和偏差
optimizer_w.step()
optimizer_b.step()
train_ls.append(loss(net(train_features), train_labels).mean().item())
test_ls.append(loss(net(test_features), test_labels).mean().item())
d2l.semilogy(range(1, num_epochs + 1), train_ls, 'epochs', 'loss',
range(1, num_epochs + 1), test_ls, ['train', 'test'])
print('L2 norm of w:', net.weight.data.norm().item())
丢弃法
多层感知机中神经网络图描述了一个单隐藏层的多层感知机。其中输入个数为4,隐藏单元个数为5,且隐藏单元
h
i
h_i
hi(
i
=
1
,
…
,
5
i=1, \ldots, 5
i=1,…,5)的计算表达式为
h
i
=
ϕ
(
x
1
w
1
i
+
x
2
w
2
i
+
x
3
w
3
i
+
x
4
w
4
i
+
b
i
)
h_i = \phi\left(x_1 w_{1i} + x_2 w_{2i} + x_3 w_{3i} + x_4 w_{4i} + b_i\right)
hi=ϕ(x1w1i+x2w2i+x3w3i+x4w4i+bi)
这里
ϕ
\phi
ϕ是激活函数,
x
1
,
…
,
x
4
x_1, \ldots, x_4
x1,…,x4是输入,隐藏单元
i
i
i的权重参数为
w
1
i
,
…
,
w
4
i
w_{1i}, \ldots, w_{4i}
w1i,…,w4i,偏差参数为
b
i
b_i
bi。当对该隐藏层使用丢弃法时,该层的隐藏单元将有一定概率被丢弃掉。设丢弃概率为
p
p
p,那么有
p
p
p的概率
h
i
h_i
hi会被清零,有
1
−
p
1-p
1−p的概率
h
i
h_i
hi会除以
1
−
p
1-p
1−p做拉伸。丢弃概率是丢弃法的超参数。具体来说,设随机变量
ξ
i
\xi_i
ξi为0和1的概率分别为
p
p
p和
1
−
p
1-p
1−p。使用丢弃法时我们计算新的隐藏单元
h
i
′
h_i'
hi′
h
i
′
=
ξ
i
1
−
p
h
i
h_i' = \frac{\xi_i}{1-p} h_i
hi′=1−pξihi
由于
E
(
ξ
i
)
=
1
−
p
E(\xi_i) = 1-p
E(ξi)=1−p,因此
E
(
h
i
′
)
=
E
(
ξ
i
)
1
−
p
h
i
=
h
i
E(h_i') = \frac{E(\xi_i)}{1-p}h_i = h_i
E(hi′)=1−pE(ξi)hi=hi
即丢弃法不改变其输入的期望值。让我们对之前多层感知机的神经网络中的隐藏层使用丢弃法,一种可能的结果如图所示,其中
h
2
h_2
h2和
h
5
h_5
h5被清零。这时输出值的计算不再依赖
h
2
h_2
h2和
h
5
h_5
h5,在反向传播时,与这两个隐藏单元相关的权重的梯度均为0。由于在训练中隐藏层神经元的丢弃是随机的,即
h
1
,
…
,
h
5
h_1, \ldots, h_5
h1,…,h5都有可能被清零,输出层的计算无法过度依赖
h
1
,
…
,
h
5
h_1, \ldots, h_5
h1,…,h5中的任一个,从而在训练模型时起到正则化的作用,并可以用来应对过拟合。在测试模型时,我们为了拿到更加确定性的结果,一般不使用丢弃法。
def dropout(X, drop_prob):
X = X.float()
assert 0 <= drop_prob <= 1
keep_prob = 1 - drop_prob
# 这种情况下把全部元素都丢弃
if keep_prob == 0:
return torch.zeros_like(X)
mask = (torch.rand(X.shape) < keep_prob).float()
return mask * X / keep_prob
'''
OR
nn.Dropout()
'''
梯度消失、梯度爆炸以及Kaggle房价预测
深度模型有关数值稳定性的典型问题是消失(vanishing)和爆炸(explosion)。
当神经网络的层数较多时,模型的数值稳定性容易变差。
假设一个层数为
L
L
L的多层感知机的第
l
l
l层
H
(
l
)
\boldsymbol{H}^{(l)}
H(l)的权重参数为
W
(
l
)
\boldsymbol{W}^{(l)}
W(l),输出层
H
(
L
)
\boldsymbol{H}^{(L)}
H(L)的权重参数为
W
(
L
)
\boldsymbol{W}^{(L)}
W(L)。为了便于讨论,不考虑偏差参数,且设所有隐藏层的激活函数为恒等映射(identity mapping)
ϕ
(
x
)
=
x
\phi(x) = x
ϕ(x)=x。给定输入
X
\boldsymbol{X}
X,多层感知机的第
l
l
l层的输出
H
(
l
)
=
X
W
(
1
)
W
(
2
)
…
W
(
l
)
\boldsymbol{H}^{(l)} = \boldsymbol{X} \boldsymbol{W}^{(1)} \boldsymbol{W}^{(2)} \ldots \boldsymbol{W}^{(l)}
H(l)=XW(1)W(2)…W(l)。此时,如果层数
l
l
l较大,
H
(
l
)
\boldsymbol{H}^{(l)}
H(l)的计算可能会出现衰减或爆炸。举个例子,假设输入和所有层的权重参数都是标量,如权重参数为0.2和5,多层感知机的第30层输出为输入
X
\boldsymbol{X}
X分别与
0.
2
30
≈
1
×
1
0
−
21
0.2^{30} \approx 1 \times 10^{-21}
0.230≈1×10−21(消失)和
5
30
≈
9
×
1
0
20
5^{30} \approx 9 \times 10^{20}
530≈9×1020(爆炸)的乘积。当层数较多时,梯度的计算也容易出现消失或爆炸。
随机初始化模型参数
在神经网络中,通常需要随机初始化模型参数。回顾多层感知机一节描述的多层感知机。为了方便解释,假设输出层只保留一个输出单元 o 1 o_1 o1(删去 o 2 o_2 o2和 o 3 o_3 o3以及指向它们的箭头),且隐藏层使用相同的激活函数。如果将每个隐藏单元的参数都初始化为相等的值,那么在正向传播时每个隐藏单元将根据相同的输入计算出相同的值,并传递至输出层。在反向传播中,每个隐藏单元的参数梯度值相等。因此,这些参数在使用基于梯度的优化算法迭代后值依然相等。之后的迭代也是如此。在这种情况下,无论隐藏单元有多少,隐藏层本质上只有1个隐藏单元在发挥作用。因此,正如在前面的实验中所做的那样,我们通常将神经网络的模型参数,特别是权重参数,进行随机初始化。
PyTorch的默认随机初始化
随机初始化模型参数的方法有很多。在线性回归的简洁实现中,我们使用torch.nn.init.normal_()
使模型net
的权重参数采用正态分布的随机初始化方式。不过,PyTorch中nn.Module
的模块参数都采取了较为合理的初始化策略(不同类型的layer具体采样的哪一种初始化方法的可参考源代码),因此一般不用我们考虑。
Xavier随机初始化
还有一种比较常用的随机初始化方法叫作Xavier随机初始化。
假设某全连接层的输入个数为
a
a
a,输出个数为
b
b
b,Xavier随机初始化将使该层中权重参数的每个元素都随机采样于均匀分布
U
(
−
6
a
+
b
,
6
a
+
b
)
.
U\left(-\sqrt{\frac{6}{a+b}}, \sqrt{\frac{6}{a+b}}\right).
U(−a+b6,a+b6).
它的设计主要考虑到,模型参数初始化后,每层输出的方差不该受该层输入个数影响,且每层梯度的方差也不该受该层输出个数影响。
考虑环境因素
协变量偏移
这里我们假设,虽然输入的分布可能随时间而改变,但是标记函数,即条件分布P(y∣x)不会改变。虽然这个问题容易理解,但在实践中也容易忽视。
想想区分猫和狗的一个例子。我们的训练数据使用的是猫和狗的真实的照片,但是在测试时,我们被要求对猫和狗的卡通图片进行分类。
cat | cat | dog | dog |
---|---|---|---|
测试数据:
cat | cat | dog | dog |
---|---|---|---|
显然,这不太可能奏效。训练集由照片组成,而测试集只包含卡通。在一个看起来与测试集有着本质不同的数据集上进行训练,而不考虑如何适应新的情况,这是不是一个好主意。不幸的是,这是一个非常常见的陷阱。
统计学家称这种协变量变化是因为问题的根源在于特征分布的变化(即协变量的变化)。数学上,我们可以说P(x)改变了,但P(y∣x)保持不变。尽管它的有用性并不局限于此,当我们认为x导致y时,协变量移位通常是正确的假设。
标签偏移
当我们认为导致偏移的是标签P(y)上的边缘分布的变化,但类条件分布是不变的P(x∣y)时,就会出现相反的问题。当我们认为y导致x时,标签偏移是一个合理的假设。例如,通常我们希望根据其表现来预测诊断结果。在这种情况下,我们认为诊断引起的表现,即疾病引起的症状。有时标签偏移和协变量移位假设可以同时成立。例如,当真正的标签函数是确定的和不变的,那么协变量偏移将始终保持,包括如果标签偏移也保持。有趣的是,当我们期望标签偏移和协变量偏移保持时,使用来自标签偏移假设的方法通常是有利的。这是因为这些方法倾向于操作看起来像标签的对象,这(在深度学习中)与处理看起来像输入的对象(在深度学习中)相比相对容易一些。
病因(要预测的诊断结果)导致 症状(观察到的结果)。
训练数据集,数据很少只包含流感p(y)的样本。
而测试数据集有流感p(y)和流感q(y),其中不变的是流感症状p(x|y)。
概念偏移
另一个相关的问题出现在概念转换中,即标签本身的定义发生变化的情况。这听起来很奇怪,毕竟猫就是猫。的确,猫的定义可能不会改变,但我们能不能对软饮料也这么说呢?事实证明,如果我们周游美国,按地理位置转移数据来源,我们会发现,即使是如图所示的这个简单术语的定义也会发生相当大的概念转变。
美
国
软
饮
料
名
称
的
概
念
转
变
美国软饮料名称的概念转变
美国软饮料名称的概念转变
如果我们要建立一个机器翻译系统,分布P(y∣x)可能因我们的位置而异。这个问题很难发现。另一个可取之处是P(y∣x)通常只是逐渐变化。
GRU
RNN存在的问题:梯度较容易出现衰减或爆炸(BPTT)
⻔控循环神经⽹络:捕捉时间序列中时间步距离较⼤的依赖关系
RNN:
H
t
=
ϕ
(
X
t
W
x
h
+
H
t
−
1
W
h
h
+
b
h
)
H_{t} = ϕ(X_{t}W_{xh} + H_{t-1}W_{hh} + b_{h})
Ht=ϕ(XtWxh+Ht−1Whh+bh)
GRU:
R
t
=
σ
(
X
t
W
x
r
+
H
t
−
1
W
h
r
+
b
r
)
Z
t
=
σ
(
X
t
W
x
z
+
H
t
−
1
W
h
z
+
b
z
)
H
~
t
=
t
a
n
h
(
X
t
W
x
h
+
(
R
t
⊙
H
t
−
1
)
W
h
h
+
b
h
)
H
t
=
Z
t
⊙
H
t
−
1
+
(
1
−
Z
t
)
⊙
H
~
t
R_{t} = σ(X_tW_{xr} + H_{t−1}W_{hr} + b_r)\\ Z_{t} = σ(X_tW_{xz} + H_{t−1}W_{hz} + b_z)\\ \widetilde{H}_t = tanh(X_tW_{xh} + (R_t ⊙H_{t−1})W_{hh} + b_h)\\ H_t = Z_t⊙H_{t−1} + (1−Z_t)⊙\widetilde{H}_t
Rt=σ(XtWxr+Ht−1Whr+br)Zt=σ(XtWxz+Ht−1Whz+bz)H
t=tanh(XtWxh+(Rt⊙Ht−1)Whh+bh)Ht=Zt⊙Ht−1+(1−Zt)⊙H
t
• 重置⻔有助于捕捉时间序列⾥短期的依赖关系;
• 更新⻔有助于捕捉时间序列⾥⻓期的依赖关系。
LSTM
长短期记忆long short-term memory:
遗忘门:控制上一时间步的记忆细胞
输入门:控制当前时间步的输入
输出门:控制从记忆细胞到隐藏状态
记忆细胞:⼀种特殊的隐藏状态的信息的流动
I
t
=
σ
(
X
t
W
x
i
+
H
t
−
1
W
h
i
+
b
i
)
F
t
=
σ
(
X
t
W
x
f
+
H
t
−
1
W
h
f
+
b
f
)
O
t
=
σ
(
X
t
W
x
o
+
H
t
−
1
W
h
o
+
b
o
)
C
~
t
=
t
a
n
h
(
X
t
W
x
c
+
H
t
−
1
W
h
c
+
b
c
)
C
t
=
F
t
⊙
C
t
−
1
+
I
t
⊙
C
~
t
H
t
=
O
t
⊙
t
a
n
h
(
C
t
)
I_t = σ(X_tW_{xi} + H_{t−1}W_{hi} + b_i) \\ F_t = σ(X_tW_{xf} + H_{t−1}W_{hf} + b_f)\\ O_t = σ(X_tW_{xo} + H_{t−1}W_{ho} + b_o)\\ \widetilde{C}_t = tanh(X_tW_{xc} + H_{t−1}W_{hc} + b_c)\\ C_t = F_t ⊙C_{t−1} + I_t ⊙\widetilde{C}_t\\ H_t = O_t⊙tanh(C_t)
It=σ(XtWxi+Ht−1Whi+bi)Ft=σ(XtWxf+Ht−1Whf+bf)Ot=σ(XtWxo+Ht−1Who+bo)C
t=tanh(XtWxc+Ht−1Whc+bc)Ct=Ft⊙Ct−1+It⊙C
tHt=Ot⊙tanh(Ct)
深度循环神经网络
H
t
(
1
)
=
ϕ
(
X
t
W
x
h
(
1
)
+
H
t
−
1
(
1
)
W
h
h
(
1
)
+
b
h
(
1
)
)
H
t
(
ℓ
)
=
ϕ
(
H
t
(
ℓ
−
1
)
W
x
h
(
ℓ
)
+
H
t
−
1
(
ℓ
)
W
h
h
(
ℓ
)
+
b
h
(
ℓ
)
)
O
t
=
H
t
(
L
)
W
h
q
+
b
q
\boldsymbol{H}_t^{(1)} = \phi(\boldsymbol{X}_t \boldsymbol{W}_{xh}^{(1)} + \boldsymbol{H}_{t-1}^{(1)} \boldsymbol{W}_{hh}^{(1)} + \boldsymbol{b}_h^{(1)})\\ \boldsymbol{H}_t^{(\ell)} = \phi(\boldsymbol{H}_t^{(\ell-1)} \boldsymbol{W}_{xh}^{(\ell)} + \boldsymbol{H}_{t-1}^{(\ell)} \boldsymbol{W}_{hh}^{(\ell)} + \boldsymbol{b}_h^{(\ell)})\\ \boldsymbol{O}_t = \boldsymbol{H}_t^{(L)} \boldsymbol{W}_{hq} + \boldsymbol{b}_q
Ht(1)=ϕ(XtWxh(1)+Ht−1(1)Whh(1)+bh(1))Ht(ℓ)=ϕ(Ht(ℓ−1)Wxh(ℓ)+Ht−1(ℓ)Whh(ℓ)+bh(ℓ))Ot=Ht(L)Whq+bq
双向循环神经网络
H
→
t
=
ϕ
(
X
t
W
x
h
(
f
)
+
H
→
t
−
1
W
h
h
(
f
)
+
b
h
(
f
)
)
H
←
t
=
ϕ
(
X
t
W
x
h
(
b
)
+
H
←
t
+
1
W
h
h
(
b
)
+
b
h
(
b
)
)
\begin{aligned} \overrightarrow{\boldsymbol{H}}_t &= \phi(\boldsymbol{X}_t \boldsymbol{W}_{xh}^{(f)} + \overrightarrow{\boldsymbol{H}}_{t-1} \boldsymbol{W}_{hh}^{(f)} + \boldsymbol{b}_h^{(f)})\\ \overleftarrow{\boldsymbol{H}}_t &= \phi(\boldsymbol{X}_t \boldsymbol{W}_{xh}^{(b)} + \overleftarrow{\boldsymbol{H}}_{t+1} \boldsymbol{W}_{hh}^{(b)} + \boldsymbol{b}_h^{(b)}) \end{aligned}
HtHt=ϕ(XtWxh(f)+Ht−1Whh(f)+bh(f))=ϕ(XtWxh(b)+Ht+1Whh(b)+bh(b))
H
t
=
(
H
→
t
,
H
←
t
)
\boldsymbol{H}_t=(\overrightarrow{\boldsymbol{H}}_{t}, \overleftarrow{\boldsymbol{H}}_t)
Ht=(Ht,Ht)
O
t
=
H
t
W
h
q
+
b
q
\boldsymbol{O}_t = \boldsymbol{H}_t \boldsymbol{W}_{hq} + \boldsymbol{b}_q
Ot=HtWhq+bq
友情链接:
深度学习基础(四)
深度学习基础(二)