参数初始化与信号尺度:参考答案

目录

\[ \begin{align}\begin{aligned}\newcommand{\ba}{\boldsymbol{a}} \newcommand{\bb}{\boldsymbol{b}} \newcommand{\be}{\boldsymbol{e}} \newcommand{\bq}{\boldsymbol{q}} \newcommand{\bk}{\boldsymbol{k}} \newcommand{\bw}{\boldsymbol{w}} \newcommand{\bx}{\boldsymbol{x}} \newcommand{\by}{\boldsymbol{y}} \newcommand{\bz}{\boldsymbol{z}} \newcommand{\bd}{\boldsymbol{d}} \newcommand{\bv}{\boldsymbol{v}} \newcommand{\bs}{\boldsymbol{s}}\\\newcommand{\btheta}{\boldsymbol{\theta}} \newcommand{\bbeta}{\boldsymbol{\beta}} \newcommand{\bgamma}{\boldsymbol{\gamma}} \newcommand{\bsigma}{\boldsymbol{\sigma}} \newcommand{\md}{\mbox{d}} \newcommand{\bmu}{\boldsymbol{\mu}} \newcommand{\bone}{\boldsymbol{1}} \newcommand{\bzero}{\boldsymbol{0}} \newcommand{\bepsilon}{\boldsymbol{\epsilon}} \newcommand{\bphi}{\boldsymbol{\phi}} \newcommand{\bh}{\boldsymbol{h}} \newcommand{\bc}{\boldsymbol{c}} \newcommand{\br}{\boldsymbol{r}} \newcommand{\bQ}{\boldsymbol{Q}} \newcommand{\bK}{\boldsymbol{K}} \newcommand{\bV}{\boldsymbol{V}} \newcommand{\bSigma}{\boldsymbol{\Sigma}} \newcommand{\bg}{\boldsymbol{g}} \newcommand{\bxi}{\boldsymbol{\xi}} \newcommand{\bvarepsilon}{\boldsymbol{\varepsilon}} \newcommand{\bdelta}{\boldsymbol{\delta}} \newcommand{\bq}{\boldsymbol{q}} \newcommand{\bk}{\boldsymbol{k}} \newcommand{\bJ}{\boldsymbol{J}} \newcommand{\bp}{\boldsymbol{p}} \newcommand{\bi}{\boldsymbol{i}} \newcommand{\bo}{\boldsymbol{o}} \newcommand{\bE}{\boldsymbol{E}} \newcommand{\bH}{\boldsymbol{H}} \newcommand{\bL}{\boldsymbol{L}} \newcommand{\bu}{\boldsymbol{u}} \newcommand{\bLambda}{\boldsymbol{\Lambda}} \newcommand{\trans}{^{\rm\scriptsize T}} \newcommand{\var}{\mathrm{var}}\\\newcommand{\bA}{\boldsymbol{A}} \newcommand{\bB}{\boldsymbol{B}} \newcommand{\bC}{\boldsymbol{C}} \newcommand{\bD}{\boldsymbol{D}} \newcommand{\bG}{\boldsymbol{G}} \newcommand{\bI}{\boldsymbol{I}} \newcommand{\bM}{\boldsymbol{M}} \newcommand{\bP}{\boldsymbol{P}} \newcommand{\bS}{\boldsymbol{S}} \newcommand{\bU}{\boldsymbol{U}} \newcommand{\bW}{\boldsymbol{W}} \newcommand{\bX}{\boldsymbol{X}} \newcommand{\bY}{\boldsymbol{Y}} \newcommand{\bZ}{\boldsymbol{Z}} \newcommand{\cotp}{\textcolor[RGB]{48,209,88}{TP}} \newcommand{\cotn}{\textcolor[RGB]{100,210,255}{TN}} \newcommand{\cofp}{\textcolor[RGB]{94,92,230}{FP}} \newcommand{\cofn}{\textcolor[RGB]{191,90,242}{FN}}\\\newcommand{\numcotp}{\textcolor[RGB]{48,209,88}{50}} \newcommand{\numcotn}{\textcolor[RGB]{100,210,255}{30}} \newcommand{\numcofp}{\textcolor[RGB]{94,92,230}{10}} \newcommand{\numcofn}{\textcolor[RGB]{191,90,242}{10}} \DeclareMathOperator*{\argmin}{arg\,min}\end{aligned}\end{align} \]

参数初始化与信号尺度:参考答案#

返回正文练习 · 返回答案索引

说明#

