面试题目:欠拟合、过拟合及如何防止过拟合

对于深度学习或机器学习模型而言,我们不仅要求它对训练数据集有很好的拟合(训练误差),同时也希望它可以对未知数据集(测试集)有很好的拟合结果(泛化能力),所产生的测试误差被称为泛化误差。度量泛化能力的好坏,最直观的表现就是模型的过拟合(overfitting)和欠拟合(underfitting)。过拟合和欠拟合是用于描述模型在训练过程中的两种状态。一般来说,训练过程会是如下所示的一个曲线图在这里插入图片描述

一、什么是欠拟合?

欠拟合是指模型不能在训练集上获得足够低的误差。换句换说,就是模型复杂度低,模型在训练集上就表现很差,没法学习到数据背后的规律。

如何解决欠拟合?

欠拟合基本上都会发生在训练刚开始的时候,经过不断训练之后欠拟合应该不怎么考虑了。但是如果真的还是存在的话,可以通过增加网络复杂度或者在模型中增加特征,这些都是很好解决欠拟合的方法。

二、什么是过拟合?

过拟合是指训练误差和测试误差之间的差距太大。换句换说,就是模型复杂度高于实际问题,模型在训练集上表现很好,但在测试集上却表现很差。模型对训练集"死记硬背"(记住了不适用于测试集的训练集性质或特点),没有理解数据背后的规律,泛化能力差。
在这里插入图片描述
为什么会出现过拟合现象?

造成原因主要有以下几种:
1、训练数据集样本单一,样本不足。如果训练样本只有负样本,然后那生成的模型去预测正样本,这肯定预测不准。所以训练样本要尽可能的全面,覆盖所有的数据类型。
2、训练数据中噪声干扰过大。噪声指训练数据中的干扰数据。过多的干扰会导致记录了很多噪声特征,忽略了真实输入和输出之间的关系。
3、模型过于复杂。模型太复杂,已经能够“死记硬背”记下了训练数据的信息,但是遇到没有见过的数据的时候不能够变通,泛化能力太差。我们希望模型对不同的模型都有稳定的输出。模型太复杂是过拟合的重要因素。

三、如何防止过拟合?

要想解决过拟合问题,就要显著减少测试误差而不过度增加训练误差,从而提高模型的泛化能力。我们可以使用正则化(Regularization)方法。那什么是正则化呢?正则化是指修改学习算法,使其降低泛化误差而非训练误差。

常用的正则化方法根据具体的使用策略不同可分为:(1)直接提供正则化约束的参数正则化方法,如L1/L2正则化;(2)通过工程上的技巧来实现更低泛化误差的方法,如提前终止(Early stopping)和Dropout;(3)不直接提供约束的隐式正则化方法,如数据增强等。

3 1. 获取和使用更多的数据(数据集增强)——解决过拟合的根本性方法

让机器学习或深度学习模型泛化能力更好的办法就是使用更多的数据进行训练。但是,在实践中,我们拥有的数据量是有限的。解决这个问题的一种方法就是创建“假数据”并添加到训练集中——数据集增强。通过增加训练集的额外副本来增加训练集的大小,进而改进模型的泛化能力。

我们以图像数据集举例,能够做:旋转图像、缩放图像、随机裁剪、加入随机噪声、平移、镜像等方式来增加数据量。另外补充一句,在物体分类问题里,CNN在图像识别的过程中有强大的“不变性”规则,即待辨识的物体在图像中的形状、姿势、位置、图像整体明暗度都不会影响分类结果。我们就可以通过图像平移、翻转、缩放、切割等手段将数据库成倍扩充。

2. 采用合适的模型(控制模型的复杂度)

过于复杂的模型会带来过拟合问题。对于模型的设计,目前公认的一个深度学习规律"deeper is better"。国内外各种大牛通过实验和竞赛发现,对于CNN来说,层数越多效果越好,但是也更容易产生过拟合,并且计算所耗费的时间也越长。

根据奥卡姆剃刀法则:在同样能够解释已知观测现象的假设中,我们应该挑选“最简单”的那一个。对于模型的设计而言,我们应该选择简单、合适的模型解决复杂的问题。

3. 降低特征的数量

