热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

训练集准确率很高,验证集准确率低问题

训练集在训练过程中,loss稳步下降,准确率上升,最后能达到97%验证集准确率没有升高,一直维持在50%左右(二分类问题,随机概率)测试集准确率57%在网上搜索可能打的原因:1.l

训练集在训练过程中,loss稳步下降,准确率上升,最后能达到97%
验证集准确率没有升高,一直维持在50%左右(二分类问题,随机概率)
测试集准确率57%

在网上搜索可能打的原因:
1.learning rate太小,陷入局部最优

2.训练集和测试集数据没有规律

3.数据噪声太大

4.数据量太小(总共1440个样本,80%为训练集)

5.训练集和测试集数据分布不同:如训练集正样本太少(如果训练集和测试集每次运行随机选择,则排除)

6.数据集存在问题,如标注有问题(如采用公开数据集,则排除)

7.学习率过大

8.模型参数量过多而数据量过少

9.过拟合,数据量太小但是模型的结构较为复杂
解决办法:降低模型的复杂度,增大L2正则项,在全连接层加入Dropout层;有了dropout,网络不会为任何一个特征加上很高的权重(因为那个特征的输入神经元有可能被随机删除),最终dropout产生了收缩权重平方范数的效果

10.输入到网络中的特征有问题,特征与label之间没有很明确的关联,或特征太少

11.数据没有归一化

12.修改学习率,使得每次梯度下降低于某个值或者停止下降时,降低学习率,来使得梯度进一步下降。(我使用该方法,使得问题得到解决)

【备注:
batch size过小,花费时间多,同时梯度震荡严重,不利于收敛;batch size过大,不同batch的梯度方向没有任何变化,容易陷入局部极小值。】

针对第12点,修改学习率的举例如下:(基于pytorch)

optimizer = torch.optim.SGD(model.parameters(), lr=0.1) # 优化器
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1) # 设定优优化器更新的时刻表
def train(...):
for i, data in enumerate(train_loader):
......
y_ = model(x)
loss = criterion(y_,y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
......
# 开始训练
for epoch in range(epochs):
scheduler.step() #在每轮epoch之前更新学习率
train(...)
veritf(...)

等间隔调整学习率 StepLR
torch.optim.lr_scheduler.StepLR(optimizer, step_size, gamma=0.1, last_epoch=-1)
每训练step_size个epoch,学习率调整为lr=lr*gamma.
参数:
optimizer: 神经网络训练中使用的优化器,如optimizer=torch.optim.SGD(…)
step_size(int): 学习率下降间隔数,单位是epoch,而不是iteration.
gamma(float): 学习率调整倍数,默认为0.1
last_epoch(int): 上一个epoch数,这个变量用来指示学习率是否需要调整。当last_epoch符合设定的间隔时,就会对学习率进行调整;当为-1时,学习率设置为初始值。
学习率变化如下图所示:

当然调整学习率的方式还有很多:
多间隔调整学习率 MultiStepLR
指数衰减调整学习率 ExponentialLR
余弦退火函数调整学习率:
根据指标调整学习率 ReduceLROnPlateau
自定义调整学习率 LambdaLR

网上都可以查到,这里就不一一列举了。

欢迎留言讨论~ ^ _ ^

# 前面省略了一部分代码,下面的代码仅供代码格式参考:
args = parser.parse_args()
device = 'cuda' if torch.cuda.is_available() else 'cpu'
best_acc = 0
start_epoch = 0
# Data
print('==> Preparing data..')
transform_train = transforms.Compose([
transforms.RandomCrop(32, padding=4),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
])
transform_test = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
])
dict_datasets={'CIFAR10':torchvision.datasets.CIFAR10, 'CIFAR100':torchvision.datasets.CIFAR100}
trainset = dict_datasets[args.datasets](
root='./data', train=True, download=True, transform=transform_train)
trainloader = torch.utils.data.DataLoader(
trainset, batch_size=args.batchsize, shuffle=True, num_workers=0)
testset = dict_datasets[args.datasets](
root='./data', train=False, download=True, transform=transform_test)
testloader = torch.utils.data.DataLoader(
testset, batch_size=args.batchsize_test, shuffle=False, num_workers=0)
global_x.plot_lr=[]
best_acc=0
# Model
print('==> Building model..')
net = dict_model[args.model]
net = net.to(device)
if device == 'cuda':
net = torch.nn.DataParallel(net)
cudnn.benchmark = True

