在 Torch 上 CIFAR-10 达到 92.45% 准确率

2015 年 7 月 30 日 作者:Sergey Zagoruyko

完整代码可在 https://github.com/szagoruyko/cifar.torch 获取,只需将其克隆到你的机器上即可使用。

CIFAR-10 包含 60000 张标记为 10 个类别,大小为 32x32 的图像,训练集有 50000 张,测试集有 10000 张。曾经举办过一个 Kaggle 比赛:https://www.kaggle.com/c/cifar-10,这里有一个略微过时的最先进结果表:http://rodrigob.github.io/are_we_there_yet/build/classification_datasets_results.html

cifar.10

按照今天的标准,该数据集相当小,但仍然是机器学习算法的一个很好的游乐场。最先进的当然包括深度卷积神经网络,然而很难定义哪种“深度”技术是最好的。如果你不做任何裁剪、仿射变换或集成,只进行水平翻转,我认为 92.45% 是最好的结果。有趣的是,人类的表现大约为 94%,要超越它就必须使用大量的图像增强。查看 @nagadomi 在 24x24 裁剪上的训练代码:https://github.com/nagadomi/kaggle-cifar10-torch7

我的代码大约 400 行,包括模型定义和数据预处理,主要来自 2_supervised 教程。有一些我不喜欢的地方

  • 所有代码都在一个文件中:这对演示来说很好,但是如果你想做实验,你不想每次运行都要等待数据预处理;
  • 批次逐个示例处理。对于新手来说,如何正确地做到这一点并不明显,他们会复制粘贴代码,然后它就会非常慢;
  • 其中的模型已经很旧了。

所以我对它进行了现代化,并添加了一些不错的技巧,例如保存一个每次迭代都会更新的 html 报告。它可以复制到 Dropbox 等地方,非常有助于跟踪模型性能并保存报告。

你需要一台至少有 2 GB 内存的 GPU,并安装 cudnn,使用标准 nn 后端需要更多内存。 cudnn 是 NVIDIA 的深度学习库,目前尚未公开发布,但绝对值得注册并申请,它很棒:https://developer.nvidia.com/cudnn

NVIDIA GPU 是首选,也是 BatchNormalization 所需的,但 AMD 卡也可以使用 OpenCL,这得益于 Hugh Perkins 的这项惊人工作:https://github.com/hughperkins/cltorch.git 查看 opencl 分支

这篇文章和代码由 3 个部分/文件组成

  • 模型定义
  • 数据预处理
  • 训练

模型 models/vgg_bn_drop.lua

在 Batch Normalization 论文 [1] 今年冬天出现在 arxiv 上,提供了一种通过使用批次统计来加速训练和提高性能的方法,以及 nn.BatchNormalization 在 Torch 中实现后(感谢 Facebook),我想看看它与 Dropout 如何协同工作,CIFAR-10 是一个很好的起点。

想法很简单,虽然 BatchNormalization 的作者认为它可以代替 Dropout,但我认为为什么不在网络内部一起使用它们来大规模正则化训练呢?

所以模型定义在这里

这是一个类似 VGG 的网络 [2],有许多 3x3 过滤器,填充为 1,1,因此它们之后的特征图大小不会改变。只有在最大池化后才会改变它们的大小。卷积层的权重采用 MSR 风格 [3] 初始化。

预处理 provider.lua

我喜欢用 BatchProvider -> 网络结构来训练模型。实际上,你甚至可以创建一个像这样的模型

model = nn.Sequential()
model:add(BatchProvider) -- different in train and test mode
model:add(DataAugmentation) -- disabled in test mode
model:add(NeuralNetwork)

然后你的训练代码非常简单。但是,在实际代码中,我只在模型中保留数据增强,虽然 BatchProvider 是一个类。所以,让我们开始预处理,从 https://github.com/szagoruyko/cifar.torch 克隆代码,进入文件夹 cifar.torch,启动解释器

th -i provider.lua

它会运行文件并进入交互模式。预处理大约需要 40 分钟

provider = Provider()
provider:normalize()
torch.save('provider.t7',provider)

最终,所有数据都将存储在 provider.t7 文件中,大小为 1400 MB。图像被转换为 YUV,并进行均值-标准差归一化。

训练 train.lua

就是这样,你可以开始训练了

CUDA_VISIBLE_DEVICES=0 th train.lua

模型达到最佳性能的参数是代码中的默认参数。我使用了带交叉熵损失的 SGD,学习率为 1,动量为 0.9,权重衰减为 0.0005,每 25 个迭代周期降低一次学习率。几个小时后,你将拥有模型。可以通过例如自动更新的 Firefox 或 Chrome 插件更新 logs/report.html 来跟踪准确率。

准确率如何提高

test.log

混淆矩阵

ConfusionMatrix:
[[     929       4      15       7       4       0       1       2      29       9]   92.900%
 [       2     977       2       0       1       0       0       0       6      12]   97.700%
 [      16       1     923      16      25       8       7       1       3       0]   92.300%
 [      14       2      30     836      19      68      18       5       6       2]   83.600%
 [       6       1      18      16     932       7       6      10       4       0]   93.200%
 [       3       1      25      78      17     867       4       5       0       0]   86.700%
 [       4       1      19      17       6       7     942       0       2       2]   94.200%
 [       6       0      12      15      10      14       0     942       1       0]   94.200%
 [      22       6       4       1       0       1       1       0     961       4]   96.100%
 [       9      38       1       4       0       1       1       1      10     935]]  93.500%
 + average row correct: 92.439999580383%
 + average rowUcol correct (VOC measure): 86.168013215065%
 + global correct: 92.44%

移除 BN 或 Dropout 会导致 91.4% 的准确率。

我创建了一个小表格,在 GeForce GTX 980 上对 VGG+BN+Dropout 架构的不同后端进行了基准测试。批次大小设置为 128,数字以秒为单位

| cunn | cudnn R2 | clnn(无 BN) — | :—: | :—: | :—: forward | 0.292 | 0.163 | 1.249 backward | 0.407 | 0.333 | 0.831 forward + backward | 0.699 | 0.500 | 2.079

cunn 是 Torch 的标准 CUDA 神经网络后端,clnn 是 OpenCL 后端。 cudnn 是最快的,正如预期的那样。还有一个 cuda-convnet2 后端,它可能更快,但我没有在这个架构上进行测试,主要是因为 BN 是以 BDHW 格式实现的,而 cuda-convnet2 以 DHWB 格式工作。

这段代码是深度卷积神经网络的一个很好的游乐场,例如,它很容易实现 Network-In-Network 架构 [4],该架构在使用 BN 时可以达到 92% 的准确率(比他们在论文中声称的准确率高出约 2%),在不使用 BN 时可以达到 88% 的准确率,而 NIN 的训练速度是 VGG 的 4 倍。我在 nin.lua 中添加了示例

感谢 Soumith 和 IMAGINE 实验室帮助我准备这篇文章!

参考资料

  1. Sergey Ioffe, Christian Szegedy. Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift [arxiv]
  2. K. Simonyan, A. Zisserman. Very Deep Convolutional Networks for Large-Scale Image Recognition [arxiv]
  3. Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun. Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification [arxiv]
  4. Min Lin, Qiang Chen, Shuicheng Yan. Network In Network [arxiv]
Disqus 提供支持的评论