问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

【5】过拟合处理的一些技巧

发布网友 发布时间:2024-09-30 17:08

我来回答

1个回答

热心网友 时间:2024-10-19 00:10

1.过拟合与欠拟合

Underfitting欠拟合的特点:模型的复杂度<数据分布的复杂度1)训练集的准确率不好,loss会比较高2)测试集的准确率也不好,loss也会比较高

Overfitting过拟合的特点:模型的复杂度>数据分布的复杂度1)训练集的准确度比较高,但是测试集的准确度比较低2)过分的准确降低loss,导致效果不好

由于现在的网络层数都比较大,所以出现过拟合的情况比较多,欠拟合的情况相对会少一点

一般来说,如何防止过拟合的一些基本的操作:

1)提供更多的数据

2)降低模型的复杂度降低神经网络结构的层数或者正则化方法

3)Dropout去掉一部分的神经元

4)DataEnhancement数据增强

5)EarlyStopping对训练过程做一个提前的终结

2.交叉验证

train-val-test交叉验证结构的思路:由于datasets.MNIST函数可以将数据样本划分成数据集与测试集两类,但是这是不够的,可以引入第三类,也就是train-val-test交叉验证结构。可以将样本数量较多的训练集再度的划分为train样本集与val样本集,这样可以使用train样本集来训练神经网络,然后使用val样本集来测试来选择一个较好的参数值,最后test数据集是作为最后的样本得出最终的结果

参考代码

