D2L-四-多层感知机

DL动手学深度学习_四

多层感知机

4.4 模型选择,欠拟合和过拟合

训练误差:模型在训练数据集上计算得到的

泛化误差:模型在从原始样本的分布中抽取的无限多数据样本时的误差的期望

模型泛化的影响因素:

  1. 可调整参数数量
  2. 参数采用的值
  3. 训练样本的数量

K折交叉验证

​ 原始训练数据被分成K个不重叠子集,然后执行K次模型训练和验证,每次在K-1个子集上进行训练并在剩余子集上进行验证。通过K此实验结果取平均估计训练和验证误差

def get_k_fold_data(k, i, X, y):
    assert k > 1
    fold_size = X.shape[0] // k
    X_train, y_train = None, None
    for j in range(k):
        idx = slice(j * fold_size, (j + 1) * fold_size)
        X_part, y_part = X[idx, :], y[idx]
        if j == i:
            X_valid, y_valid = X_part, y_part
        elif X_train is None:
            X_train, y_train = X_part, y_part
        else:
            X_train = torch.cat([X_train, X_part], 0)
            y_train = torch.cat([y_train, y_part], 0)
    return X_train, y_train, X_valid, y_valid

4.5 权重衰减(L2正则化)

​ 技术通过函数与零的距离来衡量函数的复杂度

一般的损失函数:
$$
L(\mathbf{w}, b) = \frac{1}{n} \sum_{i=1}^{n} \frac{1}{2} \left( \mathbf{w}^{\top} \mathbf{x}^{(i)} + b - y^{(i)} \right)^2
$$
引入正则化常数后的损失函数:
$$
L(\mathbf{w}, b) + \frac{\lambda}{2} \left| \mathbf{w} \right|^2
$$
​ 学习算法偏向于在大量特征上均匀分布权重的模型

L2正则化回归的小批量随机梯度下降更新后为:
$$
\mathbf{w} \leftarrow (1 - \eta\lambda)\mathbf{w}

  • \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}}
    \mathbf{x}^{(i)} \left( \mathbf{w}^{\top} \mathbf{x}^{(i)} + b - y^{(i)} \right)
    $$
    ​ 根据估计值与观测值之间的差异来更新w

实现方法:在实例化优化器时直接通过weight_decay指定weight decay超参数。

    net = nn.Sequential(nn.Linear(num_inputs, 1))
    for param in net.parameters():
        param.data.normal_()
    #注意,nn.linear()本身自带初始化,调用Kaiming/Xavier
    #此处,用标准正态初始化
    loss = nn.MSELoss(reduction='none')
    num_epochs, lr = 100, 0.003
    # 偏置参数没有衰减
    trainer = torch.optim.SGD([
        {"params":net[0].weight,'weight_decay': wd},
        {"params":net[0].bias}], lr=lr)
        #parameter groups(参数组
    #我把参数分成两组,不同组可以用不同设置
    # 第一组
    # {"params": net[0].weight,
    #  "weight_decay": wd}
    # 第二组:
    #{"params": net[0].bias}
    # 但是没有指定 weight_decay,所以使用默认:

4.6 暂退法(dropout)

在标准暂退法正则化中,通过按保留(未丢弃)的节点的分数进行规范化来消除每一层的偏差。 换言之,每个中间活性值h以暂退概率p由随机变量h'替换,如下所示:
$$
h' =
\begin{cases}
0, & \text{概率为 } p \[6pt]
\dfrac{h}{1-p}, & \text{其他情况}
\end{cases}
$$
依据此模型,其期望值不变

​ 一般将暂退法应用到隐藏层,以p概率将隐藏单元置于零时,结果可以看作一个只包含原始神经元子集的网络。

​ 注意,暂退法仅仅在训练中使用,在测试过程中,给定一个训练好的模型和一个新的样本不会使用

image-20260923224733855

concise implementation

dropout1, dropout2 = 0.2, 0.5
net = nn.Sequential(nn.Flatten(),
        nn.Linear(784, 256),
        nn.ReLU(),
        # 在第一个全连接层之后添加一个dropout层
        nn.Dropout(dropout1),
        nn.Linear(256, 256),
        nn.ReLU(),
        # 在第二个全连接层之后添加一个dropout层
        nn.Dropout(dropout2),
        nn.Linear(256, 10))

def init_weights(m):
    if type(m) == nn.Linear:
        nn.init.normal_(m.weight, std=0.01)
    #nn.linear一般会对w和b进行初始化,这里想把改成高斯分布

net.apply(init_weights);#遍历网络,对每一层执行初始化函数

4.8 数值稳定性

​ 对于比较深层的神经网路,由于层之间的乘积作用,容易出现梯度消失和梯度爆炸。为了让训练更稳定

  1. 乘法变加法:ResNet,LSTM
  2. 归一化:梯度归一化,梯度裁剪
  3. 合理的权重初始化和激活函数
  4. 当然,优化期间适当正则化也可以提高稳定性

​ Xavier初始化:
$$
\frac{1}{2} (n_{\text{in}} + n_{\text{out}}) \sigma^2 = 1
\quad \text{或等价于} \quad
\sigma = \sqrt{\frac{2}{n_{\text{in}} + n_{\text{out}}}}
$$

posted @ 2026-09-28 23:18  EmoT1on  阅读(3)  评论(0)    收藏  举报