对于一些特征工程而言,可以降低特征的数量——删除冗余特征,人工选择保留哪些特征。这种方法也可以解决过拟合问题。

4. L1 / L2 正则化

(1) L1 正则化

在原始的损失函数后面加上一个L1正则化项,即全部权重www的绝对值的和,再乘以λ/n。则损失函数变为:

[公式]

对应的梯度(导数):
在这里插入图片描述

其中 [公式] 只是简单地取 [公式] 各个元素地正负号。

在这里插入图片描述

梯度下降时权重 [公式] 更新变为:

w=0w=0w=0时,|w|是不可导的。所以我们仅仅能依照原始的未经正则化的方法去更新w。

w>0w>0w>0时,sgn( www )>0, 则梯度下降时更新后的 www变小。

w<0w<0w<0 时,sgn( www )>0, 则梯度下降时更新后的 www 变大。换句换说,L1正则化使得权重www往0靠,使网络中的权重尽可能为0,也就相当于减小了网络复杂度,防止过拟合。

这也就是L1正则化会产生更稀疏(sparse)的解的原因。此处稀疏性指的是最优值中的一些参数为0。L1正则化的稀疏性质已经被广泛地应用于特征选择机制,从可用的特征子集中选择出有意义的特征。

(2) L2 正则化

L2正则化通常被称为权重衰减(weight decay),就是在原始的损失函数后面再加上一个L2正则化项,即全部权重www的平方和,再乘以λ/2n。则损失函数变为:

对应的梯度(导数):
在这里插入图片描述
在这里插入图片描述

能够发现L2正则化项对偏置 b 的更新没有影响,可是对于权重 [公式] 的更新有影响:
在这里插入图片描述

这里的[公式]都是大于0的, 所以[公式] 小于1。因此在梯度下降过程中,权重 www 将逐渐减小,趋向于0但不等于0。这也就是权重衰减(weight decay)的由来。

L2正则化起到使得权重参数www变小的效果,为什么能防止过拟合呢?因为更小的权重参数 www意味着模型的复杂度更低,对训练数据的拟合刚刚好,不会过分拟合训练数据,从而提高模型的泛化能力。

5. Dropout

Dropout是在训练网络时用的一种技巧(trike),相当于在隐藏单元增加了噪声。Dropout 指的是在训练过程中每次按一定的概率(比如50%)随机地“删除”一部分隐藏单元(神经元)。所谓的“删除”不是真正意义上的删除,其实就是将该部分神经元的激活函数设为0(激活函数的输出为0),让这些神经元不计算而已。

Dropout为什么有助于防止过拟合呢?

(a)在训练过程中会产生不同的训练模型,不同的训练模型也会产生不同的的计算结果。随着训练的不断进行,计算结果会在一个范围内波动,但是均值却不会有很大变化,因此可以把最终的训练结果看作是不同模型的平均输出。

(b)它消除或者减弱了神经元节点间的联合,降低了网络对单个神经元的依赖,从而增强了泛化能力。

6. Early stopping(提前终止)

对模型进行训练的过程即是对模型的参数进行学习更新的过程,这个参数学习的过程往往会用到一些迭代方法,如梯度下降(Gradient descent)。Early stopping是一种迭代次数截断的方法来防止过拟合的方法,即在模型对训练数据集迭代收敛之前停止迭代来防止过拟合。

为了获得性能良好的神经网络,训练过程中可能会经过很多次epoch(遍历整个数据集的次数,一次为一个epoch)。如果epoch数量太少,网络有可能发生欠拟合;如果epoch数量太多,则有可能发生过拟合。Early stopping旨在解决epoch数量需要手动设置的问题。具体做法:每个epoch(或每N个epoch)结束后,在验证集上获取测试结果,随着epoch的增加,如果在验证集上发现测试误差上升,则停止训练,将停止之后的权重作为网络的最终参数。

为什么能防止过拟合?当还未在神经网络运行太多迭代过程的时候,w参数接近于0,因为随机初始化w值的时候,它的值是较小的随机值。当你开始迭代过程,w的值会变得越来越大。到后面时,w的值已经变得十分大了。所以early stopping要做的就是在中间点停止迭代过程。我们将会得到一个中等大小的w参数,会得到与L2正则化相似的结果,选择了w参数较小的神经网络。