#导入需要的模块importtorchimporttorch.nnasnnimporttorch.nn.functionalasFimporttorch.optimasoptimimporttorchvisionfromtorchvisionimporttransforms,datasets#参数的初始化batch_size=200learning_rate=0.01epochs=10#训练集下载train_db=datasets.MNIST('datasets/mnist_data',train=True,download=True,transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.1307,),(0.3081,))]))#测试集下载test_db=datasets.MNIST('datasets/mnist_data',train=False,download=True,transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.1307,),(0.3081,))]))#将训练集再度分成两类,train数据集样本数为50k,val数据集的样本数为10ktrain_db,val_db=torch.utils.data.random_split(train_db,[50000,10000])#接下来进行导入数据train_loader=torch.utils.data.DataLoader(train_db,batch_size=batch_size,shuffle=True)test_loader=torch.utils.data.DataLoader(test_db,batch_size=batch_size,shuffle=True)val_loader=torch.utils.data.DataLoader(val_db,batch_size=batch_size,shuffle=True)#打印三种数据集的样本数量print('train:',len(train_db),'val:',len(val_db),'test:',len(test_db))#输出为:train:50000val:10000test:10000#定义神经网络结构classMLP(nn.Mole):def__init__(self):super(MLP,self).__init__()self.model=nn.Sequential(nn.Linear(784,200),nn.LeakyReLU(inplace=True),nn.Linear(200,200),nn.LeakyReLU(inplace=True),nn.Linear(200,10),nn.LeakyReLU(inplace=True),)defforward(self,x):x=self.model(x)returnx#使用GPU来加速计算device=torch.device('cuda:0')net=MLP().to(device)#设置容器optimizer=optim.SGD(net.parameters(),lr=learning_rate)criteon=nn.CrossEntropyLoss().to(device)#一次epoch是直接训练全部的样本forepochinrange(epochs):#对于train数据集,主要的功能是不断的改进神经网络结构forbatch_idx,(data,target)inenumerate(train_loader):data=data.view(-1,28*28)data,target=data.to(device),target.cuda()logits=net(data)loss=criteon(logits,target)optimizer.zero_grad()loss.backward()optimizer.step()ifbatch_idx%100==0:print('TrainEpoch:{}[{}/{}({:.0f}%)]\tLoss:{:.6f}'.format(epoch,batch_idx*len(data),len(train_loader.dataset),100.*batch_idx/len(train_loader),loss.item()))#然后使用val数据集来挑选一个精度最高的参数值来进行下一次的epoch训练,主要主要是监视时候出现过拟合的情况#根据val样本集输出的情况,进行人为的选择最低loss指的参数,来作为做好的参数,来给最后的test样本集来做验证test_loss=0correct=0fordata,targetinval_loader:data=data.view(-1,28*28)data,target=data.to(device),target.cuda()logits=net(data)test_loss+=criteon(logits,target).item()#data.shape,pred.shape输出为:(torch.Size([200,784]),torch.Size([200]))#也就是data为200张28*28的图片pred=logits.data.max(1)[1]#得出每一个数据的预测数字#输出为:#tensor([3,2,7,0,2,9,3,5,0,1,8,8,1,8,5,0,8,0,5,9,1,9,4,8,#1,0,4,3,7,7,2,2,8,7,1,2,9,9,1,0,2,3,5,4,8,8,2,1,#3,8,2,6,3,2,1,1,7,9,2,1,2,9,9,3,0,0,1,9,7,5,6,4,#5,3,8,3,1,6,0,1,6,1,1,2,6,6,5,3,4,9,9,5,8,3,1,5,#7,9,6,1,2,5,3,4,3,1,7,2,0,3,0,3,1,4,1,6,6,5,3,1,#1,6,2,7,2,8,4,4,0,8,2,9,0,1,6,7,3,1,6,1,0,5,4,9,#9,3,3,0,9,8,9,7,8,1,7,6,4,0,1,8,4,2,4,2,1,1,3,4,#4,8,8,7,4,8,2,1,7,6,0,9,9,6,1,7,9,4,7,5,8,7,3,4,#4,0,0,5,8,3,2,1],device='cuda:0')correct+=pred.eq(target.data).sum()test_loss/=len(val_loader.dataset)print('\nVALset:Averageloss:{:.4f},Accuracy:{}/{}({:.0f}%)\n'.format(test_loss,correct,len(val_loader.dataset),100.*correct/len(val_loader.dataset)))#测试集得出最后的结果,根据上述的输出人为的选择一个最好的参数,去避免神经网络训练次数过多而导致过拟合的情况#这部分代码与val数据集的样本是完全一模一样的test_loss=0correct=0fordata,targetintest_loader:data=data.view(-1,28*28)data,target=data.to(device),target.cuda()logits=net(data)test_loss+=criteon(logits,target).item()pred=logits.data.max(1)[1]correct+=pred.eq(target.data).sum()test_loss/=len(test_loader.dataset)#得出最后一个最终结果print('\nTestset:Averageloss:{:.4f},Accuracy:{}/{}({:.0f}%)\n'.format(test_loss,correct,len(test_loader.dataset),100.*correct/len(test_loader.dataset)))

结果输出:

