原文: Categorizing Listing Photos at Airbnb Large-scale deep learning models are changing the way we think about images of homes on our platform.

Airbnb 上有很多关于房子的图片, 以便于用户寻找最合适的房间.
除了位置和价格, 列表图片(listing photos) 也是用户选择房间的一个重要因素.
但, 以前往往忽略了该因素, 直到最近才开始关注这些重要的列表图片.
当用于浏览房子的列表图片时, 我们无法提供一种帮助他们寻找最感兴趣的图片, 以确保图片所传达的信息是准确的, 提高图片的吸引力.

随着 CV 和 DL 技术的快速发展, 现在针对该问题, 我们可以在一定程度上进行应用.
首先关注的问题是将列表图片分类为不同的房间类型.
这样做的好处是, (1) - 归类相同房间类型图片, 可以使旅行更简单;(2) 更易于管理特定房间的数量, 并检测基本的房间信息的正确性.

<h2>1. 图像分类</h2>

对给定列表图片进行正确的房间类型分类, 有助于提升用户体验.
对用户来说, 基于不同房间类型归类后的列表图片, 重新排列组合, 更有助于寻找感兴趣的点.
对房主来说, 有助于 Airbnb 自动的检查列表图片, 以确保上传的图片能够符合平台的高标准.
精确的图片分类, 是关键.

在这里, 待分类的房间列表图片类型有:

Bedrooms, Bathrooms, Living Rooms, Kitchens, Swimming Pools, Views

房间类型分类问题, 与 ImageNet 分类问题十分相似, 除了待处理图片类型是定制的房间类型room-types.
因此, 不可以采用 VGG, ResNet 和 Inception 等 DNN 模型直接来应用.
但, 现在有很多博文介绍了如何处理这样的问题.

  • [1] 修改 DNN 网络的最后几层, 以匹配输出的 dim 与房间类型数量.
  • [2] 重新训练 DNN 网络, 以达到希望的精度.

在测试很不同的 DNN 网络结构后, 我们选择 ResNet50. 其具有模型精度和计算效率更好的平衡.
我们新添加了两个全连接层FC 和一个 Softmax 激活层. 进行了不同训练参数的实验.

<h2>2. Re-train 修改后的 ResNet50</h2>

三种训练方案:

  • [1] 固定基础的 ResNet50 模型, 采用少量数据, 只重新训练新增的两个 FC 层. 即, 一般被称为 fine-tuning.
  • [2] 类似于 [1] 进行 fine-tuning, 但采用更多的数据.
  • [3] 从零开始重新训练整个修改后的 ResNet50.

网络上很多材料大部分采用训练方案[1], 因为其速度快, 且一般都能得到理想的结果. 我们测试了第一种方案, 确实取得了合理的初始结果. 但, 为了得到更高质量的图片产品, 需要进一步显著提高模型表现 -- 理想的要求结果为: 95%+ 精度precision, 80%+ 召回率recall.

为了同时却的高精度和高召回率, 不可避免地需要使用大量的数据重新训练 DNN 模型.
但是, 面临两个主要的挑战:

  • [1] 即使房主已经上传了大量的列表图片, 但缺少与之相关联的房间类型标签room-types.
  • [2] 重新训练类似于 ResNet50 的 DNN 模型是非常复杂的 non-trivial , 其有超过 2,500,000 的待训练参数量, 需要大量的 GPU 支持.

以下分别讨论这两个挑战, 并解决.

<h3>2.1 图像标注</h3>

很多公司采用第三方外包服务来获取图像数据高质量的标注标签. 这显然不是最经济的解决方案, 因为有大量的图片待标注.
为了平衡成本和绩效, 我们采用一种混合方式来进行图片标注.
[1] 采用第三方来标注相对少量的图片, 一般是几千或几万张图片. 这些标注数据随机采样一部分来作为评估模型的重要数据集, 确保这部分数据集的准确性.
[2] 采用房主创建的图片描述(image caption) 来作为房间类型的辅助信息, 并从中提取房间类型标签. 这种方式是非常重要的, 能够有效的避免大量的不可避免的标注任务. 我们只需要判断正确与否的方式, 来确保从图片描述中提取的房间类型标签的准确性和可靠性.