criterion = nn.CrossEntropyLoss()
#####################################################
optimizer = optim.SGD(net.parameters(), lr=args.lr,
momentum=0.8, weight_decay=5e-4)
scheduler = lr_scheduler.Warmup_lineardecay(optimizer, T_max=args.epochs, improved=args.improved)
##################################################
# Training
train_Acc=np.array([])
train_Loss=np.array([])
def train(epoch):
global train_Acc
global train_Loss

print('\nEpoch: %d' % epoch)
net.train()
train_loss = 0
correct = 0
total = 0

for batch_idx, (inputs, targets) in enumerate(trainloader):
inputs, targets = inputs.to(device), targets.to(device)
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, targets)
loss.backward()
##################梯度更新
optimizer.step()
##################
train_loss += loss.item()
_, predicted = outputs.max(1)
total += targets.size(0)
correct += predicted.eq(targets).sum().item()
progress_bar(batch_idx, len(trainloader), 'Loss: %.3f | Acc: %.3f%% (%d/%d)'
% (train_loss/(batch_idx+1), 100.*correct/total, correct, total))

train_Acc=np.append(train_Acc,100.*correct/total)
train_Loss=np.append(train_Loss,train_loss/(batch_idx+1))
if not os.path.exists(args.model):
os.mkdir(args.model)
np.savetxt(args.model+'/result_of_train_acc.txt',train_Acc,fmt='%f')
np.savetxt(args.model+'/result_of_train_loss.txt',train_Loss,fmt='%f')
test_Acc=np.array([])
test_Loss=np.array([])
def test(epoch):
global test_Acc
global test_Loss
global best_acc
net.eval()
test_loss = 0
correct = 0
total = 0
with torch.no_grad():
DATA_predict=np.empty([0,10])
DATA_predict_index=np.empty([0,1])
for batch_idx, (inputs, targets) in enumerate(testloader):
inputs, targets = inputs.to(device), targets.to(device)
outputs = net(inputs)
loss = criterion(outputs, targets)
test_loss += loss.item()
_, predicted = outputs.max(1)
total += targets.size(0)
correct += predicted.eq(targets).sum().item()
DATA_predict=np.append(DATA_predict,outputs.cpu(),axis=0)
DATA_predict_index=np.append(DATA_predict_index,targets.view(-1,1).cpu(),axis=0)
progress_bar(batch_idx, len(testloader), 'Loss: %.3f | Acc: %.3f%% (%d/%d)'
% (test_loss/(batch_idx+1), 100.*correct/total, correct, total))
test_Acc=np.append(test_Acc,100.*correct/total)
global_x.reference_acc = correct/total
test_Loss=np.append(test_Loss,test_loss/(batch_idx+1))
np.savetxt(args.model+'/result_of_test_acc.txt',test_Acc,fmt='%f')
np.savetxt(args.model+'/result_of_test_loss.txt',test_Loss,fmt='%f')
# Save checkpoint.
acc = 100.*correct/total
if acc > best_acc:
np.savetxt(args.model+'_DATA_predict.txt',DATA_predict,fmt='%f')
np.savetxt(args.model+'_DATA_predict_index.txt',DATA_predict_index,fmt='%d')
print('Saving..')
state = {
'net': net.state_dict(),
'acc': acc,
'epoch': epoch,
}
if not os.path.isdir('checkpoint'):
os.mkdir('checkpoint')
torch.save(state, './checkpoint/ckpt.pth')
best_acc = acc
for epoch in range(start_epoch, start_epoch+args.epochs):
train(epoch)
test(epoch)
################学习率更新,每轮更新一次,有些学习率的更新是每次迭代更新一次,注意区分,如果是每次迭代更新一次,可以把这一行放在梯度更新的下一行
scheduler.step()
###################

对于此问题,进行的更新:
以下内容参考
版权声明:本文为CSDN博主「TinaO-O」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u013249853/article/details/89393982

0.学习率设置太高,一个epoch直接收敛,所以损失不会下降
比如学利率一开始设置为1,因为下降太快,那么很有可能在一个epoch旧完全收敛。所以看到的validation数值并不下降,第一个epoch就已经处于谷底了。所以如果使用的是系统默认的学习率,最好检查下默认值是什么。

1.最常见的原因:过拟合
过拟合值得单独开个章节。主要包括

1.数据量小,网络复杂
2.learning rate 比较高,又没有设置任何防止过拟合的机制
解决方法主要包括
1.简化模型,利用现有深度学习手段增加数据(翻转,平移,随机裁剪,imgaug)
2.利用 dropout层
3.利用正则化

2.没有把数据规格化
图片的话,img/255是肯定的

3.没有在分验证集之前打乱数据
因为validation_split操作不会为你shuffle数据,所以如果你的数据前一半标签全是1 ,后一半全是0,validation=0.5。恭喜你,你压根也分不对,你的validation准确率会一直为0.因为你拿所有的正样本训练,却想判断负样本。