Early Stopping缺点:没有采取不同的方式来解决优化损失函数和过拟合这两个问题,而是用一种方法同时解决两个问题 ,结果就是要考虑的东西变得更复杂。之所以不能独立地处理,因为如果你停止了优化损失函数,你可能会发现损失函数的值不够小,同时你又不希望过拟合。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/535180.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LaTeX:equation, aligned 书写公式换行,顶部对齐

使用aligined 函数&#xff0c;其中aligned就是用来公式对齐的&#xff0c;在中间公式中&#xff0c;\ 表示换行&#xff0c; & 表示对齐。在公式中等号之前加&&#xff0c;等号介绍要换行的地方加\就可以了。 \begin{equation} \begin{aligned} L_{task} &\lamb…

Latex: 表格中 自动换行居中

1、在导言区添加宏包&#xff1a; \usepackage{makecell}2、环境&#xff1a;tabular 命令&#xff1a; \makecell[居中情况]{第1行内容 \\ 第2行内容 \\ 第3行内容 ...} \makecell [c]{ResNet101\\ (11.7M)}参数说明&#xff1a; [c]是水平居中&#xff0c;[l]水平左居中&am…

argparse:shell向Python中传参数

一般是 python train.py --bath_size 5利用argparse解析参数 import argparse parser argparse.ArgumentParser() parser.add_argument(integer, typeint, helpdisplay an integer) args parser.parse_args()参数类型 可选参数 import argparse parser argparse.Argumen…

FTP命令:下载,上传FTP服务器中的文件

步骤 1: 建立 FTP 连接 想要连接 FTP 服务器&#xff0c;在命令上中先输入ftp然后空格跟上 FTP 服务器的域名 domain.com 或者 IP 地址例如:1.ftp domain.com2.ftp 192.168.0.13.ftp userftpdomain.com注意: 本例中使用匿名服务器。替换下面例子中 IP 或域名为你的服务器地址。…

Tensorflow代码转pytorch代码 函数的转换