TrainEpoch:0[0/50000(0%)]Loss:2.306638TrainEpoch:0[20000/50000(40%)]Loss:2.004949TrainEpoch:0[40000/50000(80%)]Loss:1.304654VALset:Averageloss:0.0048,Accuracy:7999/10000(80%)TrainEpoch:1[0/50000(0%)]Loss:0.950421TrainEpoch:1[20000/50000(40%)]Loss:0.750856TrainEpoch:1[40000/50000(80%)]Loss:0.486089VALset:Averageloss:0.0024,Accuracy:8725/10000(87%)TrainEpoch:2[0/50000(0%)]Loss:0.551328TrainEpoch:2[20000/50000(40%)]Loss:0.393225TrainEpoch:2[40000/50000(80%)]Loss:0.364113VALset:Averageloss:0.0019,Accuracy:8911/10000(89%)TrainEpoch:3[0/50000(0%)]Loss:0.349589TrainEpoch:3[20000/50000(40%)]Loss:0.392292TrainEpoch:3[40000/50000(80%)]Loss:0.436958VALset:Averageloss:0.0017,Accuracy:9017/10000(90%)TrainEpoch:4[0/50000(0%)]Loss:0.258544TrainEpoch:4[20000/50000(40%)]Loss:0.338164TrainEpoch:4[40000/50000(80%)]Loss:0.359373VALset:Averageloss:0.0016,Accuracy:9062/10000(91%)TrainEpoch:5[0/50000(0%)]Loss:0.273114TrainEpoch:5[20000/50000(40%)]Loss:0.253162TrainEpoch:5[40000/50000(80%)]Loss:0.311780VALset:Averageloss:0.0015,Accuracy:9127/10000(91%)TrainEpoch:6[0/50000(0%)]Loss:0.250342TrainEpoch:6[20000/50000(40%)]Loss:0.315225TrainEpoch:6[40000/50000(80%)]Loss:0.349633VALset:Averageloss:0.0014,Accuracy:9168/10000(92%)TrainEpoch:7[0/50000(0%)]Loss:0.279099TrainEpoch:7[20000/50000(40%)]Loss:0.223900TrainEpoch:7[40000/50000(80%)]Loss:0.316459VALset:Averageloss:0.0014,Accuracy:9201/10000(92%)TrainEpoch:8[0/50000(0%)]Loss:0.349246TrainEpoch:8[20000/50000(40%)]Loss:0.241840TrainEpoch:8[40000/50000(80%)]Loss:0.193532VALset:Averageloss:0.0013,Accuracy:9231/10000(92%)TrainEpoch:9[0/50000(0%)]Loss:0.238849TrainEpoch:9[20000/50000(40%)]Loss:0.193404TrainEpoch:9[40000/50000(80%)]Loss:0.204639VALset:Averageloss:0.0013,Accuracy:9251/10000(93%)Testset:Averageloss:0.0012,Accuracy:9305/10000(93%)

由于设置的epoch过小,神经网络没有完全训练好,所以目前loss还是不断地在降低,还没有出现过拟合的情况,所以目前还不需要人为的挑选参数,来给最后的test样本集来进行训练。

3.regularization正则化

问题:正则化的操作是为了使得参数分布减小,从而避免过拟合的情况,但是为什么参数范数接近于0的时候,其模型的复杂度会减少?

答案:因为将一个高维函数的高维部分的参数下降为接近于0,所以正则化在另一方面也称为WeightDecay

正则化分为两类:划分的依据是范数的不同1)L1-regularizationimage

2)L2-regularization(较常用)

对于L2-regularization来说,PyTorch有直接API接口可以直接使用,比较的方便,而L1-regularization需要人为进行添加。

#L2-regularization的使用参考device=torch.device('cuda:0')net=MLP().to(device)#其实就是添加了一个参数weight_decay=0.01optimizer=optim.SGD(net.parameters(),lr=learning_rate,weight_decay=0.01)criteon=nn.CrossEntropyLoss().to(device)#weight_decay=0.01的含义:相当于设置了L2-regularization公式中的λ为0.01#由于net.parameters()已经得到了神经网络的全部参数,w’=w-▽w,然后使得参数的二范数|w|——>0

需要注意的是,正则化的操作是为了避免网络结果过于的复杂所以需要约束其参数不能过大,也就是避免过拟合的情况,如果网络并没有出现过拟合的情况而使用正则化操作会使得训练的效果差很多

#L1-regularization的使用参考regulatization_loss=0#遍历参数计算出参数的1范数,根据公式也就是模的相加forparaminmodel.parameters():regulatization_loss+=torch.sum(torch.abs(param))#对参数取绝对值求和classify_loss=criteon(logits,target)#计算出结果的交叉熵#交叉熵+参数的1范数损失=总的loss,现在降低这个loss就可以改善网络#根据上述的公式,0.01就是L1-regularization公式中的λ#以下这行代码就是模仿公式的结果loss=classify_loss+0.01*regulatization_loss#基本的三部曲,向后传播更新参数optimizer.zero_grad()loss.backward()optimizer.step()4.动量与学习量的衰减1)动量