4.数据和标签没有对上
有可能再读取自定义的数据库的时候出现问题,导致数据与标注不对应。比如第一张图片用第十张的标注

5.你的训练数据太少,validation数据太多,类别也太多
比如4000张训练,1000张validation,300类,这显然就是不合理的。
遇到这种情况,建议:

1.使用别的大的数据集预训练
2.使用DATA augment
3.可以考虑迁移学习

6.最好使用预训练的权重
大多数流行的backone比如resnet都有再imagenet数据集上与训练过,那么使用这种权重,比起随即重新训练,显然要可靠不少注意调整学习率。

7.网络结构有问题
可以通过使用现在流行的网络(resnet,unet等)替入你的代码,如果结果没有问题,你的结果有问题那么肯定就是你网络结构出问题了。那么可以通过逐层注释掉排查究竟哪里出了问题

7.1 网络最后一层没有使用正确的激活函数
比如多类的应该使用softmax

8.relu后面是softmax
有一些说法是relu由于对于很大的数值直接复制,所以会对softmax产生不好的影响,从而输出不好的结果。所以可以使用tanh代替relu。

9.batch normalization需要batch size至少16张
https://mp.csdn.net/postedit/89456400
由于做dense prediction图片通常比较大。所以一个batch一般都只有1-2张图片,不建议使用 BN。
因为BN一般是16张图片以上一起跑。所以吧,如果是BN,那么请用多GPU,16以上的batch size。s
另外keras TF1.x可能会出问题,https://github.com/keras-team/keras/pull/9965

10.可能设置了一些参数是不可训练的
在训练语句之前,检查以下你的trainable参数,是否设置了一些参数是不可训练的。这还可能导致你的输出只能是一个值,比如永远预测为标注0,因为你只有一点点的参数,而这并不是一个模型(比如只有100个参数是可以训练的,太简单了,无法模拟)。

11.附送一个调参论文
Bag of Tricks for Image Classification with Convolutional Neural Networks
https://arxiv.org/abs/1812.01187

来源:LS_learner



推荐阅读
  • 开源Keras Faster RCNN模型介绍及代码结构解析
    本文介绍了开源Keras Faster RCNN模型的环境需求和代码结构,包括FasterRCNN源码解析、RPN与classifier定义、data_generators.py文件的功能以及损失计算。同时提供了该模型的开源地址和安装所需的库。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 本文整理了315道Python基础题目及答案,帮助读者检验学习成果。文章介绍了学习Python的途径、Python与其他编程语言的对比、解释型和编译型编程语言的简述、Python解释器的种类和特点、位和字节的关系、以及至少5个PEP8规范。对于想要检验自己学习成果的读者,这些题目将是一个不错的选择。请注意,答案在视频中,本文不提供答案。 ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了logistic回归(线性和非线性)相关的知识,包括线性logistic回归的代码和数据集的分布情况。希望对你有一定的参考价值。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
  • Ihavethefollowingonhtml我在html上有以下内容<html><head><scriptsrc..3003_Tes ... [详细]
  • IjustinheritedsomewebpageswhichusesMooTools.IneverusedMooTools.NowIneedtoaddsomef ... [详细]
  • 本文介绍了绕过WAF的XSS检测机制的方法,包括确定payload结构、测试和混淆。同时提出了一种构建XSS payload的方法,该payload与安全机制使用的正则表达式不匹配。通过清理用户输入、转义输出、使用文档对象模型(DOM)接收器和源、实施适当的跨域资源共享(CORS)策略和其他安全策略,可以有效阻止XSS漏洞。但是,WAF或自定义过滤器仍然被广泛使用来增加安全性。本文的方法可以绕过这种安全机制,构建与正则表达式不匹配的XSS payload。 ... [详细]
  • 小程序wxs中的时间格式化以及格式化时间和date时间互转
    本文介绍了在小程序wxs中进行时间格式化操作的问题,并提供了解决方法。同时还介绍了格式化时间和date时间的互相转换的方法。 ... [详细]
  • Ihaveaworkfolderdirectory.我有一个工作文件夹目录。holderDir.glob(*)>holder[ProjectOne, ... [详细]
  • 简述在某个项目中需要分析PHP代码,分离出对应的函数调用(以及源代码对应的位置)。虽然这使用正则也可以实现,但无论从效率还是代码复杂度方面考虑ÿ ... [详细]
  • Python教学练习二Python1-12练习二一、判断季节用户输入月份,判断这个月是哪个季节?3,4,5月----春 ... [详细]
author-avatar
苏小丫123_877
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有