python猫狗⼤战游戏_Kaggle猫狗⼤战图⽚分类项⽬研究本⽂以研究报告形式描述了使⽤TensorFlow Slim 提供的预训练模型 Inception-ResNet-V2 进⾏猫狗图⽚分类的研究。
题图来⾃于⽹络,如侵权请留⾔,⽴即删除。
⼀、 问题定义
(⼀)项⽬概述
本项⽬是机器学习竞赛平台Kaggle上的⼀个图⽚分类项⽬Dogs vs. Cats[1]——猫狗⼤战,项⽬要解决的问题实际是⼀个计算机视觉领域的图像分类问题,图像分类⼀般的⼯作模式为给定⼀张图⽚,判断其属于某个有限类别集合中的哪⼀类。这个领域不仅⾮常有趣,⽽且具有⾮常⼤的应⽤价值和商业价值。猫狗⼤战项⽬图⽚数据来⾃于微软研究院的⼀个CAPTCHA[2](for Completely Automated Public Turing test to tell Computers and Humans Apart)项⽬Asirra[3] 的⼦数据集。
(⼆)问题陈述
猫狗⼤战项⽬要求对⼀个混合了猫和狗的图⽚数据集进⾏⼆分类,项⽬提供了⽤于训练、测试的两部分数据,要求使⽤算法程序在训练集上对已分类的猫和狗的图⽚进⾏建模,然后利⽤建⽴的模型对测试集上多张打乱顺序的未标记猫和狗的图⽚进⾏推断,输出图⽚是狗的概率,使⽤交叉熵损失值作为模型好坏的评
估分数,最终分数需要进⼊Public Leaderboard 10%。
此毕业项⽬要求使⽤深度学习⽅法进⾏建模,将采⽤常见的CNN模型解决这个猫狗图⽚分类问题。
(三)评价指标
使⽤交叉熵损失loss值作为评估指标,交叉熵损失函数是神经⽹络分类算法中常⽤的损失函数,其值越⼩说明模型拟合的分布约接近真实分布,模型表现越好。交叉熵损失函数公式定义如下:
公式1 交叉熵损失函数[4]。
为数据集中的图⽚数;
为预测概率;
python 定义数组在图⽚是狗时为1,否则为0;
是以
为底的⾃然对数。
使⽤交叉熵作为损失函数⼀⽅⾯是其适⽤于分类问题,⼆是题⽬得分评判标准也是交叉熵loss值,与得分评判标准⼀致使得训练阶段的评估指标与题⽬推断阶段评估指标⽐较是有意义的。
⼆、 分析
(⼀)数据的探索
输⼊数据包含训练集、测试集两部分,图⽚格式为JPEG。
训练集:train.zip,包含25000张已标记的图⽚⽂件,⽂件名格式为“类别.图⽚id.jpg”,类别为cat或dog,图⽚id为数字,如
cat.0.jpg、dog.12247.jpg。
测试集:test.zip,包含12500张未标记的图⽚⽂件,⽂件名格式为“图⽚id.jpg”, 图⽚id为数字,如1.jpg、11605.jpg。
训练集数据中标记为猫、狗的图⽚分别有125000张,⽐例1:1,训练集、测试集⽐例为1:2。
数据集中图⽚尺⼨⼤⼩不⼀,训练集、测试集图⽚尺⼨分别有8513、4888种,在训练和推断时需要统⼀
尺⼨。数据中图像不⼀定完整包含完整猫或狗的⾝体,有的主体在图⽚中很⼩,图⽚背景复杂,图⽚⾥会出现⼈或其他物体,如图1。训练集中包含少量⾮猫或狗的图⽚,如
图2,这些异常数据⼤约占训练集的5.6 ‱,需要被清理掉。图1图2
图⽚数值异常可能导致训练时模型不收敛,经检查验证集、测试集数据图⽚RGB值都在[0,255]区间内,数值正常,可直接进⾏归⼀化。
(⼆)探索性可视化
训练集、测试集如果尺⼨分布差异很⼤,训练出来的模型可能在预测时表现不佳。为了确认这⼀点,对训练集、测试集图⽚尺⼨分布进⾏了
可视化,如图3、图4。由可视化结果可见同⼀个集合⾥图⽚尺⼨差异⾮常⼤,各尺⼨分布⽐较平衡,训练集中存在两个离点。训练集和
测试集尺⼨分布形状是相似的,并且除离点外尺⼨分布区间也是⼀致的,图⽚宽和⾼约在[30,500]像素之间,因此训练集训练出的模型是可以⽤于测试集的。图3 训练集尺⼨分布散点图图4 测试集尺⼨分布散点图
(三)算法和技术
图像分类⽬前最流⾏的解决⽅案是使⽤CNN(卷积神经⽹络),CNN是⼀种多层神经⽹络,使⽤多个卷积层、池化层堆叠提取图⽚特征(称之
为feature map),末端⽤多个全连接层堆叠得到概率,使⽤softmax归⼀化输出最终概率。常见的CNN有很多,如InceptionNet[5]、
VGG[6]、ResNet[7]、Inception-ResNet[8]。
上述这些知名的CNN由于⽹络层次⽐较深,参数量⼤,导致计算量⾮常⼤,所需训练时间⽐较长,通常需要使⽤GPU加速训练。实际使⽤
时⼀般采⽤在⼤规模数据集上训练过的预训练模型进⾏微调(fine tune),即迁移学习,这样做不仅可以利⽤其已训练的参数,⽽且还可以⼤
幅减少训练时间。这⾥使⽤tensorflow slim[9] 模块⾥提供的Inception-ResNet-V2预训练模型,Inception-ResNet-V2架构如图5所
⽰,其使⽤ResNet中的残差连接与Inception思想结合,在模型精度和训练速度都有提升。Inception-ResNet-V2在ImageNet数据集上
Top-1、Top-5准确率分别达到了80.4、95.3,在ILSVRC[10]图像分类基准测试中实现了当时(2016年8⽉31⽇)最好的成绩。
ImageNet数据集有1400多万幅图像,涵盖2万多个类别,类别中也包含猫和狗,ImageNet数据集和本项⽬相似性⽐较⼤,进⾏迁移学习时可以利⽤预训练模型卷积层参数提取特征,并调整预训练模型输出1000个分类为2个分类,训练全连接层以拟合本项⽬数据集。图5
Inception-ResNet-V2⽹络架构图[11]
(四)基准模型
题⽬中要求得分进⼊Public Leaderboard 前10%,得分以交叉熵损失loss值计算,总参赛⼈数1314,前10%即排名在1~131名,131
名得分为0.06127,即最终得分需要在(0.00000, 0.06127)之间。
三、 ⽅法
(⼀)数据预处理
本项⽬数据预处理主要包含异常数据清理、训练集划分验证集、图⽚数据读取、标签独热编码、图⽚变换、数值归⼀化、分批、打乱顺序。
异常数据清理:训练集中⼤约包含了15张⾮猫或狗的图像,这些图⽚属于离数据,可能会影响模型精度,需要移除。可以利⽤ImageNet
预训练模型可以出⾮猫或狗的图⽚以确定要清理哪些图⽚。鉴于时间原因且数据量不是太⼤,采⽤了⼈⼯挑选异常图⽚,这⼤约花费了1
⼩时,这种⽅法并不推荐⽤于⼤数据集上,这些异常图⽚⽂件名如下:
cat.4688.jpg,cat.5418.jpg,cat.7377.jpg,cat.7564.jpg,cat.8100.jpg,cat.8456.jpg,cat.10029.jpg,cat.12272.jpg,dog.12
训练集划分验证集:通常模型训练时需要在验证集上观察评估指标是否达到要求,⽽本项⽬只提供了训练集和测试集,所以需要从训练集中
划分⼀部分数据作为验证集,使⽤4:1的⽐例从训练集中随机挑选出⼀部分图⽚作为验证集。
图⽚数据读取:训练时需要将图⽚读⼊内存,并转换为tensorflow使⽤的张量格式。读取图⽚数据时采⽤了tensorflow的⽂件读取管线[12],这样不需要⼀次性将所有数据读⼊内存,可以明显感受到训练逻辑等待读取数据时间⽐⼀次性读⼊要短。图⽚读⼊内存后进⾏JPEG
解码,图⽚是彩⾊图⽚,解码时指定通道数为3(3表⽰Red、Green、Blue三个颜⾊通道),解码后图⽚数据形状为299×299×3的数组。
标签独热编码:分类问题通常需要将离散的标签值转换为独热编码的onehot向量,通常可以采⽤tensorflow或scikit-learn提供的API进⾏
转换,但是这⾥没必要,因为只有两个类别,根据图⽚⽂件名称判断是dog还是cat决定编码为[0,1]或[1,0]即可,这⾥[0,1]表⽰狗,[1,0]表⽰猫。为了保证图⽚编码与标签对应关系是正确的,这⾥做了可视化以验证,如图6:图6 图⽚标签与图⽚对应关系
由图6可看出标签与图⽚对应关系是正确的,读⼊的图⽚数据和实际⽂件也是对应的。
图⽚变换:使⽤的图⽚变换主要为尺⼨调整,图像尺⼨根据使⽤的CNN模型决定,Inception-ResNet-V2使⽤的输⼊图⽚尺⼨为
299×299,调整尺⼨时图⽚宽度或⾼度⼩于299则填充⿊⾊像素⾄299,⼤于299则从图⽚中⼼位置开始
裁剪⾄299,裁剪前后效果⽰
例如图7、图8:图7 dog.8556.jp裁切前图8 dog.8556.jpg裁切后
⽰例中图7、图8⾼度⼀致是为了⽂档美观进⾏了等⽐缩放,图7裁剪前实际尺⼨为499 × 375,图8裁剪后实际尺⼨为299×299。
数值归⼀化:图⽚数值在[0,255]区间,为了训练时收敛速度快,避免激活函数饱和,需要将图⽚数值转换⾄[0,1]区间。这⾥采⽤了tensorflow内置的vert_image_dtype操作,不仅执⾏了归⼀化,还可以转换数据类型为需要的
tensorflow.float32数据类型。归⼀化⼀张图⽚部分数据⽰例如下:
[[[0.5529412 0.4156863 0.26666668]
[0.5372549 0.4039216 0.25882354]
[0.53333336 0.40000004 0.2509804 ]
...
[0.43921572 0.3137255 0.16470589]
[0.43921572 0.3137255 0.16470589]
[0.4431373 0.31764707 0.16862746]]
...
[0.6862745 0.4901961 0.25882354]
[0.76470596 0.5686275 0.3372549 ]
[0.7568628 0.56078434 0.32941177]]]
分批与打乱顺序:分批是为了保证⼀次处理的数据量不超过内存容量或显存容量,这⾥受制于显存容量,批次⼤⼩设置为32。打乱训练数据顺序是防⽌模型过拟合或⽋拟合的⼀种⽅法,采⽤随机打乱即可。
(⼆)执⾏过程
训练阶段代码采⽤tensorflow.slim模块中预置的Inception-ResNet-V2模块构建⽹络,使⽤tensorflow.slim
模块提供的ImageNet预训练模型参数的ckpt⽂件恢复⽹络参数。通过使⽤tensorflow.slim.learning模块train函数控制训练迭代,可简化读取数据的线程控制和保存模型参数。训练阶段训练集batch_size设置为32,验证集批次⼤⼩batch_size设置为160,learning_rate尝试0.01、0.001,迭代次数epochs尝试5、10次。
推断阶段需要载⼊保存的模型,对测试集进⾏预测,输出每个图⽚。
tensorflow.slim提供的⽂档相对简陋,很多情况下需要阅读源代码解决问题,实践中遇到主要问题及解决⽅案如下:
1).由于Inception-ResNet-V2预训练模型使⽤ImageNet数据集训练时是1000个类别,⽽本项⽬是2个类别,训练时需重新训练全连接层,恢复参数时需要排除“Logits”和“AuxLogits”这两层的参数。
2). 训练时要固定卷积层参数,训练全连接层参数,即训练“Logits”和“AuxLogits”这两层的参数,这需要从所有可训练变量中查上述两层的所有变量,并传递给tensorflow.ain函数的variables_to_train参数。如果未固定“Logits”和“AuxLogits”这两层参数,会出现训练很久不收敛的现象。
3).由于tensorflow.ain函数内部控制了Tensorflow Session的创建,恢复变量时需要通过指定初始化函数给tensorflow.ain函数的init_fn参数,在这个初始化函数中实现恢复参数,幸运的是ib.framework中提供了assign_from_checkpoint_fn函数来实现此功能。
4).通常在训练时需要在⽇志中输出训练集和验证集上的准确率、loss、step等信息以便观察模型训练的情况。同样由于
ain函数对外屏蔽了Session,需要通过传⼊回调函数的⽅式给train⽅法的train_step_fn参数来实现这⼀功能。
尝试多次后,最终在learning_rate=0.001,epochs=5时获得最佳结果,得分为0.06584。
(三)完善
最终获得的最优的得分为0.06584,这个得分⼤于0.06127,未能进⼊Public满Leaderboard前10%的要求。尝试数据提升,通随机⽔平翻转、随机调整⾊调、对⽐度、饱和度、明亮度,但对模型的提升不明显。
考虑到最终得分使⽤log loss的交叉熵,对于正确的样本0.995和1相差不⼤,对于错误的样本,0和0.005差距⾮常⼤[13],所以此处可采⽤⼀个clip trick,将测试集预测的数值限制在[0.005, 0.995]这个区间。结果证明采⽤这个trick之后,得分提升到0.04845,排名进⼊51名,详见表1。由表1可看出,使⽤了clip trick对两个模型的最终得分都是有明显提升的。表1 不同学习速率和是否使⽤clip的得分对
⽐,score为测试集上的交叉熵loss,epoch为5
四、 结果
(⼀)模型的评价与验证
通过保存训练时验证集loss和准确率可以绘制训练次数与loss和准确率的曲线,这⾥使⽤了tensorflow⾃带的可视化⼯具tensorboard进⾏可视化,如图9。从图上可看出,统⼀在训练次数为2000次时,learning_rate=0.001时准确率和loss抖动较⼩,更加稳健,表现更
好。图9 不同学习速率表现对⽐
(⼆)合理性分析
学习速率是⼀个超参数,设置过⼩会导致收敛较慢,设置过⼤会导致准确率和loss振荡较⼤难以收敛。由图9可见,学习速率在0.01时,准确率和loss振幅和振荡频率都⽐较⼤,从0.01调整⾄到0.001后,准确率和loss振荡幅度和频率有明显降低,模型更加稳健,所以在尝试的两个学习速率中,学习速率为0.001时,模型得到最优分数是合理的。
五、 项⽬结论
(⼀)结果可视化
模型最终预测结果见图9,随机展⽰了5张图⽚及其预测为够的概率,可以看出与图⽚中实际的动物是⼀致的,猫的图⽚预测为狗的概率都是0.005(由于trick限制了数据范围最⼩为0.005,实际计算出的概率<=0.005),狗的图⽚都在90%以上。图10 模型预测是狗概率与实际
图⽚对照
结果提交⾄Kaggle上最终得分0.04845,见图11。图11 Kaggle得分
(⼆)对项⽬的思考
通过本项⽬实现了猫狗图像的⼆分类,⾸先对数据进⾏预处理,然后利⽤tensorflow slim模块搭建了深度卷积神经⽹络Inception-RestNet-V2,并利⽤迁移学习加速了模型训练的过程,根据交叉熵评估函数的特点采⽤了数值计算上的trick,最终得分进⼊Public Leaderboard 前4%,达到题⽬10%的要求。
项⽬中对于第⼀次使⽤缺乏完善⽂档的tensorflow slim来说是有困难的,幸运的是所有问题都解决了。项⽬中最难的地⽅在于提升模型的得分,要多次调整超参数,尝试多个⽅法后没有取得更好的成绩⾮常令⼈沮丧。最有意思的是使⽤了⼀个⼩的trick居然提升⾮常⼤,这是万万没想到的。
最终的模型和结果在这个猫狗分类问题上是符合期望的,没有使⽤trick时,单模型精度已经⾮常⾼了。这个模型⽆法⽤于通⽤场景,模型参数和数据集是⾮常相关的,通⽤场景的数据与本项⽬数据集分布不
⼀致,所以⽆法适⽤,但⽹络架构是可以通⽤的。
(三)需要做出的改进
如果不⽤trick就能否冲进前10%,这值得⼀试,使⽤集成学习可能是⼀个好办法。可考虑Inception-ResNet-V2、Inception-V4、ResNet-V2三个预训练模型集成,集成时使⽤三个模型的预训练权重进⾏特征提取,提取特征后进⾏拼接,再dropout加全连接进⾏训练,这样通过不同模型学到的不同特征组合很可能获得更⾼的精度、更低的loss。
六、 引⽤
[3] Microsoft. Asirra: A CAPTCHA that Exploits Interest-Aligned Manual Image Categorization - Microsoft Research
[11] yeephycho. A Note to Techniques in Convolutional Neural Networks and Their Influences III (paper summary) | yeephycho
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论