首页 > 其他分享 >limu|P10-14|多层感知机、激活函数、模型选择、欠拟合、过拟合、权重衰减、dropout、数值稳定性、模型初始化

limu|P10-14|多层感知机、激活函数、模型选择、欠拟合、过拟合、权重衰减、dropout、数值稳定性、模型初始化

时间:2024-08-15 21:27:31浏览次数:9  
标签:nn 训练 模型 感知机 正则 参数 拟合

从感知机到多层感知机:
感知机:只能产生线性分割面,不能拟合XOR

为突破线性模型的限制,可以通过在网络中加入一个/多个隐藏层,即 多层感知机MLP。但是如果只是单纯添加隐藏层,还是等价于一个线性模型(仿射变换的仿射变换还是仿射变换),没有带来益处!此时,需要加入额外因素以激发多层架构的潜力——对每个隐藏层使用非线性的激活函数,这样多层感知机就不会退化成线性模型

理论上,单隐藏层的网络可以学习任何函数,然而实际中我们并不这么用。因为一个浅但宽的网络很难训练,且易overfit;而一个更深的网络(每层学一点)相对容易训练
———————————————————————————————————
激活函数:
关于激活函数的选择,李沐老师说,激活函数的选择不是很重要,没主意的时候就用ReLU吧,毕竟简单!其他的超参数对于模型更重要些,比如隐藏层数、每层隐藏层的大小
1、ReLU
\(ReLU(x) = max(x,0)\)
(1)ReLU提供了一种非常简单的非线性变换(无指数运算,算起来快)
(2)ReLU的求导表现特别好,要么让参数消失——在输入<0时导数为0,要么让参数通过——输入>0时导数为1,这使得其优化表现很好;输入=0处不可导,但是因为输入不可能为0,可忽略这种情况
(3)ReLU还解决了sigmoid函数在两端梯度消失的问题
2、sigmoid函数
\(sigmoid(x) = \frac{1}{1+exp(-x)}\)
其形状很像一个soft版本的阶跃函数,符合人体神经元的特性。但是由于其两端太平(梯度~0),易造成梯度消失,在激活函数中已较少使用(RNN中还用,用于控制时序信息流)

*softmax和sigmoid:
softmax是线性变换,一般是多类别分类问题的输出层接softmax,使得每个输出在0-1内,和为1
softmax适用于多类别分类,一个正确答案,互斥输出
sigmoid适用于多标签分类,多个正确答案,非互斥输出

3、tanh函数
\(tanh(x) = \frac{1-exp(-2x)}{1+exp(-2x)}\)
把sigmoid原来(0,1)的范围拉到(-1,1)的区间内,且关于原点中心对称

代码实现:
在网络中加入隐藏层和激活函数也比较简单,nn.Sequential里加layer就行:

net = nn.Sequential(nn.Flatten(),
                    nn.Linear(784, 256),
                    nn.ReLU(),
                    nn.Linear(256, 10))

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

net.apply(init_weights);

————————————————————————————————————
训练误差:模型在训练集上计算得到的误差
泛化误差:模型应用于从原始样本的分布中抽取无限多数据样本时,模型误差的期望。难以准确计算,但可以用模型在一个独立测试集or验证集上的误差,即测试误差or验证误差,来估计泛化误差

监督学习场景中,我们假设训练集和测试集是独立同分布的,但事实上可能会轻微违背独立同分布,导致训练出的模型在没见过的数据(测试集or验证集)上表现不好,泛化性不佳

过拟合、欠拟合:模型容量(模型复杂度)& 数据复杂度 不匹配

模型复杂度的影响因素:1-参数数量——模型复杂;2-参数的取值范围大——模型复杂
数据复杂度的影响因素:1-样本个数;2-每个样本的元素个数;3-时间、空间结构;4-多样性

