改善深度神经网络:超参数调试、正则化以及优化——实践方面(2-1)

本文探讨了在深度学习中防止过拟合的各种方法,包括偏差/方差的理解、L2正则化、Dropout正则化等。并介绍了如何初始化神经网络权重以避免梯度消失或爆炸问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.测试集

在配置训练、验证和测试数据集的过程中做出正确决策会更高效的创建神经网络

在机器学习中,经常将样本分为训练集、验证集和测试集三部分。对于早期的机器学习的数据而言,经常使用 70%/30% 来划分验证集和测试集或者使用 60%/20%/20% 来划分训练集、验证集和测试集。

在大数据时代中,假如有1000000个数据,那么验证集就不需要太大,有10000条验证数据或者10000条测试数据就够了,即占到总量的10%以下

举个例子:

假如需要做一个应用程序,分辨出用户上传的图片上含有猫的照片。
训练集:网页抓取,专业处理,分辨率高,这会导致训练集和验证集不是同一个分布
测试集:用户随机拍的,模糊,分辨率低

需要注意:验证集和测试集的数据来自同一分布。

  1. 偏差/方差

深度学习的误差很少权衡偏差和方差,总是分别考虑:

high bias:第1种情况,如果给这个数据集拟合一条直线,可能得到一个逻辑回归拟合,但并不能很好的拟合该数据集,即偏差高,为“欠拟合”。

high variance:第3种情况,如果拟合了一个很复杂的分类器,比如用了深度神经网络,可能很好的把数据即分类了,但是这种分类器方差较高,数据过度拟合。

**just right:**第2种情况,复杂度适中,数据拟合适度,称为适度拟合。

这里写图片描述

理解偏差和误差还可以通过训练集误差和验证集误差来评判:

**情况1:**假设训练集误差为 1%,验证集误差为11%,训练集设置较好,而验证集设置较差,过度拟合了训练集,高方差。

**情况2:**训练集误差为15%,而验证集误差为16%,而人的错误率几乎为0%,这个数据拟合不高,则为欠拟合,即偏差高。

**情况3:**训练集误差为15%,而验证集误差则更大,为30%,这种情况下,算法偏差高,方差也高。

**情况4:**训练集误差为0.5%,验证集误差为1%,偏差和方差都很低。

以上情况都是基于最优误差为0%(即基本误差很小)和训练集、验证数据来自同一分布前提下的。但是如果一张图片很模糊,人眼分辨误差为15%,那最后我们判断的思路就要换一下了。

这里写图片描述

算法偏差过高——选择新的算法,比如含有更多隐层或者隐藏单元的网格(解决掉偏差问题是最基础的,如果网络够大,通常可以很好的拟合训练集)—— 检查方差有没有问题(如果方差太大,搜集更多的数据)——直至找到一个偏差和方差都很小的框架

在深度学习中,可以通过构建大的神经网络减小偏差而不影响方差,可以通过大量的数据减小方差而不影响误差,所以不用去权衡方差与偏差的关系。

3.L2正则表达式正则化(Regularization)

如果怀疑神经网络过度拟合了数据,即存在高方差问题,那么最先想到的方法可能是正则化或者准备更多的数据。

minw,bJ(w,b)\underset{w,b}{min}J(w,b)w,bminJ(w,b) (通过优化w,b来减少代价函数)

具体一点,我们有:

J(w,b)=1m∑i=1mL(y∧(i),y(i))+λ2m∥w∥22J(w,b)=\frac{1}{m}\sum_{i=1}^{m}L(\overset{\wedge}{y}^{(i)},y^{(i)})+\frac{\lambda }{2m}\left \| w \right \|^{2}_{2}J(w,b)=m1i=1mL(y(i),y(i))+2mλw22