以下答案与正文10道题逐题对应。推导题给出主要步骤;编程和实验题给出参考程序和检查方法,并说明结果适用于哪些条件。

  1. 独立且零均值给出 \(\mathbb E(w_{jk}a_k)=0\)⁠。互不相关的求和项满足 \(\operatorname{Var}(z_j)=\sum_k\operatorname{Var}(w_{jk}a_k)\)⁠,而独立性给出 \(\operatorname{Var}(w_{jk}a_k)=\operatorname{Var}(w_{jk})\operatorname{Var}(a_k)\)⁠,故共有 \(d_{\mathrm{in}}\) 个同分布项时得到题中等式。若权重或激活非零均值、项间相关或方差不相同,必须保留额外的协方差或逐项方差,简式不再严格成立。

  2. 记权重方差为 \(v_w\)⁠。若输入近似零均值,各输入分量具有相同的二阶矩,则线性运算结果满足

    \[\mathbb E(z_j^2) \approx d_{\mathrm{in}}v_w\mathbb E(a_k^2).\]

    对关于 0 近似对称的线性运算结果,ReLU 函数约保留一半二阶矩,因此

    \[\mathbb E[\operatorname{ReLU}(z_j)^2] \approx \frac{d_{\mathrm{in}}v_w}{2}\mathbb E(a_k^2).\]

    若希望前向传播前后的二阶矩大致不变,应取 \(v_w\approx2/d_{\mathrm{in}}\)⁠,这就是 fan-in 模式 He 初始化的目标。

      后向传播也有对应的尺度条件。设 \(g_j\) 是从后一层传到 ReLU 输出的梯度。在独立、零均值且约有一半 ReLU 单元处于激活状态的近似下,传回某个输入分量的梯度方差满足

    \[\operatorname{Var}\!\left(\frac{\partial\mathcal J}{\partial a_k}\right) \approx \frac{d_{\mathrm{out}}v_w}{2}\operatorname{Var}(g_j).\]

    若优先保持后向梯度的尺度,应取 \(v_w\approx2/d_{\mathrm{out}}\)⁠,这就是 fan-out 模式的目标。当 \(d_{\mathrm{in}}\ne d_{\mathrm{out}}\) 时,\(2/d_{\mathrm{in}}\)\(2/d_{\mathrm{out}}\) 不相等,同一个权重方差无法同时精确满足两个目标。实际使用时可以根据更关心前向激活还是后向梯度选择模式,也可以采用折中尺度。普通 Xavier 正态初始化的方差为 \(2/(d_{\mathrm{in}}+d_{\mathrm{out}})\)⁠;若再乘入 ReLU 的增益 \(\sqrt 2\)⁠,折中方差变为 \(4/(d_{\mathrm{in}}+d_{\mathrm{out}})\)⁠。这些结论来自近似尺度分析,不保证有限宽网络中的统计量精确不变。

  3. 设第 \(t\) 步的整套参数在交换这两个神经元时保持不变。它们对每个输入产生相同的线性运算结果和激活;由于通向下一层的对应权重也相同,交换操作不改变网络输出和损失,链式法则便给出成对相同的输入权重梯度、偏置梯度和输出权重梯度。使用相同学习率更新后,整套参数仍具有同一交换对称性。初始步成立,数学归纳法说明所有更新步均成立。因此两个神经元只能学习重复特征。仅令输入权重和偏置相同还不够:若输出权重不同,第一次后向传播得到的隐藏层梯度就可能不同。随机小扰动、不同的 Dropout 掩码或其他破坏对称性的机制也会改变结论。

  4. 代入 \(d_{\mathrm{in}}=128\)\(d_{\mathrm{out}}=64\)⁠,四种初始化的标准差分别为

    \[\begin{split}\begin{aligned} \sigma_{\mathrm{Xavier}} &=\sqrt{\frac{2}{128+64}} =\sqrt{\frac{1}{96}}\approx0.1021,\\ \sigma_{\mathrm{He,in}} &=\sqrt{\frac{2}{128}}=0.1250,\\ \sigma_{\mathrm{He,out}} &=\sqrt{\frac{2}{64}}\approx0.1768,\\ \sigma_{\mathrm{ReLU\text{-}gain}} &=\sqrt{\frac{4}{128+64}} =\sqrt{\frac{1}{48}}\approx0.1443. \end{aligned}\end{split}\]

    输入二阶矩为 1 时,fan-in 模式 He 初始化使线性运算结果的二阶矩约为

    \[\mathbb E(Z^2)\approx128\frac{2}{128}=2, \qquad \mathbb E[\operatorname{ReLU}(Z)^2]\approx\frac12\mathbb E(Z^2)=1.\]

    因此,这一分析保持的是 ReLU 输出的二阶矩,而不一定是严格方差。若进一步近似 \(Z\sim\mathcal N(0,2)\)⁠,则 \(\mathbb E[\operatorname{ReLU}(Z)]=1/\sqrt\pi\)⁠,严格方差为 \(1-1/\pi\approx0.6817\)⁠。

  5. 下面的实现使用全连接层和标准卷积层常见的权重存放顺序。全连接权重维度为 (fan_out, fan_in)卷积权重维度为 (out_channels, in_channels_per_group, *kernel_size)

    from numbers import Integral
    import numpy as np
    
    
    def calculate_fans(shape):
        try:
            dims = tuple(shape)
        except TypeError as exc:
            raise ValueError("shape 必须是维度序列") from exc
        if len(dims) < 2:
            raise ValueError("权重至少需要两个轴")
        if any(not isinstance(size, Integral) or size <= 0 for size in dims):
            raise ValueError("每个权重维度都必须是正整数")
    
        receptive_field = int(np.prod(dims[2:], dtype=np.int64))
        fan_in = int(dims[1] * receptive_field)
        fan_out = int(dims[0] * receptive_field)
        return fan_in, fan_out
    
    
    def init_weight(shape, kind, rng, normal_std=None, mode="fan_in"):
        fan_in, fan_out = calculate_fans(shape)
        dims = tuple(shape)
    
        if kind == "zero":
            return np.zeros(dims, dtype=np.float64)
    
        if kind == "normal":
            if normal_std is None or not np.isfinite(normal_std):
                raise ValueError("normal 初始化需要有限的标准差")
            if normal_std < 0:
                raise ValueError("标准差不能为负数")
            variance = float(normal_std) ** 2
        elif kind == "xavier":
            variance = 2.0 / (fan_in + fan_out)
        elif kind == "he":
            if mode not in {"fan_in", "fan_out"}:
                raise ValueError("He 初始化的 mode 必须是 fan_in 或 fan_out")
            fan = fan_in if mode == "fan_in" else fan_out
            variance = 2.0 / fan
        elif kind == "xavier_relu":
            # 普通 Xavier 方差乘以 ReLU 增益平方 2
            variance = 4.0 / (fan_in + fan_out)
        else:
            raise ValueError("未知初始化方法")
    
        return rng.normal(0.0, np.sqrt(variance), size=dims)
    

    调用 init_weight(shape, "he", rng, mode="fan_in")mode="fan_out" 即可得到两种 He 初始化;kind="xavier_relu" 对应带 ReLU 增益的折中方案。卷积层的感受野大小是所有卷积核空间维度的乘积,因此 (16, 8, 3, 3) 得到 fan_in=72fan_out=144分组卷积的第二个轴已经是每组输入通道数;转置卷积的权重轴含义不同,使用时应根据框架的存放顺序调整前两个轴。

  6. 数值对照应比较大量权重的经验均值和方差,而不是要求自编程序与 PyTorch 逐元素相同。设 w 是 PyTorch 中按 (fan_out, fan_in) 存放的权重,可分别调用

    import torch
    from torch.nn import init
    
    init.xavier_normal_(w, gain=1.0)
    init.xavier_normal_(w, gain=init.calculate_gain("relu"))
    init.kaiming_normal_(w, mode="fan_in", nonlinearity="relu")
    init.kaiming_normal_(w, mode="fan_out", nonlinearity="relu")
    

    这四种调用对应普通 Xavier、带 ReLU 增益的 Xavier 折中、fan-in 模式 He 和 fan-out 模式 He。它们的理论方差依次为 \(2/(d_{\mathrm{in}}+d_{\mathrm{out}})\)⁠、\(4/(d_{\mathrm{in}}+d_{\mathrm{out}})\)⁠、\(2/d_{\mathrm{in}}\)\(2/d_{\mathrm{out}}\)⁠。kaiming_normal_nonlinearity="relu" 会使用 ReLU 增益;mode 决定优先保持前向激活还是后向梯度。PyTorch 的 fan 计算默认权重用于 x @ w.T若程序使用 x @ w应对转置后的权重调用初始化函数,否则 fan-in 与 fan-out 会交换。

      网络核验时,前向钩子应记录激活均值和二阶矩,例如 (output.detach() ** 2).mean()梯度钩子记录各层梯度范数。使用相同输入分别检查两种 mode 和两种 gain才能判断自编实现是否与对应框架设置一致。若激活二阶矩或梯度范数随深度迅速趋近 0 或持续增大,应先核对初始化模式、激活函数和权重存放顺序。

  7. 测试可分为确定性检查、统计检查和错误输入检查。使用两个由相同种子创建的 np.random.default_rng相同调用应得到逐元素相同的权重;零初始化应满足 np.count_nonzero(weight) == 0二维权重 (64, 128) 必须得到 fan_in=128fan_out=64因此两种 He 模式的理论方差分别为 \(2/128\)\(2/64\)⁠,不能返回相同尺度。可执行检查例如

    shape = (64, 128)
    w_in = init_weight(
        shape, "he", np.random.default_rng(7), mode="fan_in"
    )
    w_out = init_weight(
        shape, "he", np.random.default_rng(7), mode="fan_out"
    )
    
    np.testing.assert_allclose(w_in.var(), 2 / 128, rtol=0.15)
    np.testing.assert_allclose(w_out.var(), 2 / 64, rtol=0.15)
    assert w_out.std() > w_in.std()
    

    卷积权重 (16, 8, 3, 3) 应得到 fan_in=72fan_out=144还应分别检查普通 Xavier 和带 ReLU 增益折中的经验方差,覆盖指定标准差的正态初始化,并确认空维度、一维权重、零长度轴、非整数维度、负标准差、未知方法和非法 mode 都会明确报错。统计容差应随权重元素数确定,不能要求有限随机样本精确等于理论方差。

  8. 六种方法应明确为零初始化、过小高斯、过大高斯、普通 Xavier、fan-in 模式 He 和 fan-out 模式 He。所有方法使用相同的数据划分、网络结构、优化器、训练更新次数、批次顺序和随机种子集合;不同初始化方法可以使用各自独立但可复现的参数随机数生成器。每个随机种子都要保留,失败或产生非有限损失的运行也应报告,不能只挑选成功结果。

      结果表应包含训练集、验证集和测试集任务指标及其多次运行的均值与波动、达到预先规定验证指标所需时间、总训练时间、固定批量预测时间、参数量和峰值内存。还应逐层记录训练开始时及训练过程中的激活二阶矩和梯度范数。零初始化通常难以打破隐藏神经元的对称性;过小或过大高斯可能造成信号逐层衰减或放大;fan-in 模式 He 更关注 ReLU 网络的前向激活,fan-out 模式 He 更关注后向梯度。普通 Xavier 是不含 ReLU 增益的前后向折中,但具体结果仍取决于网络宽度、数据和优化设置。网络结构相同时,参数量和预测计算过程不因初始化方法而改变,固定批量预测时间的微小差异通常只是计时波动。

  9. 本题共有 \(3\times3=9\) 个“初始化方法—学习率”组合:普通 Xavier、fan-in 模式 He、fan-out 模式 He 分别与三个预先给定的学习率组合。所有组合使用相同的数据划分、网络结构、批量大小、训练轮数、批次顺序和随机种子集合;三个学习率必须在实验前确定,不能根据测试集结果为某一种初始化方法单独增加候选值。

      对每个组合报告任务性能、训练是否稳定、损失是否保持有限、达到验证指标所需的更新次数和时间、总训练时间、固定批量预测时间、参数量和峰值内存,并画出训练损失与验证指标随更新次数变化的曲线。比较时既要在同一初始化方法内观察学习率变化,也要在同一学习率下比较三种初始化方法。较大的初始化尺度与较大学习率同时出现时更容易造成更新过大;较小学习率则可能在规定训练轮数内尚未收敛。初始化方法和学习率不会改变网络参数量,主要差异应体现在优化轨迹、稳定性和任务表现上。

  10. 四组实验可明确写为“tanh 函数 + 普通 Xavier”“tanh 函数 + fan-in 模式 He”“ReLU 函数 + 普通 Xavier”和“ReLU 函数 + fan-in 模式 He”。如果选择其他 He 模式,必须在实验开始前说明,并在所有相关组中保持一致。四组使用相同的数据划分、网络深度与宽度、随机种子集合、优化器、训练更新次数和评价程序,只改变激活函数与初始化方法的组合。

      这四组形成一个简单的二因素比较:在初始化相同时比较 tanh 函数与 ReLU 函数,可以分析激活函数的影响;在激活函数相同时比较普通 Xavier 与 He 初始化,可以分析初始化尺度的影响。tanh 函数与普通 Xavier、ReLU 函数与 fan-in 模式 He 通常是较匹配的组合,但不能在看到结果之前认定它们一定最好。除任务指标外,应逐层报告激活均值、激活二阶矩和梯度范数,并报告训练时间、固定批量预测时间和峰值内存。四组结构相同时参数量相同,不应把少量计时波动解释成结构性效率差异。