免费 网站建设,域名注册过程,长沙市网站设计公司,深圳龙华区发达吗论文中一般都是用在验证集上效果最好的模型去预测测试集#xff0c;多次预测的结果取平均计算准确率或者mAP值#xff0c;而不是单纯的取一次验证集最好的结果作为论文的结果。如果你在写论文的过程中#xff0c;把测试集当做验证集去验证的话#xff0c;这其实是作假的多次预测的结果取平均计算准确率或者mAP值而不是单纯的取一次验证集最好的结果作为论文的结果。如果你在写论文的过程中把测试集当做验证集去验证的话这其实是作假的建议不要这样一旦有人举报或者复现出来你的结果和你论文中的结果相差很大的话是会受到很大处分的。
我之前曾遇到过这种情况我在图像分类的过程中曾经用过CutMix增强方式CutMix其实就是将两张图片放在一起如下图所示这种结果会造成验证集上准确率很大的波动可能一会儿变成99%一会儿变成88%那我总不能拿99%作为我论文中的结果啊所以还是要以最终的测试集的准确率为主因为这个才是我们需要关注的。
如果只是单纯的取提高准确率的话可以看看文中下面的一些方式这些方式的提升一定会比单纯取最好的模型的效果要好的。
首先我们需要理解一下概念什么是训练集什么是验证集什么是测试集?大家很容易将“验证集”与“测试集”“交叉验证”混淆。
首先我们来了解一下基本的概念哈然后在分析如何解决分类问题提高模型的准确率和泛化能力。
训练集、验证集、测试集
训练集train set —— 用于模型拟合的数据样本。 验证集development set—— 是模型训练过程中单独留出的样本集它可以用于调整模型的超参数(包括EarlyStopping的epoch)和用于对模型的能力进行初步评估。 测试集 —— 用来评估模最终模型的泛化能力也就是计算论文里最后各个评价指标的值。但不能作为调参、选择特征等算法相关的选择的依据。
一个形象的比喻 训练集学生的课本学生 根据课本里的内容来掌握知识。 验证集作业通过作业可以知道 不同学生学习情况、进步的速度快慢。 测试集考试考的题是平常都没有见过考察学生举一反三的能力。
为什么验证数据集和测试数据集两者都需要
因为验证数据集Validation Set)用来调整模型参数从而选择最优模型模型本身已经同时知道了输入和输出所以从验证数据集上得出的误差Error)会有偏差Bias)。 但是我们只用测试数据集(Test Set) 去评估模型的表现并不会去调整优化模型。 传统上一般三者切分的比例是622验证集并不是必须的即验证集可有可无(可以选择不用验证集调整超参数)。 所以很多人口中的测试集应该是验证集的意思测试集不能作为调参、选择特征等算法相关的选择的依据。
K-折交叉验证K-fold Cross Validation记为K-CV
就按照作者说的10折交叉来说算法步骤是图如1
将数据集分成十份轮流将其中9份作为训练数据1份作为测试数据进行试验。每次试验都会得出相应的正确率。10次的结果的正确率的平均值作为对算法精度的估计一般还需要进行多次10折交叉验证例如10次10折交叉验证再求其均值作为对算法准确性的估计。 在数据缺乏的情况下使用如果设原始数据有N个样本那么LOO-CV就是N-CV即每个样本单独作为验证集其余的N-1个样本作为训练集故LOO-CV会得到N个模型用这N个模型最终的验证集的分类准确率的平均数作为此下LOO-CV分类器的性能指标。 优点1每一回合中几乎所有的样本皆用于训练模型因此最接近原始样本的分布这样评估所得的结果比较可靠。2实验过程中没有随机因素会影响实验数据确保实验过程是可以被复制的。 缺点计算成本高需要建立的模型数量与原始数据样本数量相同。当数据集较大时几乎不能使用。
关于EarlyStopping保存最优的模型
Pytroch保存最优的训练模型 min_loss 100000#随便设置一个比较大的数for epoch in range(epochs):train()val_loss val()if val_loss min_loss:min_loss val_lossprint(save model)torch.save(net.state_dict(),model.pth)图像分类
当我们拿到数据集的第一步就是对数据进行分析
各个种类的样本是否平衡如果数据不平衡的话对模型准确性的影响是非常大的。举个栗子如果有100个样本其中99个是正样本1个是负样本。那么就算我们把所有的样本都预测成正样本准确率也有99%显然这是不对的因为这个模型只能识别正样本了泛化能力非常差。这个时候可以考虑改动损失函数增加难样本负样本的权重减少简单样本正样本的权重。数据集中是否含有大量噪声。数据量是否充足等等.
接下来我们讲解一下图像分类中的一些trick 1.数据清洗 借助弱监督方式引入外部数据集中的高质量数据——解决了自行扩展数据集带来的测试偏移。步骤如下
使用训练数据建立模型预测爬取的数据的标签对外部数据进行伪标签标注。结合样本分布和混淆矩阵的结果设置了多级阈值选择可信度高的数据组合成新的数据集重复1,2,3。
2.数据增强 ①几何变换——只进行水平翻转和平移0.05
transforms.RandomAffine(degrees0, translate(0.05, 0.05)),
transforms.RandomHorizontalFlip()②CutMix
3.数据不均衡 在数据层面和算法层面同时测试选取—— 上采样和class_wight相结合 ①上采样——通过混淆矩阵和验证集的随机化设置提取模型预测错误的数据然后按照一定的权重进行数据复制扩充为了减少上采样可能带来的过拟合问题我们对扩充的数据进行了区域裁剪使数据更倾向于需要关注的部分。 ②class_weight——将不同的类别映射为不同的权值该参数用来在训练过程中调整损失函数只能用于训练。该参数在处理非平衡的训练数据某些类的训练样本数很少时可以使得损失函数对样本数不足的数据更加关注。
4.数据标签平滑 目的减小过拟合问题 平滑过后的样本交叉熵损失就不仅考虑到了训练样本中正确的标签位置的损失也稍微考虑到其他错误标签位置的损失导致最后的损失增大导致模型的学习能力提高即要下降到原来的损失就得学习的更好也就是迫使模型往增大正确分类概率并且同时减小错误分类概率的方向前进。
#!/usr/bin/python
# -*- encoding: utf-8 -*-import torch
import torch.nn as nnclass LabelSmoothSoftmaxCE(nn.Module):def __init__(self,lb_pos0.9,lb_neg0.005,reductionmean,lb_ignore255,):super(LabelSmoothSoftmaxCE, self).__init__()self.lb_pos lb_posself.lb_neg lb_negself.reduction reductionself.lb_ignore lb_ignoreself.log_softmax nn.LogSoftmax(1)def forward(self, logits, label):logs self.log_softmax(logits)ignore label.data.cpu() self.lb_ignoren_valid (ignore 0).sum()label label.clone()label[ignore] 0lb_one_hot logits.data.clone().zero_().scatter_(1, label.unsqueeze(1), 1)label self.lb_pos * lb_one_hot self.lb_neg * (1-lb_one_hot)ignore ignore.nonzero()_, M ignore.size()a, *b ignore.chunk(M, dim1)label[[a, torch.arange(label.size(1)), *b]] 0if self.reduction mean:loss -torch.sum(torch.sum(logs*label, dim1)) / n_validelif self.reduction none:loss -torch.sum(logs*label, dim1)return lossif __name__ __main__:torch.manual_seed(15)criteria LabelSmoothSoftmaxCE(lb_pos0.9, lb_neg5e-3)net1 nn.Sequential(nn.Conv2d(3, 3, kernel_size3, stride2, padding1),)net1.cuda()net1.train()net2 nn.Sequential(nn.Conv2d(3, 3, kernel_size3, stride2, padding1),)net2.cuda()net2.train()with torch.no_grad():inten torch.randn(2, 3, 5, 5).cuda()lbs torch.randint(0, 3, [2, 5, 5]).cuda()lbs[1, 3, 4] 255lbs[1, 2, 3] 255print(lbs)import torch.nn.functional as Flogits1 net1(inten)logits1 F.interpolate(logits1, inten.size()[2:], modebilinear)logits2 net2(inten)logits2 F.interpolate(logits2, inten.size()[2:], modebilinear)# loss1 criteria1(logits1, lbs)loss criteria(logits1, lbs)# print(loss.detach().cpu())loss.backward()5.双损失函数 categorical_crossentropy 和 Label Smoothing Regularization 在对原始标签进行平滑的过程中可能存在某些数据对标签变化特别敏感导致损失函数的异常增大使模型变得不稳定为了增加模型的稳定性所以使用双损失函数——categorical_crossentropy 和 Label Smoothing Regularization即保证了模型的泛化能力又保证了数据不会对标签过于敏感增加了模型的稳定性。
criterion L.JointLoss(firstnn.crossentropyloss(), secondLabelSmoothSoftmaxCE(),first_weight0.5, second_weight0.5)6.优化器 RAdam LookAhead兼具Adam和SGD两者的优化器RAdam收敛速度快鲁棒性好LookAhead对SGD进行改进在各种深度学习任务上实现了更快的收敛 。 将RAdam和LookAhead结合在了一起形成名为Ranger的新优化器。在ImageNet上进行了测试在128px20epoch的测试中Ranger的训练精度达到了93%比目前FastAI排行榜榜首提高了1%。
7.选择的模型
ResNeXt101系列EfficientNet系列。 resnext101_32x16d_wsl resnext101_32x8d_wsl efficientnet-b4 efficientnet-b5
8.注意力机制
在模型中加入SECBAM注意力机制——提升网络模型的特征提取能力。
channel attention的过程。比SE多了一个 global max pooling池化本身是提取高层次特征不同的池化意味着提取的高层次特征更加丰富。其第2个池化之后的处理过程和SE一样都是先降维再升维不同的是将2个池化后相加再sigmod和原 feature map。
class ChannelAttention(nn.Module):def __init__(self, in_planes, ratio16):super(ChannelAttention, self).__init__()self.avg_pool nn.AdaptiveAvgPool2d(1)self.max_pool nn.AdaptiveMaxPool2d(1)self.fc1 nn.Conv2d(in_planes, in_planes // 16, 1, biasFalse)self.relu1 nn.ReLU()self.fc2 nn.Conv2d(in_planes // 16, in_planes, 1, biasFalse)self.sigmoid nn.Sigmoid()def forward(self, x):avg_out self.fc2(self.relu1(self.fc1(self.avg_pool(x))))max_out self.fc2(self.relu1(self.fc1(self.max_pool(x))))out avg_out max_outreturn self.sigmoid(out)② spatial attention 的过程。将做完 channel attention 的feature map 作为输入之后作2个大小为列通道的维度池化每一次池化得到的 feature map 大小就为 h * w * 1 再将两次池化的 feature map 作基于通道的连接变成了大小为 h * w * 2 的 feature map 再对这个feature map 进行核大小为 7*7 卷积核个数为1的卷积操作通道压缩再sigmod最后就是熟悉的矩阵全乘。
class SpatialAttention(nn.Module):def __init__(self, kernel_size7):super(SpatialAttention, self).__init__()assert kernel_size in (3, 7), kernel size must be 3 or 7padding 3 if kernel_size 7 else 1self.conv1 nn.Conv2d(2, 1, kernel_size, paddingpadding, biasFalse)self.sigmoid nn.Sigmoid()def forward(self, x):avg_out torch.mean(x, dim1, keepdimTrue)max_out, _ torch.max(x, dim1, keepdimTrue)x torch.cat([avg_out, max_out], dim1)x self.conv1(x)return self.sigmoid(x)9.SVM替换softmax层 抽取出模型的最后一层将其接入SVM用训练数据动态训练SVM分类器再使用训练好的SVM分类器进行预测。 深度学习模型有支持向量机无法比拟的非线性函数逼近能力能够很好地提取并表达数据的特征深度学习模型的本质是特征学习器。然而深度模型往往在独立处理分类、回归等问题上难以取得理想的效果。对于 SVM 来说可以利用核函数的思想将非线性样本映射到高维空间使其线性可分再通过使数据集之间的分类间隔最大化来寻找最优分割超平面在分类问题上表现出许多特有优势。但实质上SVM 只含有一个隐层数据表征能力并不理想。因此将深度学习方法与 SVM 相结合构造用于分类的深层模型。利用深度学习的无监督方式分层提取样本高级特征然后将这些高级特征输入 SVM 模型进行分类从而达到最优分类精度。 10.模型融合 多模型融合的策略StackingVotingClassifier—— 提升分类准确率Stacking方法 Stacking 先从初始数据集训练出初级学习器然后”生成”一个新数据集用于训练次级学习器。在这个新数据集中初级学习器的输出被当作样例输入特征而初始样本的标记仍被当作样例标记。stacking使用交叉验证的方式初始训练集 D 被随机划分为 k 个大小相似的集合 D1 D2 … Dk每次用k-1 个部分训练 T 个模型对另个一个部分产生 T 个预测值作为特征遍历每一折后也就得到了新的特征集合标记还是源数据的标记用新的特征集合训练一个集合模型。
11.TTA测试时数据增强保证数据增强的几何变换和tta一致 可将准确率提高若干个百分点它就是测试时增强test time augmentation, TTA。这里会为原始图像造出多个不同版本包括不同区域裁剪和更改缩放程度等并将它们输入到模型中然后对多个版本进行计算得到平均输出作为图像的最终输出分数。
tta_model tta.TTAWrapper(model,tta.fliplr_image2label)作者初识CV 链接https://www.zhihu.com/question/408153243/answer/1490901503 来源知乎 著作权归作者所有。商业转载请联系作者获得授权非商业转载请注明出处。