其中,m代表的是样本的数量, λ\lambdaλ是正则化参数(这也是一个超级参数),∥w∥22=∑j=1nxwj2=wTw\left \| w \right \|^{2}_{2} = \sum_{j=1}^{n_{x}} w_{j}^{2}=w^{T}ww22=j=1nxwj2=wTw,这个称为L2正则表达式,只加w而不加a是因为w通常是一个高维参数矢量,已经可以表达高偏差问题了,w里有很多参数,基本上涵盖了所有参数,而不是b。

当然也有L1 表达式(regularization),可直接将 ∣∣w∣∣22||w || _{2}^{2}w22换成||w||,公式为 ∣∣w∣∣1=∑j=1nxwj||w || _{1}= \sum_{j=1}^{n_{x}} w_{j}w1=j=1nxwj

如果使用使用L1 正则表达式,则W会是个稀疏矩阵,即W向量中有很多0,尽管变稀疏了,但是却没有压缩内存,所以在训练模型的时候,更多的是使用L2正则化。

对于神经网络而言,J(w[1],b[1],...,wl],b[l])=1m∑i=1mL(y∧(i),yl)=λ2m∑l=1L∣∣wl∣∣F2J(w^{[1]},b^{[1]},...,w^{l]},b^{[l]})=\frac{1}{m}\sum_{i=1}^{m}L(\overset{\wedge}{y}^{(i)},y^{l})=\frac{\lambda}{2m}\sum_{l=1}^{L}||w^{l}||_{F}^{2}J(w[1],b[1],...,wl],b[l])=m1i=1mL(y(i),yl)=2mλl=1LwlF2

其中, w:(n[l−1],n[l])w:(n^{[l-1]},n^{[l]})w:(n[l1],n[l]),这里l-1指的是隐藏单元的数量(我觉得这里是指下一层隐含层),n[l]表示l层单元的数量,∣∣wl∣∣F2=∑i=1n[l−1]∑j=1n[l](wij[l])2||w^{l}||_{F}^{2}=\sum_{i=1}^{n^{[l-1]}}\sum_{j=1}^{n^{[l]}}(w_{ij}^{[l]})^{2}wlF2=i=1n[l1]j=1n[l](wij[l])2,这里是指的该矩阵范数被称作“费罗 贝尼乌斯范数”,即矩阵每个元素的平方和。

正则化表达式主要是通过设置 λ\lambdaλ来降低w的权重,从而实现对过拟合的调整

这里写图片描述

通过L2调整的方式:
对于矩阵W的导数,我们有dW[l]=(from back propagation)+λmW[l]\frac{\lambda}{m} W^{[l]}mλW[l]
则对于新的更新迭代的下一轮W,我们有
W[l]:=W[l]−αdW[l]W^{[l]}:=W^{[l]}-\alpha dW^{[l]}W[l]:=W[l]αdW[l]

则有 W[l]:=W[l]−αλmW[l]−α(frombackpropagation)W^{[l]} :=W^{[l]}-\alpha \frac{\lambda}{m} W^{[l]}-\alpha (from back propagation)W[l]:=W[l]αmλW[l]α(frombackpropagation)

由于在梯度下降的时候,权重系数乘了一个比1小的系数,所以在每次迭代更新的时候,都会使得W这个权重变小,在不断迭代的过程中对权重进行衰减,所以也成为“权重衰减”。因为相应的把权重W给降低了,则输出的z=Wx+b 较小,如果是tanh函数,那么在接近0的时候呈线性,而不是复杂的非线性高方差拟合。

Python代码实现:

如何在代价函数的基础上增加惩罚项(forward propagation):

def compute_cost_with_regularization(A3,Y,parameters,lambd):
    
    ''''  
    Arguments:A3-post-activation,output of forward propagation,of shape
    Y-"true" labels vector,of shape
    parameters-python dictionary containing parameters of the model
    lambd-hyper paramter lambd是超参数
    Returns:
    cost-vaule of the regularized loss function
    
    '''' 
    m=Y.shape[1]   # if Y is the matrix 1 by m,and then Y.shape[1] is equal to m 
    W1=parameters["W1"]  #这里假设是3层神经网络,这里为第一层的权重
    W2=parameters["W2"] 
    W3=parameters["W3"]
    
    cross_entropy_cost=compute_cost(A3,Y) #This gives you the cross-enteropy part of the cost,假设已经计算出了代价函数 
    
    L2_regularization_cost = (1/m)*(lambd/w)*(np.sum(np.square(W1))+np.sum(np.square(W2))+np.sum(np.square(W3)))  #惩罚项,L2范数
    
    cost function = cross_entropy_cost+L2_regularization_cost
    
    return cost 