在实际训模型时,我们通过观察训练误差和验证误差来判断有无欠拟合or过拟合
欠拟合训练误差&验证误差都很大,模型无法减小训练误差。意味着,模型过于简单,无法捕捉数据pattern。这时候可以换一个更复杂的模型去降低训练误差
过拟合训练误差明显小于验证误差。意味着,模型过于复杂但数据简单,模型过度关注数据细节甚至噪声,试图记住所有训练数据,偏离了数据本身的主要pattern,导致其在没见过的数据上表现不佳,泛化性不佳

可以看出,欠拟合&过拟合 取决于 模型容量=模型复杂度、数据复杂度
(1)模型复杂&数据量少,往往更易过拟合
(2)模型简单,易欠拟合(此时关键要提升模型复杂度,增加数据量没啥用)

但是,在深度学习领域,过拟合并不总是一件坏事!我们更关心验证误差是不是小,而不是训练误差和验证误差的差距是不是小

关于欠拟合和过拟合的其他解释,见我的另一博客
————————————————————————————————————
模型选择:
训练集:训练模型的参数
验证集:选择模型的超参数
如果数据集小,可以用k折交叉验证(多训几次,但是损失的数据少)

关于k折交叉验证的具体内容,见我的另一博客
————————————————————————————————————
正则化方法——防过拟合:权重衰减、drop out

(零)“正则regularization”的含义:对模型(参数)施加规则(限制)

(一)权重衰减
1、思路
防止过拟合需要限制模型容量,两个途径1-让参数量减少;2-让参数取值范围缩小
*参数范围大,会拟合成很复杂的函数,导致对训练数据过拟合。参数范围小一点的话,拟合曲线会更平滑

缩小参数取值范围的方式:
(1)硬性限制
\(min \quad l(w,b) \quad subject \quad to \quad \|w\|^2 \leqslant \theta\)
\(\theta\)越小,正则项越强
(2)柔性限制
可用拉格朗日乘子证明:使用均方范数作为硬性限制 等价于 如下柔性限制:
\(min \quad l(w,b)+\frac{\lambda}{2}\|w\|^2\)
相当于,原loss中加了L2正则项,用\(\lambda\)控制正则项重要程度,\(\frac{1}{2}\)为了方便之后求导算梯度时与平方抵消

2、参数更新法则:权重衰减
梯度:\(\frac{\partial{l(w,b)}}{\partial(w)}+\lambda{w}\)
更新参数:\(w_{t+1}=(1-\eta\lambda)w_{t}-\eta\frac{\partial{l(w_{t},b_{t})}}{\partial(w_{t})}\)
由于\(\eta\lambda < 1\),深度学习中常称之为权重衰减

3、更多思考
思考1:
在loss中加正则项以防止过拟合,在前文中,我们是根据缩小参数范围可以降低模型容量从而防止过拟合 + 拉格朗日乘子,去证明的
但是,反过来,我们需要思考,最小化原loss和正则项的和,到底有什么实际意义?
(1)可使参数形成稀疏解,从而降低模型复杂度,防过拟合。具体解释见我的另一个blog
(2)limu的解释:

绿线中心:原loss最小化的最优解。但因为数据往往有噪声,模型把自己搞得很复杂以过度记住/关注噪声——过拟合的原因,此时,模型以为的最优(拟合了大量噪声)其实不是最优
黄线中心:正则项最小化的最优解
在原loss中加入正则项后,绿中心不再是最优解,黄线的存在(正则项的存在)把最优解往左下拉(\(\lambda\)决定拉的程度),至两者相交处。这样防止了过拟合

思考2:
为什么深度学习中首先使用L2范数?
首先使用L2范数的一个原因是,它对权重向量的大分量施加巨大惩罚,使得学习算法偏向于 在大量特征上均匀分布权重 的模型(都接近0但不为0),这样对单个变量中的观测误差更为稳定
相比之下,L1范数会导致模型把权重集中于一小部分特征,而把其他的权重清零,这样的做法其实是“特征选择”,可能是其他场景下需要的。
比如在我的另一个blog里对正则化的解释,其实是以L1范数作为正则项为例的,因为那个blog的笔记来自于传统机器学习的课程

