分类网络之猫狗大战


作业说明

代码模版

截止时间:2019.1.10 23:59:59

目标:通过深度神经网络实现猫狗分类

评分: score = 30 * (2 * mean(accuracy) - 1)

  • accuracy为小组每一个成员所提交结果的测试精度,可能为1至3项,因此取平均
  • 考虑到该任务的最高准确度大约为98%,因此这里提供一个额外的BONUS任务(抵5%准确度)

你需要做的事情:

  • (BONUS)生成训练集 ⚠️⚠️LOTS OF CODES⚠️⚠️

    模版已经实现了一个最简单的训练集生成函数,因此你可以就在这个基础上进行实验;但与此同时你也可以自制一个更精致的训练集,这会让你的网络更加稳定。

    BONUS要求:手写一个random crop的数据增强的函数(只针对训练集)

  • 正确搭建一个深度神经网络

    你可以自己从头开始搭一个神经网络,试验不同的网络结构带来的影响,也可以直接借用成熟/经典的网络结构

  • 调出最好的参数

    这真的是炼丹术

以最终精度为评分依据,模版只是一个参考,一切手段都可以采用。(允许使用Python但需自行提交测试结果)

提交:
在服务器上跑一遍demo即可,submitProject函数会保存你的:网络、测试结果以及你的整个代码文件夹。若完成BONUS项请私下说明。


涉及到的一些MATLAB函数

参考:matlab帮助文档 是很重要的东西

显卡使用:

  • 在训练前请务必在Linux命令行中输入nvidia-smi查看显卡的使用情况,请不要和其他人抢占同一块显卡
  • 利用gpuDevice(n)切换显卡,其中n = 1,2,3,4分别对应于nvidia-smi中的0,1,2,3
  • 大型网络/数据集很容易会导致显存(显卡内存)不足,首先在Linux命令行中利用nvidia-smi确保你没有在和其他人使用同一块显卡,然后将MiniBatchSize调低

数据处理:

  • 数据读取:imageDatastore 数据处理的核心工具
  • 数据增强:augmentedImageDatastore+imageDataAugmenter 提供了一些基本的数据增强方案,但有时仍然需要手写代码(由于MATLAB过度封装的原因,在augmentedImageDatastore的基础上新增额外的数据增加就比较geek了,所以建议是要么就用MATLAB提供的,要么就从头到尾自己写一个)

网络搭建:

  • 简单的网络(如Alexnet)只需要用数组串起来即可
  • 复杂一些的网络(如resnet)则必须用有向无环图DAG(directed acyclic graph)才能表示,这需要一些额外的函数才能搭建:layerGraph,removeLayers,addLayers,connectLayers等等
  • 网络初始化:修改对应层的WeightsBias即可,例如net(2).Weights = 1e-1 * randn(3,3,64,1)

网络训练:

  • 训练参数设置:trainingOptions,深度学习核心函数,建议仔细阅读文档
  • 训练网络:trainNetwork内部实现复杂,但实际使用起来很简单

炼丹经验

更详细的内容可以参考http://cs231n.github.io/,善用搜索引擎(请把百度Ban了),英文资料的参考价值远高于中文资料

深度神经网络的效果由以下三者共同影响

  1. 数据
  2. 网络结构
  3. 参数

这里简单介绍一下如果“炼”出效果最好的深度神经网络。一般的经验是:大的训练集+大的网络结构+合适的参数就能够达到一个更好的效果。

一般来说:2/5的时间处理数据(需要针对给定的数据集和具体任务手写很多代码),1/5的时间搭网络结构(成熟的框架使得这一步就像搭积木一样简单),2/5的时间调参数(比拼炼丹术和穷举法效率的时候)

数据增强 Data Augmentation

数据增强的目的是生成更大的训练集

模版代码中除了一个简单的resize统一图片尺寸的操作以外没有做任何的数据增强操作,实际项目中可能会有以下一系列数据增强的操作:

  • 随机裁剪 Random Crop

    一般来说原始图片的重要信息都在图片的中央部分,因此对其中央部分进行随机裁剪可能会生成更好的数据集(含有的无关信息更少),但剪裁不合理也有可能让网络的性能变差

  • 随机变换 Random flip/scale/translate/rotate/warp

    一些简单的几何变换不会影响图片的信息,例如:”狗”旋转180度之后依然还是一只”狗”

  • 加细微的噪声与模糊

    理由同上

Notes:

  • 合理的数据增强能够在现有的数据集的基础上生成更多有用的数据,这样能使得网络的性能更好。不合理的数据增强反而会降低网络的性能。
  • 对于图片分类任务来说,过于清晰的图像反而会降低准确度(太多的细节干扰)
  • 验证集(Validation set)的目的是为了测试网络的性能,因此一般不作数据增强操作。

网络结构搭建

目前绝大部分网络都是将相同的组件叠加在一起,因此有三方面的考虑:

  • 用什么组件/层
  • 搭成什么结构
  • 怎么初始化权重

网络结构

  • LeNet LeCun, Y., Bottou, L., Bengio, Y., & Haffner, P. (1998). Gradient-based learning applied to document recognition. Proceedings of the IEEE, 86(11), 2278-2324.
  • Alexnet Krizhevsky, A., Sutskever, I., & Hinton, G. E. (2012). Imagenet classification with deep convolutional neural networks. In Advances in neural information processing systems (pp. 1097-1105).
  • VGG net Simonyan, K., & Zisserman, A. (2014). Very deep convolutional networks for large-scale image recognition. arXiv preprint arXiv:1409.1556.
  • GoogLe Net Szegedy, C., Liu, W., Jia, Y., Sermanet, P., Reed, S., Anguelov, D., … & Rabinovich, A. (2015). Going deeper with convolutions. In Proceedings of the IEEE conference on computer vision and pattern recognition (pp. 1-9).
  • ResNet He, K., Zhang, X., Ren, S., & Sun, J. (2016). Deep residual learning for image recognition. In Proceedings of the IEEE conference on computer vision and pattern recognition (pp. 770-778).

网络结构 = 输入层 + 一串(线性层+非线性层的)+ Loss层

网络层

带标记的为MATLAB Deep learning Toolbox提供的层,参考:matlab帮助文档

  • 线性层
    • 全连接层 (Fully Connected Layer): 即线性操作y = W'X + b,大部分分类网络都以全连接层结尾
    • 卷积层 (Convolutional Layer):几乎所有图像相关的问题都采用卷积层,通过多层卷积操作取代了传统的特征提取器
  • 非线性层/激励函数(Activation Function)
    • Relu (Rectified Linear Unit):搭一个新网络时的默认选项
    • Leaky Relu: 解决了relu层带来的dying neuron的问题
    • PRelu (parameterized Relu):将Leaky relu变为可训练的层
    • sigmoid: 基本被Relu取代
  • 特殊层:
    • Max Pooling:适当降低图片的分辨率,可以提高网络的准确性
    • Dropout:采用一种随机抑制输出的操作,来增强网络的稳定性
    • Batch Normalization (BN):对数据进行归一化操作,可以让网络更好训练。
    • 其他一些针对不同任务设计的特殊层
  • Loss层
    • MSE (Mean Squared Error):回归网络的默认Loss
    • MAE (Mean Absolute Error):“有时候”比MSE更好一些
    • Softmax+Cross Entropy: 分类网络的默认Loss,softmax将分类问题转换为回归问题
    • Perceptual Loss: 利用一个其他的已知的网络来计算Loss,能够在一定程度上保证图片的内容是正常的
    • 将不同loss进行一些奇怪的组合

初始化

  • 随机初始化
    • 用比较小的随机值: MATLAB的默认初始化方式
    • Xavier/Glorot initialization Understanding the difficulty of training deep feedforward neural networks(2010)
    • Kaiming/He initialization Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification (2015)
  • 迁移学习:用已经训练好的具有同样结构的网络的权重来进行初始化。一般来说只初始化卷积层,全连接层依然用随机初始化的方法。

调参

一些比较重要的参数:

  • 优化器:一般选择sgdmadam
  • 学习率:对网络性能影响最大的参数。太大的学习率后期不稳定,太小的学习率前期学不动。
    • 初始学习率
    • 学习率的下降方法/隔多少个Epoch下降/每次下降多少
    • 经验:先找到一个合适的初始学习率(一般是1e-2,1e-3,1e-4,1e-5中取一个),先暂时将学习率设定为常数,跑足够多的epoch观察网络在该学习率下的收敛情况,然后再慢慢动态调整学习率的下降
  • BatchSize: 一般设置为64或者128,太大的情况会导致内存不足,太小会导致网络性能下降严重
  • 梯度裁剪:恰当的进行梯度裁剪可以避免网络爆炸到NaN
  • 网络结构
    • 一般来说,卷积核的大小设置为3*3(最小的卷积核)idea: 用多层小卷积核替代单层大卷积核
    • 太深的网络(层数太多)会让网络变得很难训练: ResNet比VGGNet更容易训练
  • 与正则项有关的参数(例如L2Regularization)往往采用默认参数即可