从图片描述中提取房间类型标签, 一种尝试性的方式, 如

如果在图片描述中包含某个房间类型关键词, 则该图片被标注为此房间类型.

但是, 真实场景中, 情况往往更复杂. 如果直接采用这种规则方式, 可能会不甚理想.
我们发现大量的图片描述与真实的图片内容相差很大.例如:

为了滤除差的标注样例, 我们增加了额外的规则. 经过几轮的过滤与检查, 标签质量显著提高. 例如, 过滤 Kitchen 数据以得到相对干净的 Kitchen 图片:

AND LOWER(caption) like '%kitchen%'
AND LENGTH(caption) <= 22
AND LOWER(caption) NOT LIKE '%bed%'
AND LOWER(caption) NOT LIKE '%bath%'
AND LOWER(caption) NOT LIKE '%pool%'
AND LOWER(caption) NOT LIKE '%living%'
AND LOWER(caption) NOT LIKE '%view%'
AND LOWER(caption) NOT LIKE '%door%'
AND LOWER(caption) NOT LIKE '%table%'
AND LOWER(caption) NOT LIKE '%deck%'
AND LOWER(caption) NOT LIKE '%cabinet%'
AND LOWER(caption) NOT LIKE '%entrance%'

数据过滤处理后, 会丢弃大量的图片数据. 但对于我们而言,这是允许的. 因为即使过滤了很多,仍然可以得到上百万的图片, 每一类房间类型有几十万的图片. 而且,得到的图片的标签质量大大提高.
这里,假设数据过滤前后,其数据分布不发生偏移. 可以在人工标注的数据集上得到的模型上进行验证.

也可以采用 NLP 技术来动态的聚类图片描述,而不是采用定义规则的方式. 不过,这里是基于规则的,后续考虑采用 NLP 技术.

<h3>2.2 模型构建与评价</h3>

重新训练类似于 ResNet50 的 DNN 网络,采用上百万的图片数据,需要大量的计算资源.
这里的实现,采用显卡为 8 块 K80 GPU 的 AWS P2.8 实例,每一次训练在 8 块 GPUs 上的 batchsize 设为 128 张图片.
采用 Tensorflow 作为后端并行训练. 并行化之后,再组合模型.
为了进一步加速训练, 采用 ImageNet 上预训练的模型权重来初始化 -- keras.applications.resnet50.ResNet50.
最好的模型是在训练了 3 个 epoch 之后得到,至少花费了 6 个小时.
模型开始过拟合时,模型在验证集上的表现开始停止提升.

重要的一点是,采用的是对不同房间类型的多个二值分类模型(multiple binary-class models),而非全部房间类型的单个多类别模型(multi-class model).
虽然这不是最理想的,但由于我们的模型大部分是离线的offline,多模型所造成的额外延迟影响很小. 未来会转换为多类别模型.

基于 Precision 和 Recall 来评估模型表现. 同时也采用了 F1 和精度Accuracy 等度量方式. 其定义如下图:

Precision 描述了预测结果为 positive 的精度.
Recall 描述了预测结果为 positive 所占真实为 positive 的样本的比例.
二者一般是互斥的.
这里设定的目标是:
Precision 95%+ - 确保房间类型正确分类.

混淆矩阵是计算这些度量的关键.
模型的输出是每张图片 [0, 1] 之间的概率值.
为了计算预测数据集的混淆矩阵,需要首先设定一个阈值,来将[0,1] 之间的概率值转化为 0 和 1.
然后生成 Precision-Recell(PR) 曲线.
RP 曲线的 AUC(Aera Under Curve) 越接近于 1, 模型越准确.