其中的zk可以理解为上一次梯度更新的方向,增加的动量的机制相当于不仅仅考虑了当前梯度的方向,还考虑了之前的梯度的方向,也就是综合的结合了两次梯度的变化信息来权衡。

Nomomentum

Withappr.momentum参考代码:

#方法1#同样的,pytorch中的SGD优化器也提供的一个接口,使用起来还是比较的方便optimizer=torch.optim.SGD(model.parameters().args.lr,momentum=args.momentum,#仅仅是添加了了着一个参数weight_decay=args.weight_decay)方法20.8表示新一轮产生的数据与前一轮产生的数据之间的使用比例,也就是动量操作

nn.BatchNorm2d(128,0.8),

所以在构造神经网络的时候可以使用BN层来间接使用动量操作参考解释:https://blog.csdn.net/t20134297/article/details/104960101/#####2)Learingratedecay![在这里插入图片描述](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/577deba18a814fa787451689630eea42~tplv-k3u1fbpfcp-zoom-1.image)当梯度的长时间保持不变的时候,也有可以是learningrate的问题,有时我们调整了一下学习率就可能让loss跳转,所以可以动态的设置learningrate,训练过程一直保持同样的learningrate有时进行的会是非常的缓慢的![在这里插入图片描述](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/41a2975b110942f8b60a8eb754ff7d8b~tplv-k3u1fbpfcp-zoom-1.image)![在这里插入图片描述](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e4ea417b6f5a4463a4d7027961331849~tplv-k3u1fbpfcp-zoom-1.image)参考代码:```python#方法1#在SGD容器中设置了正则化操作与动量操作optimizer=torch.optim.SGD(model.parameters().args.lr,momentum=args.momentum,weight_decay=args.weight_decay)#ReceLOonPlateau当loss已经平坦了很长时间之后,可以通过减小learningrate来进一步减小loss#接口函数为:classReceLROnPlateau(builtins.object)#|ReceLROnPlateau(optimizer,mode='min',factor=0.1,patience=10,#threshold=0.0001,threshold_mode='rel',cooldown=0,#min_lr=0,eps=1e-08,verbose=False)scheler=ReceLOonPlateau(optimizer,'min')#mode='min':表示模式是减小lr#patience=10:表示如果10个epoch都没有减小,则降低learingrate#factor=0.1:表示降低learingrate的倍数,lr=factor*lr##训练过程forepochinxrange(args.start_epoch,args.epochs):train(train_loader,model,criterion,optimizer,epoch)result_avg,loss_val=validate(val_loader,model,criterion,epoch)#每调用一次就监听一次loss,若平淡10次就会做出改变scheler.step(loss_val)#方法2:#此方法不需要监听,而是没经过一定数量的训练次数就直接降低learningrate#Assumingoptimizeruseslr=0.05forallgroups#lr=0.05ifepoch<30#lr=0.005if30<=epoch<60#lr=0.0005if60<=epoch<90#......scheler=StepLR(optimizer,step_size=30,gamma=0.1)forepochinrange(100):scheler.step()train(...)validate(...)5.EarlyStopping

思想很简单,就是使用val数据要进行验证,如果其准确度已经开始下降时,可以提前的终止训练,而使用当前认为最后的一组参数,其实这个思想前面的推文也有涉及,其简单的步骤归结为:

1)Validationsettoselectparameters:val数据集验证来挑选参数

2)Monitorvalidationperforamce:人工监视来查看性能

3)Stopatthehighestvalperf:在最高的准确度时停止实验

6.Dropout

Dropout的思想是去除掉一部分是神经元,也就是通过简化神经网络结构来避免过拟合的情况

Learninglesstolearnbetter

Eachconnectionhasp=(0,1)tolose

