基于CNN的猫狗品种识别技术研究

  • 总体方案


    image.png
  • 研究背景
    近年来,深度学习理论和技术都得到了迅速的发展,并且受到了越来越多的研究者的关注,深度学习技术在图像识别领域具有广泛的应用。尤其是在特征提取和建模上有着非常明显的优势浅层对比模型。现在已经有了非常多的经典成熟模型,如AlexNet、VGG16、VGG19、GoogleLeNet、Inception-v3和ResNet等,但未必适用于所有的试验数据集。本课题拟运用卷积神经网络(CNN)对猫狗公开数据集进行分类识别,在较成熟的Resnet模型基础上通过模型结构调整和参数寻优等,设计出适用于本课题数据集的深度学习分类器。本课题的研究结论可充实猫狗数据集的分类模型库,为后来者提供参考和借鉴。

  • 技术路线


    image.png
  • 实验环境
    本实验是在基于Anaconda的环境管理工具、PyTorch深度学习框架和Pycharm的编译器上进行设计实现的。研究环境如下所示:
    (1) 软件部分
    操作系统:Windows10 64位系统;
    开发工具:Pycharm、Anaconda;
    CUDA:10.2.89_441.22_win10;
    PyTorch:1.1.0;
    Torchvision:0.3.0;
    Pyyaml:0.1.7;
    Pillow:6.0.0;
    TensorboardX:2.0。
    (2) 硬件部分
    内存:16G;
    CPU:Inter i7-4720HQ 2.6GHz;
    GPU:GTX 950m(2G);
    硬盘:固态硬盘:128G、机械硬盘:1T。

  • 数据集
    本文采用的是Kaggle竞赛的公开的猫狗数据集。本数据集可以从Kaggle官方网站中下载Dogs vs. Cats Redux: Kernels Edition。本数据集一共有猫和狗两种种类的图片。猫和狗的图片各12500张。数据集中初始的各个图片的大小和分辨率都是不一致的。如图3-1中的cat.0.jpg的分辨率是500×374而图3-2中的dog.1.jpg的分辨率是327×499。每张图片的分辨率都是不同的,所以在之后数据集预处理中需要调整图片的大小来统一图片的分辨率。因为数据集中的图片都为彩色RGB图片,所以图像的通道数为3通道。数据集中的图像不一定完整包含完整的猫或狗的身体,有的主体在图片中非常小,图片背景也比较复杂,例如图3-1中的cat.6.jpg中会出现人或者其他物体。


    image.png

    image.png

    通过调整图片大小,水平翻转,一定角度旋转,添加噪声,图片归一化对猫狗数据集进行预处理操作。


    image.png
  • 网络模型


    image.png

    ResNet-18都是由BasicBlock组成,从图4-2也可得知50层及以上的ResNet网络模型由BottleBlock组成。在我们就需要将我们预处理过的数据集放入现有的Resnet-18和ResNet-50模型中去训练,首先我们通过前面提到的图像预处理把训练图像裁剪成一个96x96的正方形尺寸,然后输入到我们的模型中,这里就介绍一下ResNet-18的网络模型的结构,因为ResNet50与第五章的ResNet-34模型结构相仿。

    ResNet-18的模型结构为:首先第一层是一个7×7的卷积核,输入特征矩阵为[112,112,64],经过卷积核64,stride为2得到出入特征矩阵[56,56,64]。第二层一开始是由一个3×3的池化层组成的,接着是2个残差结构,一开始的输入的特征矩阵为[56,56,64],需要输出的特征矩阵shape为[28,28,128], 然而主分支与shortcut的输出特征矩阵shape必须相同,所以[56,56,64]这个特征矩阵的高和宽从56通过主分支的stride为2来缩减为原来的一半即为28,再通过128个卷积核来改变特征矩阵的深度。然而这里的shortcut加上了一个1x1的卷积核,stride也为2,通过这个stride,输入的特征矩阵的宽和高也缩减为原有的一半,同时通过128个卷积核将输入的特征矩阵的深度也变为了128。第三层,有2个残差结构,输入的特征矩阵shape是[28,28,128],输出特征矩阵shape是[14,14,256], 然而主分支与shortcut的输出特征矩阵shape必须相同,所以[14,14,256]这个特征矩阵的高和宽从14通过主分支的stride为2来缩减为原来的一半即为7,再通过128个卷积核来改变特征矩阵的深度。然而这里的shortcut加上了一个1×1的卷积核,stride也为2,通过这个stride,输入的特征矩阵的宽和高也缩减为原有的一半,同时通过256个卷积核将输入的特征矩阵的深度也变为了256。第四层,有2个残差结构,经过上述的相同的变化过程得到输出的特征矩阵为[7,7,512]。第五层,有2个残差结构, 经过上述的相同的变化过程得到输出的特征矩阵为[1,1,512]。接着是平均池化和全连接层。
    image.png
    image.png
    image.png
  • 优化和损失函数
    本次选择随机梯度下降法(SGD)进行优化,具体操作阶段,主要利用各样本迭代更新1次,若样本非常多,或许仅需一些样本,便可以把theta迭代至最佳解,而批量梯度下降(BGD)迭代1次必然涉及十多万样本,也无法做到最优,若迭代10次,必须遍历样本10次,工作量过大。事实上,SGD也不完美,譬如噪音相比BGD更多,导致SGD各次迭代过程中,无法始终朝总体最优推进。因此,即便训练更加高效,但准确率降低,难以保证全局最优。不置可否,就算有着相应随机性,但是从期望上来看,它是等于正确的导数的。但是随机梯度下降也有缺点:如果随机梯度下降更新比较频繁,可能会造成 cost function 有严重的震荡。
    损失函数采用的是交叉熵损失函数(Cross Entropy Loss),交叉熵能够衡量同一个随机变量中的两个不同概率分布的差异程度,在机器学习中就表示为真实概率分布与预测概率分布之间的差异。交叉熵的值越小,模型预测效果就越好。其计算公式为:
    cross_entropy=-∑_(k=1)^N▒〖(p_k*log⁡〖q_k 〗)〗 (4-1)
    其中表示真实值,在这个公式中是one-hot形式;是预测值,在这里假设已经是经过softmax后的结果了。
    仔细观察可以知道,因为的元素不是0就是1,而且又是乘法,所以很自然地我们如果知道1所对应的index,那么就不用做其他无意义的运算了。所以在PyTorch代码中target不是以one-hot形式表示的,而是直接用scalar表示。所以交叉熵的公式(m表示真实类别)可变形为:

cross_entropy=-∑_(k=1)^N▒〖(p_k*log⁡〖q_k 〗 )=-log⁡〖q_m 〗 〗 (4-2)
仔细观察,其实就是等同于log_softmax和nll_loss两个步骤。所以PyTorch中的F.cross_entropy会自动调用上面介绍的log_softmax和nll_loss来计算交叉熵,其计算方式如下:

loss(x,class)=-log⁡〖((exp⁡(x[class]))/(∑_j▒〖exp⁡(x[j])〗))〗 (4-3)
one-hot表示独热编码,实践操作阶段,主要通过N位条件码寄存器,面向N个状态完成有效编码,而各自均单独存在对应寄存器位,无论哪个时候,始终仅是一位有效。Softmax 属于1个“软”的最大值函数,它不是直接取输出的最大值那一类作为分类结果,同时也会考虑到其它相对来说较小的一类的输出。换言之,Softmax 能够把全连接层输出直接映射为1个概率分布,由训练角度出发,核心宗旨在于使归属第k类各样本得到 Softmax处理,第 k 类概率愈高愈好。如此一来,更有利于人们以统计学手段论证分类问题。
在实验的过程中,采用基于PyTorch框架的tensorboardX方法来实现了train_loss, test_loss, test_loss_cat, test_loss_dog这些数据在训练和测试的期间的loss的变化。

  • 结果展示


    image.png

    image.png
    image.png
    image.png
    image.png
    image.png

你可能感兴趣的:(基于CNN的猫狗品种识别技术研究)