一、数据处理
拿到数据之后,不应该直接进行模型的训练,首先进行如下几步:
- 数据清洗
这时候一定要查看数据和标签,对于比赛来讲,拿到数据之后很有可能数据本身就是有问题的,比的不仅是对模型的训练,更是对数据的处理,所以第一步是剔除有问题的数据和标签,所以也叫做数据清洗 - 数据增强
对于深度学习来讲,数据量的大小决定了模型的学习能力,一般而言,数据量越大,模型学习的越好;所以,拿到有限的数据后,可以先做数据增强,扩充数据量 - 超参实验
这里的为什么会有超参实验?主要是因为数据中存在正负样本/难易样本
关于这几种样本(对于分类):
- 正样本:我们想要正确分类出的类别所对应的样本,例如,我们需要对一张图片分类,确定是否属于猫,那么在训练的时候,猫的图片就是正样本。
- 负样本:根据上面的例子,不是猫的其他所有的图片都是负样本
- 难分正样本(hard positives):错分成负样本的正样本,也可以是训练过程中损失最高的正样本
- 难分负样本(hard negatives):错分成正样本的负样本,也可以是训练过程中损失最高的负样本
- 易分正样本(easy positive):容易正确分类的正样本,该类的概率最高。也可以是训练过程中损失最低的正样本
- 易分负样本(easy negatives):容易正确分类的负样本,该类的概率最高。也可以是训练过程中损失最低的负样本。
这里补充一下OHEM,很多比赛或者文章提到了,可以借鉴;其次是训练方法,首先可以进行实验找到不同的难易样本的比例,在此基础上进行训练策略的调整,例如找到loss特别低的样本,进行标记,或者在训练一段时间后再加入困难样本,进行针对性训练(这里未实际操作)。
(对于语义分割):
这里挖个坑,之后填
- 训练时增强
主要有transform一系列的crop,注意这里的一些crop会产生5张或者10张图片,本来[b,c,h,w]
变成了[b,k,c,h,w]
这里k为crop之后图片的张树,有5或者10,需要进行reshape[-1,c,h,w]
,实际上相当于将裁剪出来的图片都堆在了batch上面 - 重要!
因为之前数据增强做了很多,也看到了很大的提升,但是依旧卡在了一个瓶颈期,为探究其原因,上网查看了一些资料,发现了这篇知乎的文章,打算试一下! - 脏数据?
数据集存在问题
二、训练过程
- 图片读取处理保存
一些个人理解:
- PIL库是python的原生库,兼容性比较强,需要安装对应的包 pip install pillow
但是要记住PIL读取出来是image格式,需要转化numpy;支持单通道及多通道Uint8 TIFF图像读取,读取单通道Uint16 TIFF图像转为Uint8处理,直接读取Uint16 TIFF多通道图像出错 - matplotlib本身只能读取PNG,所以会有局限性
- opencv读取出来直接是numpy,但是通道和shape不一样,这里不需要在意,因为在
ToTensor()
时,pytorch会将其通道纠正,所以其实也很方便,最主要是其功能较多,比较权威
- pytorch的dataset
(1)为什么dataset返回的数据形状需要保持一致?
因为pytorch的dataloader默认的collate_fn会使用torch.stack合并多张图片成为batch,形状不同的tensor不能stack
(2)如果非要加载不同形状的样本怎么办?
要么另外写一个collate_fn,进行单独处理;要么在dataset类中对图片做padding,使得图片的size一样,可以直接stack - transform.normalization()
公式随处可见,此处不赘述。
作用:就是可以使(0, 1)变为(-1, 1)
原因:模型初始化时bias=0,但是实际的bias可能会比较大,这样的初始化就会导致神经网络收敛比较慢,经过Normalize后,可以加快模型的收敛速度。实验结果证明了,在多次周期迭代之后,我们的网络在使用归一化数据时有更高的准确性。有时被称为网络的快速收敛。
需要注意的是,并不总是归一化的数据更好。一个好的经验法则是在有疑问的时候,两种方式都要尝试。
目前很多网络都在用batch normalization
,批量归一化或批量规范化就是在网络的各层输出激活上,在网络的各层里面进行的这个同样的过程,具有很多优点,所以就不加transform.normalization()了,并且如果数据量较小,训练集和测试集的normalization的指标差距较大,可能效果不是很好。
挖坑:
SyncBatchNorm和Normalization的差别
- 损失函数
这里需要注意:
(1)BCE loss需要将标签进行one hot,比较麻烦,但是CE loss不需要
(2)CE loss 中predict的dtype应当为float并且要softmax,而gt的dtype应当为long,否则会出错
那么关键问题是,网络输出[b,num_class,h,w]
,num_class为对应类别(几分类就是几),gt为单通道的图片,怎样处理可以使其可以进行loss的计算?
例如:语义分割的图片输入是224×224×3经过神经网络之后输出是224×224×21而label值是224×224×1那么这两个值怎么转换才能构建损失函数呢?
最后说一下语义分割的几个loss,最近也没少看,但是实验结果并没有告诉我这几个的优劣性:
训练更倾向于挖掘前景区域,正负样本不平衡的情况就是前景占比较小。而ce loss会公平处理正负样本,当出现正样本占比较小时,就会被更多的负样本淹没。dice loss对正负样本严重不平衡的场景有着不错的性能,训练过程中更侧重对前景区域的挖掘。但训练loss容易不稳定,尤其是小目标的情况下,另外极端情况会导致梯度饱和现象。因此有一些改进操作,主要是结合ce loss等改进,比如: dice + ce loss,dice + focal loss等。
- 多尺度训练——
多尺度训练(Multi Scale Training, MST)通常是指设置几种不同的图片输入尺度,训练时从多个尺度中随机选取一种尺度,将输入图片缩放到该尺度并送入网络中,是一种简单又有效的提升多尺度物体检测的方法。
简书:深度学习中的多尺度训练 在tensorflow,pytorch中就可直接进图片的resize,进行多尺度的训练。
训练时,预先定义几个固定的尺度,每个epoch随机选择一个尺度进行训练。