4、代码实现:

def train_concise(wd):
    net = nn.Sequential(nn.Linear(num_inputs, 1))
    for param in net.parameters():
        param.data.normal_()
    loss = nn.MSELoss(reduction='none')
    num_epochs, lr = 100, 0.003
    # 偏置参数没有衰减
    trainer = torch.optim.SGD([
        {"params":net[0].weight,'weight_decay': wd}, # 实例化优化器时直接通过weight_decay指定weight decay超参数
        {"params":net[0].bias}], lr=lr)
    animator = d2l.Animator(xlabel='epochs', ylabel='loss', yscale='log',
                            xlim=[5, num_epochs], legend=['train', 'test'])
    for epoch in range(num_epochs):
        for X, y in train_iter:
            trainer.zero_grad()
            l = loss(net(X), y)
            l.mean().backward()
            trainer.step()
        if (epoch + 1) % 5 == 0:
            animator.add(epoch + 1,
                         (d2l.evaluate_loss(net, train_iter, loss),
                          d2l.evaluate_loss(net, test_iter, loss)))
    print('w的L2范数:', net[0].weight.norm().item())

wd取值一般设置为1e-2,1e-3,1e-4如果试了一遍都效果不好(特别是模型很复杂时),可能需要换个正则化方法,比如drop out
(二)drop out
1、思路
防过拟合
——>模型简单
——>模型简单的另一个角度要求“平滑性”
(这一步可以数学证明:要求函数平滑 等价于 要求函数对输入的随机噪声具有适应性
——>对输入的微小变化不敏感,即,对输入添加随机噪声 不影响模型
如何向输入添加噪声?无偏差地加入噪声
对原输入\(x\)加入噪声,变成\(x^{'}\)
(1)每一层期望值不变\(E(x^{'})=x\)
(2)对每个元素产生扰动

\[x_{i}^{'}= \left \{ \begin{array}{rcl} 0 && \text{with probability p} \\ \frac{x_{i}}{1-p} && \text{otherwise} \\ \end{array} \right. \]

上述公式在做的事情是,对一部分输入置零(概率为p),对剩下的输入除以1-p,以保证期望不变
——>从表面上看,是在训练过程中丢弃一些神经元(将当前层中的一些神经元的输出“置零”,等同于,将下一层中一些神经元的输入“置零”),so得名drop out丢弃法

*这里另一个思考点在于,数据本身往往有有偏好的噪声,加入随机噪声,有利于抵消上述偏好,使模型更鲁棒

2、如何实施drop out
一般将丢弃法作用于隐藏全连接层的输出上只在训练中使用丢弃法\(h^{'}=dropout(h)\),推理中不使用——直接返回\(h=dropout(h)\),也保证了模型的确定性输出
*所有正则化方法都只在训练中使用,因为正则化是为了限制模型从而影响参数更新,而只有训练中涉及参数更新

3、更多思考
每次丢弃的神经元不同,可以理解为每次随机采样一个子神经网络进行训练,但在推理时使用所有的神经元(参数),这本质上是一种ensemble,大量dropout形成的很多个网络模型ensemble,会极大提升预测能力 (Hinton解释)
另一方面,每次随机丢弃一部分神经元(输入置零),避免模型过度依赖任何一个神经元,即,避免个别神经元的影响过大,即,个别参数过大的可能性减小
后来大家做实验,发现这个和正则的效果一样,so被认为是正则化的方法

4、代码实现
对于深度学习框架的高级API,我们只需在每个全连接层之后添加一个Dropout层, 将暂退概率作为唯一的参数传递给它的构造函数。 在训练时,Dropout层将根据指定的暂退概率随机丢弃上一层的输出(相当于下一层的输入)。 在测试时,Dropout层仅传递数据。

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)

net.apply(init_weights);

几个重要的点:
(1)nn.Dropout
(2)dropout用在隐藏全连接层之后
(3)丢弃仅发生于训练时
(4)超参数:唯一需要传入的参数是丢弃概率p,一般取0.1、0.5、0.9三种值
————————————————————————————————————
为什么会有数值稳定性问题?
d层的神经网络,计算梯度时,会涉及很多次矩阵的乘法。一旦出现很小或很大的数值,多次乘法后,会出现梯度消失or爆炸

数值稳定性的2个常见问题:梯度消失、梯度爆炸

(一)梯度消失
1、后果
(1)无论怎么调lr,参数不更新,学习没有进展
(2)对神经网络的底层尤为严重:因为梯度是反向传播计算的,从网络顶层到底层,顶层的时候可能梯度没乘几次,不会太小,训练效果可能还行,但底层会梯度为0,根本学习不下去,这时,和一个很浅的网络没区别
2、原因之一
sigmoid函数的输入很大或很小时,其梯度就会消失
解决:一般默认用更稳定的ReLU作为激活函数

(二)梯度爆炸
1、后果
(1)值超出值域,对16位浮点数尤为严重
(2)对lr过于敏感,可能需要训练中不断调整lr
2、原因之一
参数初始化过大
解决:对参数初始化进行限制——在合理区间内随机初始参数——使得每层的输出【正向】和梯度【反向】的分布被限制——均值为0,方差为常数

由数学推理可得Xaiver初始化方法(nn.Linear的默认初始化方法)

总之,让训练更加稳定,目标为使得梯度值在合理范围内,方法:1-乘法变加法,如ResNet、LSTM;2-梯度归一化、梯度裁剪;3-合理权重初始化;4-激活函数选择,如ReLU
——————————————————————————————————
QA:
1、SVM两个缺点:1-数据特别大的时候,算起来慢;2-可调的参数不多(确定性强,模型容量有限)
2、数据预处理,比如标准化要算均值和标准差,最好拿所有的数据一起算,这样比较鲁棒
3、深度学习数据量特别大时,不做交叉验证,要不然成本太高;传统机器学习,一般是做交叉验证的
4、超参数选择,沐神推荐随机100次选最好的
5、按理来说,单隐藏层的MLP可以拟合任何模型,但是其实训练不出来。我们设计深度学习里的各种模型,是在用先验知识去设计一个合适的模型结构——能够更好描述数据pattern——更易训练出来
6、不平衡的数据集,如果真实世界中数据本身就是不平衡的,那没关系,把主流做好就行。但是如果是采样不平衡,则要先平衡数据集(加权重,可以在数据上加权重,也可以在loss加权)
7、关于防止过拟合的调参,即使在验证集上试出了一个比较好的超参数,未必泛化性好。这时候可以往这个超参数周围调一调,如果很敏感,变化大,说明这一带区域不平坦,只是运气好,,这时候还要再调调。工程里,调参不太重要,大概调调就行,因为数据一直会变,在一份数据上调好的超参数,如果来了新的一批数据,未必是好的超参数
8、考虑一个实际问题的解决,思路:(1)ML能不能做,能不能解决这个问题;(2)我需要去收集什么样的数据(自己的数据质量高去得到好的结果,比用烂烂的数据训模型然后费尽心机调参,简单得多)
9、loss曲线可以抖,但不能只抖动不下降,如果光抖不降,考虑把Lr、batch_size调大一点
10、如果出现NaN,是因为除了0;如果出现Inf,是值太大,可能是lr太大,或者权重初始化太大,这时候先往下调,直到不再出现Inf

标签:nn,训练,模型,感知机,正则,参数,拟合
From: https://www.cnblogs.com/xjl-ultrasound/p/18352301

相关文章

  • 大模型微调实战演练:使用代码剖析 Transformers Pipelines工作原理
    在自然语言处理(NLP)领域,Transformers模型已经成为了主流技术之一。无论是文本分类、情感分析,还是机器翻译,Transformers都展现了强大的性能。今天,我们来详细解析一下TransformersPipelines的运行原理,帮助大家更好地理解其内部机制。一、基本流程TransformersPipeline......
  • 分割模型的数据集由json转为txt
    点击查看代码#-*-coding:utf-8-*-importjsonimportosimportargparsefromtqdmimporttqdmimportglobimportcv2importnumpyasnpdefconvert_label_json(json_dir,save_dir,classes):json_paths=os.listdir(json_dir)classes=classes.spli......
  • 回归预测|基于HGS-CNN-LSTM-Attention的数据回归预测Matlab程序 多特征输入单输出 含
    回归预测|基于HGS-CNN-LSTM-Attention的数据回归预测Matlab程序多特征输入单输出含基础模型文章目录前言回归预测|基于HGS-CNN-LSTM-Attention的数据回归预测Matlab程序多特征输入单输出含基础模型一、HGS-CNN-LSTM-Attention模型1.模型组件概述1.1.海鸥优化算......
  • 【模型】XGBoost
    一、XGBoostXGBoost(ExtremeGradientBoosting)是一个强大的机器学习库,用于构建梯度提升决策树(GradientBoostingDecisionTrees,GBDT)模型。它在结构化数据上表现非常出色,广泛应用于分类、回归、排序等任务,尤其在Kaggle等数据竞赛中表现优异。1.XGBoost的核心思想XGBo......
  • 什么?你还不会微调T5模型?手把手教你弄懂!
    大家好,我是Bob!......
  • 真实案例:使用LLM大模型及BERT模型实现合同审查系统
    引言:合同审查作为法律实务中的关键环节,其准确性和效率直接影响到企业的法律风险管理。传统的人工审查方式存在耗时长、成本高、易出错等问题。随着人工智能技术的不断进步,特别是LLM和BERT模型的应用,合同审查的自动化和智能化成为可能。概述:合同审查管理系统是一个集成了LLM和B......
  • 【微调大模型参数详解】以chatGLM为例
    微调chatGLM3-6b-base时涉及的一些重要参数的详细解释batch_size:批量大小,默认为4,每个GPU的训练批量大小。增加该值可以提高训练速度,但可能需要更多的显存。lora_r:LoraR维度,默认为64,指定Lora训练中用于调节的R维度大小。该参数影响Lora模块的复杂度和模型的表现。......
  • 国内外AI大语言模型推荐分享 除了Chatgpt 你会选择哪个模型?
    当前AI技术飞速发展,Ai已经成为许多人日常工作和生活中不可或缺的工具,特别是以大语言模型为首的人工智能,它能够与我们进行自然语言对话,支持多种应用场景,如技术问答、代码生成、内容创作等,而且适用于各种群体和场景。现在国内外都有不少出色的大语言模型,这些模型在自然语言......
  • SciTech-BigDataAIML-LLM-Transformer Series-统计模型和大量数据 + MI移动互联+IoT万
    词汇MI(MobileInternet):移动互联网IoT(InternetofThings):万物互联网WE(WordEmbedding):词嵌入PE(PositionalEncoding):位置编码统计模型和大数据的保障和源头是"MI"和"IoT"。1真正"改革生产生活习惯"的是"国家政策"与"政府"。新经济的产生是以“改革生产生活......
  • SciTech-BigDataAIML-LLM-Transformer Series-Positional Encoding: 位置编码: 统计模
    词汇WE(WordEmbedding):词嵌入PE(PositionalEncoding):位置编码统计模型和大数据的本源是由"MI(移动互联网)"和"IoT(万物互联)"决定的1真正改驱“改革生产生活习惯”的是“国家政策”与“政府”。新经济的产生是以“改革生产生活习惯”为前提.生产生活的习惯改变:行政......