1. 过拟合和欠拟合
欠拟合 (underfitting) : 模型无法得到较低的训练误差
过拟合 (overfitting) : 模型的训练误差远小于它在测试数据集上的误差
- 模型越简单, 容易欠拟合, 模型越复杂, 容易过拟合
- 训练数据越少越容易过拟合
2. 过拟合解决方法
2.0增大训练集
2.1 权重衰减
权重衰减等价于 范数正则化 (regularization) . 正则化通过为模型损失函数添加惩罚项使学出的模型参数值较小, 是应对过拟合的常用手段. 范数正则化是在模型的原损失函数基础上添加范数惩罚项, 从而得到新的目标函数.
范数惩罚项是模型权重参数每个元素的平方和与一个常数的乘积.
# 正则项
def l2_penalty(w):
return (w**2).sum() / 2
net, loss = d2l.linreg, d2l.squared_loss
l = loss(net(X, w, b), y) + lambd * l2_penalty(w) # 新损失项
# 或者torch.optim.SGD中自带了权重衰减参数
torch.optim.SGD(params=[net.weight], lr=lr, weight_decay=wd)
2.2 丢弃法
以前面学习过的多层感知机为例, 使用丢弃法. 当对该隐藏层使用丢弃法时, 该层的隐藏单元将有一定概率被丢弃掉.
对多层感知机的隐层使用丢弃法
设丢弃概率为, 那么有的概率会被清零, 有的概率会除以做拉伸. 丢弃概率是丢弃法的超参数. 具体来说, 设随机变量为和的概率分别为和 . 新的隐藏单元, 而, 则. 即丢弃法不改变其输入的期望值.
由于在训练中隐藏层神经元的丢弃是随机的,即 都有可能被清零,输出层的计算无法过度依赖中的任一个,从而在训练模型时起到正则化的作用,并可以用来应对过拟合。在测试模型时,我们为了拿到更加确定性的结果,一般不使用丢弃法
从头实现
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
drop_prob1, drop_prob2 = 0.2, 0.5
def net(X, is_training=True):
X = X.view(-1, num_inputs)
H1 = (torch.matmul(X, W1) + b1).relu()
if is_training: # 只在训练模型时使用丢弃法
H1 = dropout(H1, drop_prob1) # 在第一层全连接后添加丢弃层
H2 = (torch.matmul(H1, W2) + b2).relu()
if is_training:
H2 = dropout(H2, drop_prob2) # 在第二层全连接后添加丢弃层
return torch.matmul(H2, W3) + b3
简洁实现
直接使用torch.nn模块中的Dropout类构建模型
d2l.FlattenLayer(),
nn.Linear(num_inputs, num_hiddens1),
nn.ReLU(),
nn.Dropout(drop_prob1),
nn.Linear(num_hiddens1, num_hiddens2),
nn.ReLU(),
nn.Dropout(drop_prob2),
nn.Linear(num_hiddens2, 10)
)
1. 梯度消失和梯度爆炸
这是DL中有关数值稳定性的经典问题, 当神经网络的层数较多时容易出现. 例如, 在激活函数为恒等变换时 (转存失败重新上传取消), 给定输入转存失败重新上传取消,多层感知机的第层的输出转存失败重新上传取消, 若所有层的权重都是标量如0.2和5, 则在第30层处的输出为转存失败重新上传取消 (消失) 和转存失败