评估模型时,采用的是从人工标注的数据集中筛选出来的部分.
有意思的是,不同房间类型的准确度是不一样的.
Bedroom 和 Bathroom 的模型表现更准确;但其它房间类型的模型表现准确度低一点.
简洁起见,这里只给出 Bedroom 和 Livingroom 模型的 PR 曲线.
其中虚线的交叉点表示给定阈值的最终模型表现情况.

有两个重要的发现:
[1] - Bedroom 模型的整体表现比 Living Room 更优. 其原因可能是:

(a) Bedroom 比 Living Room 更容易分类,因为 Bedroom 的布置相对更标准,而 Living Room 布置变化较多.
(b) Bedroom 图片数据集的标签质量更好. 因为 Living Room 图片可能包含 Dining Rooms 甚至 Kitchens.

[2] - 每种房间类型,完全重新训练模型(红色曲线) 比部分重新训练模型(蓝色曲线) 表现更好. 而且,在 Living Room 模型上的差别程度大于在 Bedroom 模型上的差别程度. 这表明了,完全重新训练 ResNet50 模型对于不同的房间类型具有不同的影响.

尝试的 6 个模型而言,Precision 一般都在 95% 以上,Recall 通常在 50% 以上.
通过设定不同的阈值,可以取得平衡.
该模型在 Airbnb 内部被多个产品团队的多款产品所应用.

用户对比我们的结果和有名的第三方图片识别 APIs 结果,发现,in-hounse 模型的整体表现优于第三方通用模型.
即意味着,基于自己的数据特点,我们都是有机会在某个感兴趣的特定任务取得比第三方更优秀表现的模型.

下面给出几个模型测试实例.


<h2>3. 图像分类之外</h2>

进行该项目时,我们还尝试了除了房间类型分类之外的有意思的想法.
下面给出两个例子,并展示这些问题是多么有趣.

<h3>3.1 无监督场景分类</h3>

刚开始尝试基于预训练 ResNet50 进行房间类型分类时,我们生成了列表封面图片的图片嵌入向量( 2048x1 向量).
为了解释这些嵌入向量的表示,我们将长向量采用 PCA 投影到了 2D 平面.
令我们惊讶的是, 投影数据被自然的分为两组.
分析这两个聚类,我们发现,左边组几乎完全是室内场景indoor,右边组几乎完全是室外场景outdoor.
也就是说,在完全没有任何预训练的情况下,只需要在图片嵌入的第一主成分设置一个切割线,就可以判别室内和室外场景.
这个发现,对于某些真实有意思的领域,如迁移学习,无监督学习,打开了一扇大门.

<h3>3.2 目标检测</h3>

另外一个尝试的是目标检测.
Open Images Dataset 上预训练的 Faster R-CNN 模型已经取得了不错的结果.
如下面的例示,该模型可以检测 Window,Door,Dining Table 以及他们的位置.
采用 Tensorcow Object Detection API, 我们在列表图片上进行了一些快速评估.
采用现成的模型,可以检测许多房间物体.
我们计划采用 Airbnb 的数据集来重新 Faster R-CNN 模型.
采用目标检测算法,可以验证房主所上传的列表图片的质量,并便于用户找到特地元素的房间. 这将 Airbnb 的图片智能推向更高的层次.

<h2>4. 总结</h2>

这里列出可能有助于深度学习开发的一些关键点:

[1] - 深度学习是一种监督学习. 不可以过高估计数据标签高质量的重要性.

由于深度学习往往需要大量数据来达到很好的表现,因此,有效的数据打标方式是很重要的.
幸运的是,我们采用的混合方式是经济、稳定、可靠的.

[2] - 从头训练类似于 ResNet50 的 DNN 网络确实是比较复杂的. 尝试从简单快速的方式入手 —— 只在小数据集上训练某几个输出层. 如果有大规模可用的训练数据,从头训练 DNN 模型可能得到更优的模型表现.

[3] - 如果条件允许,就选择并行训练. 我们采用 8 块 GPUs 获得了 6x 倍的加速(近似线性). 这对于构建复杂 DNN 模型的计算更可行,且更容易迭代优化到好的模型结构和模型超参数.

Last modification:October 9th, 2018 at 09:31 am