# cifar10-tensorflow **Repository Path**: l-j-l/cifar10-tensorflow ## Basic Information - **Project Name**: cifar10-tensorflow - **Description**: cifar10数据集上进行图片分类,基于tensorflow框架,旨在探究不同的改进策略对分类准确率的影响,如何一步步得提高准确率 - **Primary Language**: Python - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2022-03-09 - **Last Updated**: 2022-03-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 如何提高图像分类准确率? 知乎文章链接,https://zhuanlan.zhihu.com/p/29534841 ## 一、问题描述 本文使用的数据集是CIFAR-10数据集,该数据集有50000张图片,每张图片均为分辨率为32*32的彩色图片(分为3个信道)。分类任务需要分成青蛙、卡车、飞机等10个类别。本文设计一种卷积神经网络用于处理图像分类任务,接下来介绍基于卷积神经网络的分类模型,**并且重点说明如果通过不同的技术一步步地提高分类准确率**。 为了训练该网络,首先将数据分为训练集、验证集和测试集3个数据集,训练集样本个数为45000,验证集样本个数为5000,测试集样本个数为10000。CIFAR-10图像分类示例图像如图1。 ![图像分类示例图像](/others/pictures/frog.png) 图1、CIFAR-10数据集示例图像 ## 二、分类模型 ### 模型1——基本卷积网络 模型的输入数据是网络的输入是一个4维tensor,尺寸为(128, 32, 32, 3),分别表示一批图片的个数128、图片的宽的像素点个数32、高的像素点个数32和信道个数3。首先使用多个卷积神经网络层进行图像的特征提取,卷积神经网络层的计算过程如下步骤: 1. **卷积层1**:卷积核大小3\*3,卷积核移动步长1,卷积核个数64,池化大小2\*2,池化步长2,池化类型为最大池化,激活函数ReLU。 2. **卷积层2**:卷积核大小3\*3,卷积核移动步长1,卷积核个数128,池化大小2\*2,池化步长2,池化类型为最大池化,激活函数ReLU。 3. **卷积层3**:卷积核大小3\*3,卷积核移动步长1,卷积核个数256,池化大小2\*2,池化步长2,池化类型为最大池化,激活函数ReLU。 4. **全连接层**:隐藏层单元数1024,激活函数ReLU。 5. **分类层**:隐藏层单元数10,激活函数softmax。 参数初始化:所有权重向量使用random_normal(0.0, 0.001),所有偏置向量使用constant(0.0), 使用cross entropy作为目标函数,使用Adam梯度下降法进行参数更新,学习率设为固定值0.001。 训练5000轮,观察到loss变化曲线、训练集准确率变化曲线和验证集准确率变化曲线如图2。测试集准确率为**69.36%**。 ![model1](/exps/cifar10-v1/cifar10-v1.png) 图2、模型1的loss收敛曲线图和验证集准确率图 ### 模型2——数据增强(Data Augmentation) 在模型1的基础上,加强数据预处理部分,称为数据增强(data augmentation)技术。使用数据增强技术,主要在训练数据上增加微小的扰动或者变化,一方面可以增加训练数据,从而提升模型的性能,另一方面可以增加噪声数据,从而增强模型的鲁棒性。cifar10数据集主要做的数据增强操作有如下方面: 1. **图像切割**:生成比图像尺寸小一些的矩形框,对图像进行随机的切割,最终以矩形框内的图像作为训练数据。 2. **图像翻转**:对图像进行左右翻转。 3. **图像白化**:对图像进行白化操作,即将图像本身归一化成Gaussian(0,1)分布。 为了进行对比实验,实验1只进行步骤1,实验2只进行步骤2,实验3只进行步骤3,同样训练5000轮,观察到loss变化曲线、训练集准确率变化曲线和验证集准确率变化曲线对比如图3。 可以观察到,白化操作的效果好,其次是切割,再次是翻转,而如果同时使用这3种数据增强技术,会使验证集的准确率从72%左右提升至82%左右,提升效果十分明显。而对于测试集,准确率也提升至**80.42%**。 ![model2](/exps/cifar10-v2/cifar10-v2.png) 图3、模型2使用不同数据增强步骤的收敛曲线和验证集准确率对比图 ### 模型3——模型改进 在模型2的基础上,对模型进行进一步的改进,提高模型的性能,主要使用如下的技术进行改进: 1. **权重衰减**(weight decay):对于目标函数加入正则化项,限制权重参数的个数,这是一种防止过拟合的方法。 2. **dropout**:在每次训练的时候,让某些的特征检测器停过工作,即让神经元以一定的概率不被激活,这样可以防止过拟合,提高泛化能力。 3. **批正则化**(batch normalization):batch normalization对神经网络的每一层的输入数据都进行正则化处理,这样有利于让数据的分布更加均匀,不会出现所有数据都会导致神经元的激活,或者所有数据都不会导致神经元的激活,这是一种数据标准化方法,能够提升模型的拟合能力。 4. **LRN**:LRN层模仿生物神经系统的侧抑制机制,对局部神经元的活动创建竞争机制,使得响应比较大的值相对更大,提高模型泛化能力。 为了进行对比实验,实验1只使用权重衰减,实验2使用权重衰减+dropout,实验3使用权重衰减+dropout+批正则化,实验4使用权重衰减+dropout+批正则化+LRN,同样都训练5000轮,观察到loss变化曲线、训练集准确率变化曲线和验证集准确率变化曲线对比如图4。 可以观察到,随着每一个模型提升的方法,都会使训练集误差和验证集准确率有所提升,其中,批正则化技术和dropout技术带来的提升非常明显,而如果同时使用这些模型提升技术,会使验证集的准确率从82%左右提升至88%左右,提升效果十分明显。而对于测试集,准确率也提升至**85.72%**。 ![model3](/exps/cifar10-v6/cifar10-v6.png) 图4、模型3使用不同模型提升方法的收敛曲线和验证集准确率对比图 ### 模型4——变化学习率 在模型3的基础上,对模型进行进一步的改进,提高模型的性能,主要使用变化学习率的方法,过程如下: 1. 首先使用较大的学习率进行训练,观察目标函数值和验证集准确率的收敛曲线。 2. 如果目标函数值下降速度和验证集准确率上升速度出现减缓时,减小学习率。 3. 循环步骤2,直到减小学习率也不会影响目标函数下降或验证集准确率上升为止。 为了进行实验对比 - 实验1:只使用0.01的学习率训练。 - 实验2:前10000轮使用0.01的学习率,10000轮之后学习率降到0.001。 - 实验3:前10000轮使用0.01的学习率,10000~20000轮使用0.001的学习率,20000轮之后学习率降到0.0005。 观察到loss变化曲线和验证集准确率变化曲线对比如图5。 可以观察到,当10000轮时,学习率从0.01降到0.001时,目标函数值有明显的下降,验证集准确率有明显的提升,而当20000轮时,学习率从0.001降到0.0005时,目标函数值没有明显的下降,但是验证集准确率有一定的提升,而对于测试集,准确率也提升至**86.24%**。这说明,学习率的变化确实能够提升模型的拟合能力,从而提升准确率。 ![model4](/exps/cifar10-v11/cifar10-v11.png) 图5、模型4使用不同学习率的收敛曲线和验证集准确率对比图 ### 模型5——深层网络 在模型4的基础上,对模型进行进一步的改进,主要对网络进行层数上的加深,使用的深层网络的模型为plain-cnn,网络的每一层如下设置: 1. **卷积层1**:卷积核大小3\*3,卷积核移动步长1,卷积核个数16,激活函数ReLU,使用batch_normal和weight_decay,接下来的n层,卷积核大小3\*3,卷积核移动步长1,卷积核个数16,激活函数ReLU,使用batch_normal和weight_decay。 2. **卷积层2**:卷积核大小3\*3,卷积核移动步长2,卷积核个数32,激活函数ReLU,使用batch_normal和weight_decay,接下来的n层,卷积核大小3*3,卷积核移动步长1,卷积核个数32,激活函数ReLU,使用batch_normal和weight_decay。 3. **卷积层3**:卷积核大小3\*3,卷积核移动步长2,卷积核个数64,激活函数ReLU,使用batch_normal和weight_decay,接下来的n层,卷积核大小3*3,卷积核移动步长1,卷积核个数64,激活函数ReLU,使用batch_normal和weight_decay。 4. **池化层**:使用全局池化,对64个隐藏单元分别进行全局池化。 5. **全连接层**:隐藏层单元数10,激活函数softmax,使用batch_normal和weight_decay。 学习率设置为前50000轮使用0.01的学习率,50000~100000轮使用0.005的学习率,100000~150000轮使用0.0025的学习率,150000轮之后使用0.001的学习率。为了进行对比实验,进行4组实验,每组的网络层数分别设置8,14,20和32。观察到loss变化曲线和验证集准确率变化曲线对比如图6。 可以观察到,网络层数从8层增加到14层,准确率有所上升,从14层增加到20层再增加到32层,准确率不升反降,这说明如果网络层数过大,由于梯度衰减的原因,导致网络性能下降,因此,需要使用其他方法对网络进行改进。 ![model5](/exps/cifar10-v16/cifar10-v16.png) 图6、模型5使用深度网络的收敛曲线和验证集准确率对比图 ### 模型6——残差网络(ResNet) 在模型5的基础上,对模型进行进一步的改进,主要是使用残差网络技术,解决由于网络层数加深而引起的梯度衰减问题。由于网络层数加深,误差反传的过程中会使梯度不断地衰减,而通过跨层的直连边,可以使误差在反传的过程中减少衰减,使得深层次的网络可以成功训练。残差网络示意图如图6。 ![resnet](/others/pictures/resnet.png) 图6、残差网络示意图 通过设置对比实验,观察残差网络的性能,进行4组实验,每组的网络层数分别设置20,32,44和56。观察到loss变化曲线和验证集准确率变化曲线对比如图7。 我们观察到,网络从20层增加到56层,训练loss在稳步降低,验证集准确率在稳步提升,并且当网络层数是56层时能够在验证集上达到91.55%的准确率。这说明,使用了残差网络的技术,可以解决梯度衰减问题,发挥深层网络的特征提取能力,使模型获得很强的拟合能力和泛化能力。当我们训练深度网络的时候,残差网络很有可能作为终极武器发挥至关重要的作用。 ![model6](/exps/cifar10-v20/cifar10-v20.png) 图7、模型6使用残差网络的收敛曲线和验证集准确率对比图 ## 三、总结 对于图像分类问题,我们从最简单的卷积神经网络开始,分类准确率只能达到70%左右,通过不断地增加提升模型性能的方法,最终将分类准确里提升到了90%左右,这20%的准确率的提升来自于对数据的改进、对模型的改进、对训练过程的改进等,具体每一项提升如下表所示。 | 改进方法 | 获得的准确率 | 提升 | | -------- | ------ | ------ | | 基本神经网络 | 69.36% | - | | + 数据增强 | 80.42% | 11.06% | | + 模型改进 | 85.72% | 16.36% | | + 变化学习率 | 86.24% | 16.88% | | + 网络层数加深 | - | - | | + 残差网络技术 | 91.55% | 22.19% | 表1、每个改进锁产生的模型提升效果 其中,数据增强技术使用翻转图像、切割图像、白化图像等方法增加数据量,增加模型的拟合能力。模型改进技术包括batch normalization、weight decay、dropout等防止过拟合,增加模型的泛化能力。变化学习率通过在训练过程中递减学习率,使得模型能够更好的收敛,增加模型的拟合能力。加深网络层数和残差网络技术通过加深模型层数和解决梯度衰减问题,增加模型的拟合能力。这些改进方法的一步步堆叠,一步步递进,使得网络的拟合能力和泛化能力越来越强,最终获得更高的分类准确率。