tensoflow函数和pytorch函数之间的转换 tensorflowpytrochtf.reshape(input, shape)input.view()tf.expand_dims(input, dim)input.unsqueeze(dim) / input.view()tf.squeeze(input, dim)torch.squeeze(dim)/ input.view()tf.gather(input1, input2)input1[input2]tf.tile(inp…

在服务器上远程使用tensorboard查看训练loss和准确率

本人使用的是vscode 很简单 from torch.utils.tensorboard import SummaryWriter writer SummaryWriter(./logs)writer.add_scalar(train_loss,loss.val(),iteration) # 名字&#xff0c;数据&#xff0c;迭代次数训练的过程中会产生一个./logs的文件夹&#xff0c;里面存放的…

python,pytorch:读取,保存,显示图片

文章目录一&#xff0c;Pytorch1. 直接保存Tensor2.Tensor 转CV2 保存二、python1. opencv2.matplotlib:3. PIL一&#xff0c;Pytorch 1. 直接保存Tensor #!/usr/bin/env python # _*_ coding:utf-8 _*_ import torch from torchvision import utils as vutilsdef save_image…

Python循环创建变量名

使用命名空间locals locals 中是当前程序段中的全部变量名是一个字典的形式 所以我们新增的话&#xff0c;直接和字典那样就行了 names locals() #获取当前程序段中的全体局部变量名 for i in np.arange(0,10):names[fname_{i}]i

pytorch:固定部分层参数,固定单个模型

文章目录固定部分层参数固定指定层的参数不同层设置不同的学习率固定部分层参数 class RESNET_attention(nn.Module):def __init__(self, model, pretrained):super(RESNET_attetnion, self).__init__()self.resnet model(pretrained) # 这个model被固定for p in self.parame…

图片拼接的几种方法

1. torch tensor 格式 from torchvision.utils import save_imageimg_train_list torch.cat([image_s,image_r,im_G[0],fake_A,mask_s[:, :, 0],mask_r[:, :, 0]])result_path self.save_path_dir/imageif not os.path.exists(result_path):os.makedirs(result_path)save_im…

Pytorch 各种模块:降低学习率,

1.训练过程中学习率衰减 if (self.e1) > (self.num_epochs - self.num_epochs_decay):g_lr - (self.g_lr / float(self.num_epochs_decay))d_lr - (self.d_lr / float(self.num_epochs_decay))self.update_lr(g_lr, d_lr)print(Decay learning rate to g_lr: {}, d_lr:{}..…

cudnn.deterministic = True 固定随机种子

随机数种子seed确定时&#xff0c;模型的训练结果将始终保持一致。 随机数种子seed确定时使用相同的网络结构&#xff0c;跑出来的效果完全不同&#xff0c;用的学习率&#xff0c;迭代次数&#xff0c;batch size 都是一样。 torch.backends.cudnn.deterministic是啥&#x…

torch.backends.cudnn.benchmark 加速训练

设置 torch.backends.cudnn.benchmarkTrue 将会让程序在开始时花费一点额外时间&#xff0c;为整个网络的每个卷积层搜索最适合它的卷积实现算法&#xff0c;进而实现网络的加速。适用场景是网络结构固定&#xff08;不是动态变化的&#xff09;&#xff0c;网络的输入形状&…

各种损失损失函数的使用场景和使用方法:KL散度

KL 散度的使用场景 KL散度( Kullback–Leibler divergence)&#xff0c;又称相对熵&#xff0c;是描述两个概率分布 P 和 Q 差异的一种方法 torch.nn.functional.kl_div(input, target, size_averageNone, reduceNone, reductionmean) torch.nn.KLDivLoss(input, target, si…

RNN,LSTM,GRU的理解

RNN x 为当前状态下数据的输入&#xff0c; h 表示接收到的上一个节点的输入。 y为当前节点状态下的输出&#xff0c;而h′h^\primeh′为传递到下一个节点的输出. LSTM #定义网络 lstm nn.LSTM(input_size20,hidden_size50,num_layers2) #输入变量 input_data Variable(tor…

常用的loss函数,以及在训练中的使用

文章目录KL 散度L2 loss做标准化处理CElossCTCLossAdaptiveAvgPool2dKL 散度 算KL散度的时候要注意前后顺序以及加log import torhch.nn as nn d_loss nn.KLDivLoss(reductionreduction_kd)(F.log_softmax(y / T, dim1),F.softmax(teacher_scores / T, dim1)) * T * T蒸馏lo…

Shell 在训练模型的时候自动保存训练文件和模型到指定文件夹

在进行深度学习训练的过程中&#xff0c;往往会跑很多实验&#xff0c;这就导致有的实验设置会忘记或者记混淆&#xff0c;我们最好把train test model 的代码都copy一遍到指定文件夹中&#xff0c;这样后面检查也方便。 用shell指令保存文件 #!/bin/sh GRUB_CMDLINE_LINUX&qu…

Pytorch:数据并行和模型并行,解决训练过程中内存分配不均衡的问题

文章目录数据并行单机多卡训练&#xff0c;即并行训练。并行训练又分为数据并行 (Data Parallelism) 和模型并行两种。 数据并行指的是&#xff0c;多张 GPU 使用相同的模型副本&#xff0c;但是使用不同的数据批进行训练。而模型并行指的是&#xff0c;多张GPU 分别训练模型的…

DataParallel 和 DistributedDataParallel 的区别和使用方法

1.DataParallel DataParallel更易于使用&#xff08;只需简单包装单GPU模型&#xff09;。 model nn.DataParallel(model)它使用一个进程来计算模型参数&#xff0c;然后在每个批处理期间将分发到每个GPU&#xff0c;然后每个GPU计算各自的梯度&#xff0c;然后汇总到GPU0中…

torch.cuda.is_available(),torch.cuda.device_count(),torch.cuda.get_device_name(0)

torch.cuda.is_available() cuda是否可用&#xff1b; torch.cuda.device_count() 返回gpu数量&#xff1b; torch.cuda.get_device_name(0) 返回gpu名字&#xff0c;设备索引默认从0开始&#xff1b; torch.cuda.current_device() 返回当前设备索引&#xff1b;