Back propagation(反向传播):

def backward_propogation_with_regularization(X,Y,cache,lambd):
    ''''
    X-input dataset,of shape(input size,number of examples)
    Y-"true"label vector,of shape(output size,number of example)
    cache-cache output from forward_propagation()
    lambd-regularization hyperparameter,scalar 
    
    Returns:
    gradients-A dictionary with the gradients with respect to each parameter,activation and pre-activation variables
    
    ''''
    m=X.shape[1]  
    (Z1,A1,W1,b1,Z2,A2,W2,b2,Z3,A3,W3,b3)=cache
    
    dZ3=A3-Y
    dW3=1./m*np.dot(dZ3,A2.T)+(lambd/m)*W3
    db3=1./m*np.sum(dZ3,axis=1,keepdims=True)
    
    dA2=np.dot(W3.T,dZ3)
    dZ2=np.multiply(dA2,np.int64(A2>0)#对激活函数进行求导,multiply是对应值相乘,这里应该是ReLU函数
    dW2=1./m*np.dot(dZ2,A1.T)+(lambd/m)*W2
    db2=1./m*np.sum(dZ2,axis=1,keepdims=True)
    
    dA1=np.dot(W2.T,dZ2)
    dZ1=np.multiply(dA1,np.int64(A1>0))
    dW1=1./m*np.dot(dZ1,A1.T)+(lambd/m)*W1
    db1=1./m*np.sum(dZ1,axis=1,keepdims=True)
    
    gradients={"dZ3":dZ3,"dW3":dW3,"db3:":db3,"dZ2":dZ3,"dW2":dW3,"db2:":db3,"dZ1":dZ1,"dW1":dW1,"db1:":db1}  #创建梯度下降的字典
    
    return gradients

4.Dropout 正则化

当我们训练以下的神经网络的时候,出现了过拟合,dropout 会遍历网络的每一层,并设置消除神经网络中节点的概率,假设网络中的每个节点都以抛硬币的方式设置概率,保留和消除的概率都是0.5,设置完节点概率后,就会消除一些节点,然后用back propagation进行训练。

这里写图片描述

反向随机失活(inverted dropout)
处于完整性来考虑,我们用一个三层(l=3)网络来举例说明,说明如何在某一层中实施dropout,首先要定义向量d,d3表示一个三层的
dropout 向量,看是否d3=np.random.rand(a3.shape[0],a3.shape[1]) (创建一个维数与a3相同的矩阵)<keep-prob(是个数字,上个示例中它是0.5,本例中设为0.8,表示保存某个隐藏单元的概率,则消除任意一个隐藏单元的概率为0.2)

d3=np.random.rand(a3.shape[0],a3.shape[1])  #d3是一个布尔数组
a3=np.multiply(a3,d3)   将矩阵d3和a3矩阵对应元素相乘,作用是过滤掉d3中所有等于0的元素
a3 /= keep-prob #当我们删除a3中一些神经元的时候,为了使得z^[4]=w^[4]a^[3]+b^[4],那么我们需要修正或者弥补我们所需的那20%,从而使得a3的期望值不会改变,只是减少了网络的节点。

这里写图片描述

5.其他正则化方法

扩充(augment)训练数据来解决过拟合
如图,可以通过水平翻转、剪裁图片来增加训练集,虽然数据没那么多,
但是减少了扩张数据的代价。对于数字,还可以通过扭曲来增加训练集。

这里写图片描述

6.正则化输入

归一化输入需要俩个步骤:1.零均值化 (就是把数据集的散点移动到坐标轴附近,1图到2图) 2.归一化方差(下图的x1的方差比x2的方差要大得多,2图到3图,x1和x2的方差都为1)
这里写图片描述

如果需要用方差和均值来调整训练集数据,那么需要用相同的u和 σ2\sigma^{2}σ2来归一化测试集,而不是在训练集和测试集上分别预估u和 σ2\sigma^{2}σ2,因为我们希望的是,训练集和测试集都是通过相同u和 σ2\sigma^{2}σ2定义的相同数据转换,其中u和 σ2\sigma^{2}σ2是由训练集数据计算得来的。

为什么要归一化输入特征?
如下图,代价函数归一化之前和之后,归一化前,狭长型,归一化后,均匀许多。如果在归一化之前的图进行梯度下降,那么学习率需要很小,狭长型的那边需要迭代很多次。如果在归一化之后的,学习率和迭代步长可以较大,迭代次数也可以变小。

这里写图片描述

如果输入的特征取值范围相差很大,那么归一化起重要作用。如果相差不大,那么归一化特征就不是很重要了。

7.梯度消失和梯度爆炸

也就是说,当训练深度网络时,导数或坡度有时候会变得非常大。举个例子,假如我们有l层神经网络,输入特征为x[x1,x2],权重为 w[l]w^{[l]}w[l],设b[l]b^{[l]}b[l]=0,激活函数g(z)=z,则有:

y∧=w[l]w[l−1]⋯w1x\overset{\wedge}{y}=w^{[l]}w^{[l-1]}\cdots w^{1}xy=w[l]w[l1]w1x

设权重 w[l]=[1.5001.5]w^{[l]}=\begin{bmatrix} 1.5 &amp; 0 \\ 0 &amp; 1.5 \end{bmatrix}w[l]=[1.5001.5] >0(1.5倍个单位矩阵),则
y∧=1.5lx\overset{\wedge}{y}=1.5^{l}xy=1.5lx,直接呈爆炸性增长,若w<1,则为爆炸性递减。

8.神经网络的权重初始化

先举一个神经元初始化的例子,单个神经元可能有4个输入特征,从X1到X4,经过激活函数a=g(z),最终得到 y∧\overset{\wedge}{y}y,则得到: z=w1x1+w2x2+⋯+wnxnz=w_{1}x_{1}+w_{2}x_{2}+\cdots +w_{n}x_{n}z=w1x1+w2x2++wnxn,为了预防z值过大或者过小,当n越大的时候,我们希望的是w[i]越小,最合理的方法就是设置w[i]=1/n (n为神经元的输入特征数量)

则有公式:W[l]=np.random.randn(shape)∗np.sqrt(1/n[l−1])W^{[l]}=np.random.randn(shape)*np.sqrt(1/n^{[l-1]})W[l]=np.random.randn(shape)np.sqrt(1/n[l1])

其中W为l层的权重矩阵,shape为矩阵的维数,其中sqrt表示平方根

对于其他变体函数,针对不同激活函数而言:
1.对于tanh 激活函数,则乘以 1nl−1\sqrt{\frac{1}{n^{l-1}}}nl11,被称为Xavier 初始化,有些作者也习惯使用 2n[l−1]+n[l]\sqrt{\frac{2}{n^{[l-1]}+n^{[l]}}}n[l1]+n[l]2

2.对于ReLU 激活函数(最常用),则乘以 2nl−1\sqrt{\frac{2}{n^{l-1}}}nl12

9.梯度的数值逼近

在实施back propagation时,有一个测试叫作梯度检验,它的作用是确保backpropagation正确实施,需要逐渐实现梯度检验。

假设有一个函数为 f(θ)=θ3f(\theta)=\theta^{3}f(θ)=θ3,在 θ\thetaθ右边取 θ+ε\theta+\varepsilonθ+ε,在左边取 θ−ε\theta-\varepsilonθε,设取值分别为1,1.01,0.99,则 ε=0.01\varepsilon =0.01ε=0.01,如下图:
这里写图片描述

上图可得,较大的三角形的高比值更接近于 ε\varepsilonε 的导数,得到的是一个双边公差,期望值为:

3θ2=g(θ)≈f(θ+ε)−f(θ+ε)2ε3\theta^{2}=g(\theta)\approx \frac{f(\theta+\varepsilon )-f(\theta+\varepsilon )}{2\varepsilon }3θ2=g(θ)2εf(θ+ε)f(θ+ε) (可自行代入数据感受下)

如果只考虑到单边误差,即 f(θ+ε)−f(θ)ε\frac{f(\theta+\varepsilon )-f(\theta )}{\varepsilon }εf(θ+ε)f(θ) 或者 f(θ)−f(θ−ε)ε\frac{f(\theta)-f(\theta-\varepsilon)}{\varepsilon }εf(θ)f(θε),误差会更大。

所以,用双边误差的方法更逼近导数,更加精确。
这里写图片描述

10.梯度检验

假如有 W[1],b[1],⋯&ThinSpace;,W[l],b[l]W^{[1]},b^{[1]},\cdots ,W^{[l]},b^{[l]}W[1],b[1],,W[l],b[l],把所有的W矩阵都换成向量之后,做连接运算(得到一个巨型向量 θ\thetaθ

紧接着,我们有
dW[1],db[1],⋯&ThinSpace;,dW[1],db[l]dW^{[1]},db^{[1]},\cdots,dW^{[1]},db^{[l]}dW[1],db[1],,dW[1],db[l],用来初始化大向量 dθd\thetadθ

J(θ)=J(θ1,θ2,⋯&ThinSpace;,θn)J(\theta)=J(\theta_{1},\theta_{2},\cdots,\theta_{n})J(θ)=J(θ1,θ2,,θn)

则我们有:

∂J(θ)∂θ1=J(θ1+ε,θ2,⋯&ThinSpace;,θn)−J(θ1−ε,θ2,⋯&ThinSpace;,θn)2ε\frac{\partial J(\theta)}{\partial \theta _{1}}=\frac{J(\theta_{1}+\varepsilon,\theta_{2},\cdots,\theta_{n})-J(\theta_{1}-\varepsilon,\theta_{2},\cdots,\theta_{n})}{2\varepsilon }θ1J(θ)=2εJ(θ1+ε,θ2,,θn)J(θ1ε,θ2,,θn)
⋮\vdots
∂J(θ)∂θn=J(θ1,θ2,⋯&ThinSpace;,θn+ε)−J(θ1,θ2,⋯&ThinSpace;,θn−ε)2ε\frac{\partial J(\theta)}{\partial\theta _{n}}=\frac{J(\theta_{1},\theta_{2},\cdots,\theta_{n}+\varepsilon)-J(\theta_{1},\theta_{2},\cdots,\theta_{n}-\varepsilon)}{2\varepsilon }θnJ(θ)=2εJ(θ1,θ2,,θn+ε)J(θ1,θ2,,θnε)

上面求出的 ∂J(θ)∂θn\frac{\partial J(\theta)}{\partial\theta _{n}}θnJ(θ)只是近似值,我们要判断的就是这个近似值 ∂J(θ)∂θn\frac{\partial J(\theta)}{\partial\theta _{n}}θnJ(θ)∂J(θ)∂θntrue\frac{\partial J(\theta)}{\partial\theta _{n}}_{true}θnJ(θ)true 真实值是否等同,则我们只需要检验其向量的差值:

∣∣∂J(θ)∂θn−∂J(θ)∂θntrue∣∣2||\frac{\partial J(\theta)}{\partial\theta _{n}}-\frac{\partial J(\theta)}{\partial\theta _{n}}_{true}||_{2}θnJ(θ)θnJ(θ)true2 再除以俩者的和

如果我们的 ε\varepsilonε 取值是10(-7),当求出来的距离是10(-5)或者10^(-3),那么就要小心了,可能程序有bug

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值