其与正则化的思想是有部分类似的,但是正则化的思想是使用2范数迫使参数的复杂度降低|w|->0,既使得参数的总范数接近于0而Dropout是想不需要使用全部的参数,可以简化一部分也就是断了部分参数之间的输入输出练习∑w->0,既使得有效的参数越小越好Dropout可以是的loss函数变化的比较平和,因为其使得有效的参数量减少了,避免了网络结构学习了噪声对最后的结果造成了干扰

#Dropout的使用方法如下:net_dropped=torch.nn.Sequential(torch.nn.Linear(784,200),#层(784,200)与层(200,200)之间的连线有一定几率断掉torch.nn
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
齿瓣延胡索选方 延胡索粉是与开水服用还是与中药服用 延胡索细粉一次吃多少 青少年为什么会得抑郁症 为什么越来越多的青少年抑郁了? 游戏账号重新注册了一个,以前的老号为什么就没有了? 老爸做60大寿,要用手机发信息接朋友呷酒怎么说 老爸做60大寿,要用手机发信息接朋友呷酒怎么写 老爸60大寿请朋友来呷酒用短信通知发些什么 雷克萨斯es200和300的区别 雷克萨斯es200和300的区别哪个好 机器学习,咱先从过拟合与欠拟合讲起 奈芬尼多怎么打62丽莎72阿克希亚52鲁斯王 塔克林怎么打?还有奈芬尼多 赛尔号青龙的守护神怎么打 怎样关掉腾讯视频会员自动续费 手机刷机后不知道怎么了UC浏览器老是跳这个网页 鲍鱼干有哪些创意吃法值得尝试? QQ等级不够16级不花Q币能建群吗?怎么建啊??? 吞食天地2零陵吕布怎么打 吞天地隐品2哪些地方可以发现方天画戟? 吞食天地3吕布属性技能图鉴介绍_吞食天地3吕布属性技能图鉴是什么_百 ... ...芍药的意义A.益阴和营B.敛阴舒筋C.缓急止痛 1993-145.升麻葛根汤中升麻的配伍意义是 ...汤、当归补血汤、玉屏风散、补中益气汤、补阳还五汤的配伍意义... ...补血汤、玉屏风散、当归六黄汤中的配伍意义 线切割加工工作原理是怎样的? 6年级作文 假如我能 怎么样写一两件玉用自己的特异功能所做的事情 童话作文假如我有一枚渐子怎么写? ...是写假如我有特异功能 可以是复制的 只要那作文写的不错都可以_百度... 怎么查看微信转账给别人的账单? 苹果笔记本登陆QQ邮箱 【论文】ICCV美文:从过拟合到欠拟合? 昨天晚上做梦 先是梦见自己被人追杀 然后又梦见水母 (瀑布汗~) 苹果主屏幕4K 通过墨镜是4K还是两K 索尼z3+屏幕是两k的吗 荣耀V9怎么样?值得购买吗? 纯音乐,请推荐几首很有气势的,很激昂的音乐或钢琴曲等,不要歌. 出埃... 求一首小提琴纯音乐的名字,以前在多米听到的,不是很安静轻柔的,比较激 ... 求一首激昂与低落快速且多次穿插的纯音乐。给人神秘和优雅感觉。 不要... 请问哪位师傅可以告知长虹21K21电视机进入总线的方法 CPU是0406 5M18... ...的电视左上角出现了 FACTORY.摇控器不好使了,怎么弄,请高人指教... 你认为借钱不还的人是否值得深交? 一个借钱不还的人是不是还值得信任和交往? 穿霏比体雕衣效果怎么样? 大家知道霏比体雕好不好呀?朋友介绍说这个品牌不错 梦见婆子妈住的屋里腾的整整齐齐啥意思? 梦见自己的老公和婆子妈死了是什么意思 东营最好小区有哪些 东营万吉家园是油田小区吗 5g手机功能有什么