d2l自学笔记 – 4.多层感知机

《动手学深度学习》 — 动手学深度学习 2.0.0-beta0 documentation (d2l.ai)

多层感知机

基本概念

  • 多层感知机(multilayer perceptron, MLP)
  • 输入层 – 隐藏层(hidden layer) – 输出层
  • 激活函数(activation function)

通过使用更深(而不是更广)的网络,可以更容易地逼近许多函数。(为什么?

常见激活函数

ReLU函数(Rectified linear unit, 修正线性单元)

ReLU(x)=max(x,0)\operatorname{ReLU}(x)=\max (x, 0)

pReLU函数(Parametric Rectified Linear Unit, 参数化修正线性单元)

pReLU(x,α)=max(0,x)+αmin(0,x)\operatorname{pReLU}(x,\alpha)=\max (0,x)+\alpha\min(0,x)

sigmoid函数(又称squashing function, 挤压函数)

sigmoid(x)=11+ex\operatorname{sigmoid}(x)=\frac{1}{1+e^{-x}}

tanh函数(双曲正切函数)

tanh(x)=exexex+ex=1e2x1+e2x\operatorname{tanh}(x)=\frac{e^{x}-e^{-x}}{e^{x}+e^{-x}}=\frac{1-e^{-2x}}{1+e^{-2x}}

形状类似sigmoid函数,不同的是tanh函数关于坐标系原点中心对称。

模型与模型参数的初始化

通常选择2的次幂作为层的宽度,以便内存分配与寻址。

num_inputs, num_outputs, num_hiddens = 784, 10, 256

W1 = nn.Parameter(torch.randn(
    num_inputs, num_hiddens, requires_grad=True) * 0.01)
b1 = nn.Parameter(torch.zeros(num_hiddens, 
requires_grad=True))
W2 = nn.Parameter(torch.randn(
    num_hiddens, num_outputs, requires_grad=True) * 0.01)
b2 = nn.Parameter(torch.zeros(num_outputs, requires_grad=True))

def relu(X):
    return torch.max(X, torch.zeros_like(X))

def net(X):
    X = X.reshape((-1, num_inputs))
    H = relu(X@W1 + b1)
    return (H@W2 + b2)

或者使用高级API

net = nn.Sequential(nn.Flatten(),
    nn.Linear(num_inputs, num_hiddens),
    nn.ReLU(),
    nn.Linear(num_hiddens, num_outputs)
)

def init_weights(m):
    if type(m) == nn.Linear:
        nn.init.normal_(m.weight, std=0.01)

net.apply(init_weights)

模型选择、欠拟合与过拟合

基本概念

  • 模式(pattern)
    目标:发现反应训练集潜在总体规律的模式\rightarrow泛化能力
  • 欠拟合(underfitting)
  • 过拟合(overfitting)
    正则化(regularization):用于对抗过拟合的技术
  • 训练误差(training error)
  • 泛化误差(generalization error)
  • 训练集(train) – 验证集(validation) – 测试集(test)

训练集用来估计模型,
验证集用来确定网络结构或者控制模型复杂程度的参数,
测试集用来检验最终选择最优的模型的性能如何。

影响模型泛化的因素

  1. 可调整参数的数量
  2. 参数采用的值(权重取值范围较大时,模型可能更容易过拟合)
  3. 训练样本的数量

K折交叉验证

为什么?

有时训练数据稀缺,可能无法提供足够数据来构成一个合适的验证集。此时通常会使用K折交叉验证。

是什么?

将原始训练数据分成K个无交集,然后执行K次模型训练和验证。每次在K-1个子集上训练,最后一个子集用来验证。

最后,通过对K次实验的结果取平均来估计训练和验证误差。

权重衰减(weight decay, L2L_2正则化)

缓解过拟合:

  1. 限制特征数量
  2. 限制模型参数选择范围

权重衰减是一种广泛使用的正则化技术。

通过函数与零的距离(范数)来衡量函数的复杂度。将函数复杂度作为惩罚项加到最小化损失的问题中,以保证权重向量比较少。新的损失函数可以写做:

L(w,b)+λ2w2w(1ηλ)wηBiBx(i)(wx(i)+by(i))L(\mathbf{w}, b)+\frac{\lambda}{2}\|\mathbf{w}\|^{2} \\ \mathbf{w} \leftarrow(1-\eta \lambda) \mathbf{w}-\frac{\eta}{|\mathcal{B}|} \sum_{i \in B} \mathbf{x}^{(i)}\left(\mathbf{w}^{\top} \mathbf{x}^{(i)}+b-y^{(i)}\right)

λ\lambda为正则化常数,是一个非负超参数。

这里使用了L2L_2范数,而非L1L_1范数。

L2L_2正则化线性模型:岭回归(ridge regression)

  • 对权重向量的大分量施加了巨大的乘法
  • 偏向于在大量特征上均匀分布权重的模型
  • 可能使对单个变量的观测误差更稳定(为什么?

L1L_1正则化线性模型:套索回归(lasso regression)

  • 权重集中于一小部分特征
  • 其他权重清零(可以从图中蓝色方形与红色椭圆的交点看出)
  • 具有特征选择(feature selection)的能力

图片来源及详细解释参见机器学习算法实践-岭回归和LASSO – 知乎

权重衰减的实现

trainer = torch.optim.SGD([
    {'params': net[0].weight, 'weight_decay': wd},
    {'params': net[0].bias}], lr=lr)

暂退法(Dropout)

为什么?

避免过拟合

是什么?

在前项传播过程中,计算每一内部层的同时注入噪声。从表面上看是在训练过程中丢弃(dropout)一些神经元。

在标准暂退法正则化中,每个中间活性值hh以暂退概率pp由随机变量hh'替换,同时期望值E[h]=hE[h']=h保持不变。
h={0 概率为 ph1p 其他情况 h^{\prime}= \begin{cases}0 & \text { 概率为 } p \\ \frac{h}{1-p} & \text { 其他情况 }\end{cases}

需要说明的是,暂退法的原始论文提到了一个关于有性繁殖的类比:神经网络过拟合与每一层都依赖于前一层激活值相关,称这种情况为“共适应性”。作者认为,暂退法会破坏共适应性,就像有性生殖会破坏共适应的基因一样。(没看懂。。

常见技巧:在靠近输入层的地方设置较低的暂退概率。(为什么?

实现

net = nn.Sequential(
    nn.Linear(784, 256),
    nn.ReLU(),
    nn.Dropout(dropout1),
    nn.Linear(256, 256),
    nn.ReLU(),
    nn.Dropout(dropout2),
    nn.Linear(256, 10)
)

前向传播、反向传播和计算图

  • 前向传播(forward propagation 或 forward pass)
  • 矩阵的Frobenius范数:将矩阵展平为向量后应用的L2L_2范数
  • 反向传播(backward propagation 或 backpropagation)

反向传播重复利用前向传播中存储的中间值,以避免重复计算。我们需要保留中间值,直到反向传播完成。

这也是训练比单纯预测需要更多内存(显存)的原因之一。

使用更大批量来训练更深层次的网络更容易导致内存不足错误。

数值稳定性和模型初始化

输出o\mathbf{o}关于任何一组参数W(l)\mathbf{W}^{(l)}的梯度为:
W(l)o=h(L1)h(L)M(L)= def h(l)h(l+1)M(l+1) def =W(l)h(l)v(l)= def \partial_{\mathbf{W}^{(l)}} \mathbf{o}=\underbrace{\partial_{\mathbf{h}^{(L-1)}} \mathbf{h}^{(L)}}_{\mathbf{M}^{(L)} \stackrel{\text { def }}{=}} \cdot \ldots \cdot \underbrace{\partial_{\mathbf{h}^{(l)}} \mathbf{h}^{(l+1)}}_{\mathbf{M}^{(l+1) \text { def }}=} \underbrace{\partial_{\mathbf{W}^{(l)}} \mathbf{h}^{(l)}}_{\mathbf{v}^{(l)} \stackrel{\text { def }}{=}}

为避免数值下溢影响,一个常见技巧是切换到对数空间,即将数值表示的压力从尾数转移到指数。

梯度消失(gradient vanishing)

  • 参数更新过小,在每次更新时几乎不会移动,导致模型无法学习。
  • 例如sigmoid函数,在输入很大或很小时,梯度都会消失。
    相比之下,ReLU激活函数缓解了梯度消失问题,加速收敛。
  • 网络较深时,容易在某一层切断梯度。

梯度爆炸(gradient explosion)

  • 参数更新过大,破坏了模型的稳定收敛。

打破对称性

隐藏层参数不能初始化为相同值,因为小批量随机梯度下降不会破坏对称性(尽管暂退法正则化可以)。

随机初始化

Xavier参数初始化

在线性全连接层中,当正向传播时,若要从输入到输出方差保持不变(为什么?),则需要权重标准差σ\sigma满足ninσ2=1n_{\text{in}}\sigma^2=1;当反向传播时,同理需要权重标准差σ\sigma满足noutσ2=1n_{\text{out}}\sigma^2=1为什么?)。

为了平衡二者需求,取

12(nin +nout )σ2=1 或等价于 σ=2nin +nout \frac{1}{2}\left(n_{\text {in }}+n_{\text {out }}\right) \sigma^{2}=1 \text { 或等价于 } \sigma=\sqrt{\frac{2}{n_{\text {in }}+n_{\text {out }}}}

权重可以按高斯分布初始化,也可以按均匀分布初始化,但方差均如上式描述。

环境和分布偏移

机器学习许多应用存在的问题:通过将基于模型的决策引入环境,我们可能会破坏模型。

在很多情况下,训练集和测试集并不来自同个分布,这就是所谓的分布偏移。假设训练数据集分布为Ptra(x,y)P_{\text{tra}}(x,y),测试数据集分布为Ptst(x,y)P_{\text{tst}}(x,y)

经验风险与实际风险

经验风险(empirical risk)最小化

minimizef1ni=1nl(f(xi),yi)\underset{f}{\operatorname{minimize}} \frac{1}{n} \sum_{i=1}^{n} l\left(f\left(\mathbf{x}_{i}\right), y_{i}\right)

真实风险(true risk)

Ep(x,y)[l(f(x),y)]=l(f(x),y)p(x,y)dxdyE_{p(\mathbf{x}, y)}[l(f(\mathbf{x}), y)]=\iint l(f(\mathbf{x}), y) p(\mathbf{x}, y) d \mathbf{x} d y
由于通常无法获取真实分布p(x,y)p(\mathbf{x},y),一般通过最小化经验风险来近似最小化真实风险

下述定义部分摘自
Understanding Dataset Shift. How to make sure your models are not… | by Matthew Stewart | Towards Data Science

协变量偏移(covariate shift)

Covariate shift appears only in XYX \rightarrow Y problems, and is defined as the case where Ptra(yx)=Ptst(yx)P_{\text {tra}}(y \mid x)=P_{\text{tst}}(y \mid x) and Ptra(x)P_{\text {tra}}(x) Ptst(x)\neq P_{\mathrm{tst}}(\mathrm{x})

协变量偏移纠正

设训练数据集的观测值x\mathbf{x}来自于某些源分布q(x)q(\mathbf{x})而非目标分布p(x)p(\mathbf{x}),则有:

l(f(x),y)p(yx)p(x)dxdy=l(f(x),y)q(yx)q(x)p(x)q(x)dxdy\iint l(f(\mathbf{x}), y) p(y \mid \mathbf{x}) p(\mathbf{x}) d \mathbf{x} d y=\iint l(f(\mathbf{x}), y) q(y \mid \mathbf{x}) q(\mathbf{x}) \frac{p(\mathbf{x})}{q(\mathbf{x})} d \mathbf{x} d y

若令βi= def p(xi)q(xi)\beta_{i} \stackrel{\text { def }}{=} \frac{p\left(\mathbf{x}_{i}\right)}{q\left(\mathbf{x}_{i}\right)},则可以使用“加权经验风险最小化”来训练模型:
minimizef1ni=1nβil(f(xi),yi)\underset{f}{\operatorname{minimize}} \frac{1}{n} \sum_{i=1}^{n} \beta_{i} l\left(f\left(\mathbf{x}_{i}\right), y_{i}\right)

其中“真实”的分布pp可以通过访问测试数据获取。

现假设有一个训练集{(x1,y1),,(xn,yn)}\left\{\left(\mathbf{x}_{1}, y_{1}\right), \ldots,\left(\mathbf{x}_{n}, y_{n}\right)\right\}和一个未标记的测试集{u1,,um}\left\{\mathbf{u}_{1}, \ldots, \mathbf{u}_{m}\right\},我们预先学习一个分类器来区分从p(x)p(\mathbf{x})抽取的数据和从q(x)q(\mathbf{x})抽取的数据。整个算法包括以下几个步骤:

  1. 生成一个二元分类数据集{(x1,1),,(xn,1),(u1,1),,(um,1)}\left\{\left(\mathbf{x}_{1},-1\right), \ldots,\left(\mathbf{x}_{n},-1\right),\left(\mathbf{u}_{1}, 1\right), \ldots,\left(\mathbf{u}_{m}, 1\right)\right\}
  2. 对数几率回归(logistic regression,softmax回归的二元分类特例) 训练二元分类器得到函数hh
    P(z=1x)=p(x)p(x)+q(x) and hence P(z=1x)P(z=1x)=p(x)q(x)P(z=1x)=11+exp(h(x))P(z=1 \mid \mathbf{x})=\frac{p(\mathbf{x})}{p(\mathbf{x})+q(\mathbf{x})} \text { and hence } \frac{P(z=1 \mid \mathbf{x})}{P(z=-1 \mid \mathbf{x})}=\frac{p(\mathbf{x})}{q(\mathbf{x})}\\ P(z=1 \mid \mathbf{x})=\frac{1}{1+\exp (-h(\mathbf{x}))}
  3. 使用 βi=exp(h(xi))\beta_{i}=\exp \left(h\left(\mathbf{x}_{i}\right)\right) 或更好的 βi=min(exp(h(xi)),c)\beta_{i}=\min \left(\exp \left(h\left(\mathbf{x}_{i}\right)\right), c\right) (c为常量) 对训练数据进行加权
  4. 使用权重 βi\beta_{i} 进行 {(x1,y1),,(xn,yn)}\left\{\left(\mathbf{x}_{1}, y_{1}\right), \ldots,\left(\mathbf{x}_{n}, y_{n}\right)\right\} 的训练

标签偏移(label shift, prior probability shift)

Prior probability shift appears only in YXY \rightarrow X problems, and is defined as the case where Ptra(xy)=Ptst(xy)P_{\text {tra}}(x \mid y)=P_{\text {tst}}(x \mid y) and Ptra(y)Ptst(y)P_{\text {tra}}(y) \neq P_{\text{tst}}(y)

标签偏移纠正

同样地可以定义βi= def p(yi)q(yi)\beta_{i} \stackrel{\text { def }}{=} \frac{p\left(y_{i}\right)}{q\left(y_{i}\right)},根据加权经验风险最小化来训练模型。

下面给出估算目标标签分布pp的一种方法:

  1. 计算验证集(为什么?)的混淆矩阵C\mathbf{C}。该矩阵中每个单元格cijc_{ij}的值表示验证集中真实标签为jj,模型预测为ii的样本占比。

  2. 将所有模型在测试时的预测取平均数,得到平均模型输出μ(y^)Rk\mu(\hat{\mathbf{y}}) \in \mathbb{R}^{k}

  3. 可以通过求解一个简单线性系统来估算测试集的标签分布pp
    Cp(y)=μ(y^)\mathbf{C} p(\mathbf{y})=\mu(\hat{\mathbf{y}})
    j=1kcijp(yj)=μ(y^i)\sum_{j=1}^{k} c_{i j} p\left(y_{j}\right)=\mu\left(\hat{y}_{i}\right)

概念偏移(concept shift)

Concept shift is defined as

  • Ptra(yx)Ptst(yx)P_{\text {tra}}(y \mid x) \neq P_{\text{tst}}(y \mid x) and Ptra(x)=Ptst(x)P_{\text {tra}}(x)=P_{\text{tst}}(x) in XYX \rightarrow Y problems.
  • Ptra(xy)Ptst(xy)P_{\text {tra}}(x \mid y) \neq P_{\text{tst}}(x \mid y) and Ptra(y)=Ptst(y)P_{\text{tra}}(y)=P_{tst}(y) in YXY \rightarrow X problems.

概念偏移纠正

概念的变化总是缓慢的。我们使用新数据更新现有网络权重,而不是从头开始训练。

一些实战经验

数据预处理

特征数据标准化

因为我们不知道哪些特征是相关的,不想让惩罚分配给一个特征的系数比分配给其他特征的系数更大。

将离散特征转化为独热向量

对数差异

一些情况下,我们关心相对误差yy^y\frac{y-\hat{y}}{y},而非绝对误差yy^y-\hat{y},因此使用对数来衡量差异。

eδy^yeδlogylogy^δe^{-\delta} \leq \frac{\hat{y}}{y} \leq e^{\delta}\Leftrightarrow |\log y-\log \hat{y}| \leq \delta
误差函数为
1ni=1n(logyilogy^i)2\sqrt{\frac{1}{n} \sum_{i=1}^{n}\left(\log y_{i}-\log \hat{y}_{i}\right)^{2}}

发表评论

%d 博主赞过: