面向计算机视觉任务竞赛构建通用的可用框架
2020 年冬
作为惠普 Z 系列数据科学全球大使,Qishen Ha 的内容由惠普赞助,且向他提供了惠普产品。
大家好,我是 Qishen Ha。目前,我在 LINE Corp.工作,是一名机器学习工程师,Kaggle Grandmaster 世界排名第 5,主要研究图像分类、语义分割、对象监测等计算机视觉技术。
非常荣幸能成为惠普 Z 系列数据科学全球大使,也非常感谢惠普 Z 系列给予我这次机会,并为我提供了 HP Z8 G4 工作站和 ZBook Studio。这大大增加了我在 Kaggle 竞赛中的竞争力。
今天我想和大家聊聊我在竞赛中使用的代码框架。特别是计算机视觉竞赛使用的代码框架。
我的公共笔记本
在过去的几年里,我制作了不少可以公开使用的 CNN 训练笔记本,有的是基线模型,有的是顶层解决方案的最小版本(因为完整版本的代码和训练量太大了)。
如果大家有看过我的笔记本,就会发现尽管它们使用不同的数据、执行不同的训练任务,但都有着相同的基本框架。这称为通用框架。参加新的竞赛时,我们可以使用通用框架在尽可能短的时间内训练出新的基线模型,而且事后也很容易对此框架进行改进或维护。
下面我将总结我在这些笔记本中使用的框架,并介绍每个模块。当然,这是我自己习惯使用的框架,我觉得用起来很顺手。如果大家已经有自己熟悉的框架,那就没有必要照搬我的框架了,当作参考即可。
我的框架介绍
以下是我的框架中的基本通用模块:
- 数据集
- 增强
- 模型
- 损失函数
我将在下面逐一介绍这些模块。
数据集定义了读取数据、预处理数据、读取和处理标签的方式。这张图片显示了数据集的基本代码结构之一。
这是一个简单的图像分类任务。我们使用 cv2 将图像读入内存,接着经过增强和预处理,然后返回处理后的图像和标签。
这是一种非常通用的代码风格,当我们需要将其应用于图像分割任务时,只需要进行非常微小的修改。下图显示了一些比较重要的修改。
最后,我们需要调整掩码的数据类型和维度、替换 row.label 并返回。
通过这种方式,我们可以轻松地修改数据集、读取想要的数据、按希望的方式对数进行预处理,等等。
大家可能已经注意到,数据集中有一个名为“transforms”的参数,其中包含我们会使用的增强方法,以及这些方法在增强部分中定义。
这张图片显示了增强的简单定义。在训练中我们使用水平翻转和尺寸调整,而在验证中我们只需要使用尺寸调整。
增强
如需要添加增强方法,可以通过如下方式轻松添加。
增强
像这样,我们便可在训练过程中加入随机旋转和图像模糊。
在这一部分中,我们需要定义模型的结构。我们还是以简单的图像分类任务为例,来聊一聊模型的结构,供大家参考。
在图像分类任务中,我们通常会创建一个 imagenet 预训练模型(如 effecentnet),以此作为主干网络,同时删除自带的 1000 个类的线性层(imagenet 数据集是 1000 类数据集),并添加自己的 n 个类的线性层。如图所示。
如果想在 FC 的最后一层之前添加一个 dropout,我们可以按下列方法轻松完成编写。
另一个常见的场景是,输入图像可能不是 RGB 3 通道,而是 4 通道或其他通道。在这种情况下,我们可以变更主干网络第一卷积层的输入内容,如下图所示。
这里的 n_ch 便是输入的通道数。通过这种方式,我们不仅可以根据需要变更输入的通道数,也可以在第一卷积层继续使用 imagenet 的预训练权重值。
定义损失函数最简单的方法如下。这也是最常用的方式。
然而,它也很容易变得很复杂,如下所示。
在这个损失函数中,我们对前四个输出使用交叉熵损失,对其他输出使用 BCE 损失,同时通过添加损失权重来平衡这两个损失,这会使得逻辑变得复杂起来,但好处是不需要更改太多代码。我们利用这个损失函数赢得了 RANZCR 竞赛的第一名。
结语
我的框架包含四个基本模块,它们的设计使其非常容易扩展。这些模块结合起来便形成了我所用的框架。在使用这个框架做实验时,我每次都会以笔记本的形式记录,这对分析结果和重现实验结果很有帮助。
如需了解详细信息,可以访问我的 Kaggle 主页,查看我分享的笔记本,我相信大家会在这些笔记本中找到很多有用的信息。