Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >教程 | 如何通过距离度量学习解决Street-to-Shop问题

教程 | 如何通过距离度量学习解决Street-to-Shop问题

作者头像
机器之心
发布于 2018-05-11 05:31:15
发布于 2018-05-11 05:31:15
87900
代码可运行
举报
文章被收录于专栏:机器之心机器之心
运行总次数:0
代码可运行

选自Medium

作者:Aleksandr Movchan

机器之心编译

参与:Nurhachu Null、黄小天

本文将向你介绍用机器学习解决街道到商店 (street-to-shop) 问题的流程:如何从用户图像中识别衣服,并从网上商店找到它。你可曾有过这样的经历,在大街上看到某个人,然后不禁感叹,「哇哦,多么漂亮的衣服,我在哪里能买到它呢?」本文作者虽然没有过这样的经历,但是对其而言,尝试使用距离度量学习技术是一项很酷的任务。希望你也会觉得这很有趣。

数据集

首先,我们需要数据集。实际上,当我发现 Aliexpress 上有很多用户图像的时候我就有了这个想法。我心里想,「哇,我可以通过使用这种数据来搜索,当然是仅仅为了有趣」。为了简便,我决定重点关注女装。

下面是我所使用的类别:

  • 连衣裙
  • 衬衣&衬衫
  • 卫衣和运动衫
  • 夹克和外套

我使用 requests(https://pypi.python.org/pypi/requests)和 beautifualSoup(https://pypi.python.org/pypi/beautifulsoup4)来爬取图像。卖家的图像可从商品页面上获得,但是为了得到用户图像,我们需要浏览反馈页面。在商品页面上有一个叫做「colors」的属性,指的是另一种不同的颜色或者甚至是另一件商品,所以我们需要将不同颜色的衣服视为不同的商品。

商品页面上的「颜色」

你可以在 github 上找到我用来得到关于一件服饰的所有信息的代码(https://github.com/movchan74/street_to_shop_experiments/blob/master/get_item_info.py)(它爬取到的信息甚至比我们任务中需要的信息还要多)。

我们需要做的就是通过每一个类别取浏览对应的页面,拿到所有商品的 URL,然后使用上面提到的函数取得有关每个商品的信息。

最终,我们得到了每个商品的两个图片集合:来自于卖家的图片(商品页面上每个「colors」对应的元素)以及来自于用户的图片(商品页面上每个「feedbacks」对应的元素)。

对于每个 color,我们只有一张卖家图片,但是可能具有多于一个的用户图像 (然而有时候根本没有用户图像)。

很棒现在我们有数据了。然而得到的数据集有噪声:

  • 用户图像中含有噪声(包裹箱子的照片,商品中一些无关区域的照片,以及刚拆开包装的照片)。

用户数据中的噪声示例

为了减轻这个问题,我们给 5000 张图像打了两种不同类别的标签:好图片和噪声图片。起初,我计划训练一个分类器来清洗数据集。但是后来我决定将数据清洗分类器这项工作留在后面,仅仅将干净的数据用在测试集和验证集中。

  • 第二个问题是,一些商品有好几个卖家。这些卖家有时候甚至用的是相同图像(经过轻微编辑)。那么如何处理这个问题呢?最简单的方法就是对数据不做任何处理,使用一个鲁棒的距离度量学习算法。但是这会影响到验证,因为在这种情况下,我们在验证数据和训练数据中有相同的商品。因此这就造成了数据泄露。另一种方式就是使用某种方法来寻找相似的(甚至完全相同的)商品,并将其合并。我们可以使用感知哈希来寻找相同的图像(例如 phash 和 whash)。或者我们可以在噪声数据集上训练一个模型来寻找相似的图像。我选择了后者,因为这种方法可以合并经过轻微编辑的图像。

距离度量学习

最常用的距离度量算法之一就是 triplet loss:

其中,max(x, 0) 是 hinge 函数,d(x, y) 是 x 和 y 之间的距离函数。F(x) 是一个深度神经网络,M 是边际,a 是 anchor,p 是正例点,n 是反例点。

F(a), F(p), F(n) 都是由深度神经网络产生的高维空间中的向量。值得提及的是,为了让模型应对对照变化的时候更加鲁棒以及训练过程中具有更好的稳定性,这些向量需进行正则化处理,以拥有相同的长度,例如||x|| = 1。anchor 和正例样本属于同一类别,反例点属于其他类别。

所以 triplet loss 的主要思想就是使用一个距离边际 M 来区分正例对(anchor 和 positive)的向量。

但是如何选择元组 (a, p, n) 呢?我们可以随机选择一个 triplet,但是这样会导致以下问题。首先,存在 N³种可能的 triplet。这意味着我们需要花费很多时间来遍历所有可能的 triplet。但是实际上我们没必要这么做,因为经过少数几次的训练迭代之后,很多元 triplet 已经符合 triplet 限制(例如 0 损失)。这意味着这些 triplet 在训练中是没用的。

最常用的 triplet 选择的方式就是 hard negative mining:

实际上,选择最严格的负样本会在训练早期导致糟糕的局部最小值。尤其是,它能够导致一个收缩的模型(例如 F(x) = 0)),为了缓解这个问题,我们使用 semi-hard negative mining(半严格负样本最小化)。

半严格负样本要比 anchor 离正样本更加远,但是它们仍然是严格的(违背了 triplet 限制),因为它们在边际 M 内部。

半严格负样本的 triplet 的限制条件

下面是生成半严格和严格负样本的两种方式:在线和离线。

  • 在线方式意味着我们从数据集中随机地选择样本作为一个 mini-batch,并从这个 Mini-batch 中选择 triplet。然而,在线方法需要一个较大的 mini-batch。在我的情况中是不可能的,因为我只有一块具有 8GB 显存的 GTX 1070。
  • 在离线方式中,我们需要在一段时间之后停止训练,为一定数量的样本预测向量,从中选择 triplet 并为这些 triplet 训练模型。这意味着我们要进行两次,然而这就是离线方法的代价。

好了,现在我们可以开始用 triplet loss 和离线半严格负样本最小化来训练模型了。但是,为了成功地解决 street-to-shop 问题,我们还需要一个技巧。我们面临的任务是找到与用户照片最相似的卖家图像。然而,通常卖家的图像具有更高的质量,所以我们有两个域:卖家图像和用户图像。为了得到更有效的模型,我们需要减小这两个域之间的差距。这个问题就叫做域适应。

左边是用户的图像;右边是卖家的图像

我想出了一个非常简单的方法来减少这种域差距:我们在卖家图像中选择 anchor,从用户图像中选择正例样本和负例样本。这个方法简单有效。

实现

为了实现我的想法并快速实验,我使用了基于 TensorFlow 的 Keras 库。

我选择 inception V3 作为模型的基本卷积网络。像往常一样我使用 ImageNet 权重初始化卷积神经网络。我在使用 L2 正则化的全局池化之后又加了两个全连接层,向量的维度是 128。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def get_model():
    no_top_model = InceptionV3(include_top=False, weights='imagenet', pooling='avg')

    x = no_top_model.output
    x = Dense(512, activation='elu', name='fc1')(x)
    x = Dense(128, name='fc2')(x)
    x = Lambda(lambda x: K.l2_normalize(x, axis=1), name='l2_norm')(x)
    return Model(no_top_model.inputs, x)

我们还需要实现 triple 损失函数。我们传递一个 anchor,正样本和负样本作为一个 mini-batch,在损失函数中将其分为三个张量。距离函数就是欧氏距离的平方。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def margin_triplet_loss(y_true, y_pred, margin, batch_size):
    out_a = tf.gather(y_pred, tf.range(0, batch_size, 3))
    out_p = tf.gather(y_pred, tf.range(1, batch_size, 3))
    out_n = tf.gather(y_pred, tf.range(2, batch_size, 3))

    loss = K.maximum(margin
                 + K.sum(K.square(out_a-out_p), axis=1)
                 - K.sum(K.square(out_a-out_n), axis=1),
                 0.0)
    return K.mean(loss)

并优化模型:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#utility function to freeze some portion of a function's arguments
from functools import partial, update_wrapper
def wrapped_partial(func, *args, **kwargs):
    partial_func = partial(func, *args, **kwargs)
    update_wrapper(partial_func, func)
    return partial_func

opt = keras.optimizers.Adam(lr=0.0001)
model.compile(loss=wrapped_partial(margin_triplet_loss, margin=margin, batch_size=batch_size), optimizer=opt)

实验结果

结果:第一列-查询(用户图像),后五列-最相似的卖家图像。

性能衡量指标是 R@K。

我们来看一下 R@K 是如何计算的。验证集里面的每张用户图像作为一次查询,我们需要找到对应的卖家图像。我们不仅使用了验证集中的卖家图像,还使用了训练集中的图像,因为这样可以使我们增加干扰数量,使得我们的任务更加具有挑战性。

所以我们就有一张查询图像,以及一些很相似的卖家图像。如果在 K 个最相似的图像中有对应的卖家数据,我们就返回 1,否则就返回 0。现在我们需要为验证集中的每一次查询返回这么一个结果,然后找到每次查询的平均得分。这就是 R@K。

正如我之前讲到的,我从噪声图像中清洗了一部分用户图像。所以我在两个验证集上衡量了一下模型的质量:完整的验证集只包含干净数据的子验证集。

验证数据中的 R@K

结果距离理想情况还很远,还有很多需要做:

  • 从噪声数据中清洗用户图像。我在第一步中已经做了一部分。
  • 更加准确地合并相似的图像(至少在验证集中)。
  • 降低域差距。假设可以通过特定域增强的方法(例如亮度增强)以及其他特定的方法完成(例如这篇论文中的方法 https://arxiv.org/abs/1409.7495)。
  • 应用其他的距离指标学习技术。我试了这篇论文中的方法(https://arxiv.org/abs/1703.07464),但是比我所用的方法性能要差一些。
  • 当然,要收集更多的数据。

DEMO,代码和训练好的模型

我做了一个 demo。你可以在这里看到 vps389544.ovh.net:5555。你可以上传你自己的图像或者随便使用验证集中的图像来搜索。

代码和训练好的模型在这里:https://github.com/movchan74/street_to_shop_experiments。

本文为机器之心编译,转载请联系本公众号获得授权。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-02-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 机器之心 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
孪生网络入门(上) Siamese Net及其损失函数
最近在多个关键词(小数据集,无监督半监督,图像分割,SOTA模型)的范畴内,都看到了这样的一个概念,孪生网络,所以今天有空大概翻看了一下相关的经典论文和博文,之后做了一个简单的案例来强化理解。
huofo
2022/03/17
9460
孪生网络入门(上) Siamese Net及其损失函数
图解人脸识别算法facenet系列(一)
代码地址:https://github.com/davidsandberg/facenet
算法发
2020/08/03
2.6K0
图解人脸识别算法facenet系列(一)
度量学习:使用多类N对损失改进深度度量学习
度量学习是ReID任务中常用的方式之一,今天来看下一篇关于如何改进度量学习的论文。来自2016年NeurIPS上的一篇论文,被引用超过900次。
码科智能
2023/10/17
1.3K0
度量学习:使用多类N对损失改进深度度量学习
深度学习人脸识别核心技术—框架和优化目标
注:本文选自人脸图像资深工程师言有三出版的新书《深度学习之人脸图像处理:核心算法与案例实战》(机械工业出版社出版)的6.2节,略有改动。经授权刊登于此。
CV君
2020/08/11
1.2K0
CCKS 2020「基于标题的大规模商品实体检索」竞赛冠军,DeepBlueAI团队技术分享
第十四届全国知识图谱与语义计算大会(CCKS 2020) 11 月 12 日至 15 日在江西南昌举行,CCKS(China Conference on Knowledge Graph and Semantic Computing)是由中国中文信息学会语言与知识计算专委会定期举办的全国年度学术会议。CCKS 已经成为国内知识图谱、语义技术、语言理解和知识计算等领域的核心会议。CCKS 2020 举办的各项挑战赛公布了最终结果,来自深兰科技北京 AI 研发中心的 DeepBlueAI 团队斩获了 3 项冠军和 1 项亚军,并获得了一项技术创新奖。
机器之心
2020/11/20
9320
CCKS 2020「基于标题的大规模商品实体检索」竞赛冠军,DeepBlueAI团队技术分享
对比学习在有赞的应用
一般做算法任务时,都需要搜集大量标注的数据,假如我们要预测一个商品的产品词(中心词),下面是一个商品标题:
有赞coder
2022/09/08
8710
Muti-Similarity Loss:考虑了batch中整体距离分布的对比损失函数
这是对比损失函数的一种变体,不再是使用绝对距离,还要考虑batch中其他样本对的整体距离分布来对损失进行加权,大家可以试试。
石晓文
2020/10/09
2K1
Muti-Similarity Loss:考虑了batch中整体距离分布的对比损失函数
利用Contrastive Loss(对比损失)思想设计自己的loss function
来源:PaperWeekly本文约4500字,建议阅读9分钟该损失函数主要是用于降维中,即本来相似的样本,在经过降维(特征提取)后,在特征空间中,两个样本仍旧相似。 1、Contrastive Loss简介 对比损失在非监督学习中应用很广泛。最早源于 2006 年Yann LeCun的“Dimensionality Reduction by Learning an Invariant Mapping”,该损失函数主要是用于降维中,即本来相似的样本,在经过降维(特征提取)后,在特征空间中,两个样本仍旧相似;而
数据派THU
2023/04/12
3.9K0
利用Contrastive Loss(对比损失)思想设计自己的loss function
如何训练孪生神经网络
使用机器学习训练时,如果想训练出精确和健壮的模型需要大量的数据。但当训练模型用于需要自定义数据集的目的时,您通常需要在模型所看到的数据量级上做出妥协。
deephub
2021/05/18
1.6K0
如何训练孪生神经网络
TensorFlow2.X学习笔记(7)--TensorFlow中阶API之losses、metrics、optimizers、callbacks
一般来说,监督学习的目标函数由损失函数和正则化项组成。(Objective = Loss + Regularization)
MiChong
2020/09/24
1.8K1
论文阅读理解 - Deep Metric Learning via Lifted Structured Feature Embedding
度量学习和降维技术,旨在学习语义距离度量和嵌入,以使相似的样本被映射为流形中邻近点,不相似的样本被映射为距离较远的点.
AIHGF
2019/02/18
1.2K0
大厂技术实现 | 图像检索及其在淘宝的应用 @计算机视觉系列
图像检索任务指的是,给定查询图像,从图像数据库中找到包含相同或相似实例的图像。典型应用之一就是电商商品检索,如淘宝拍立淘,只需要用户随手拍照即可精准检索,提高了电商购物的体验。本篇我们来看看淘宝拍立淘背后的实现方案和依托的计算机视觉技术。
ShowMeAI
2021/11/24
3K0
大厂技术实现 | 图像检索及其在淘宝的应用 @计算机视觉系列
深度学习+度量学习的综述
如今,机器学习的应用广泛,包括人脸识别、医疗诊断等,为复杂问题和大量数据提供解决方案。机器学习算法能基于数据产生成功的分类模型,但每个数据都有其问题,需定义区别特征进行正确分类。常用的机器学习算法包括k最近邻、支持向量机和朴素贝叶斯分类器,但需注意特征加权和数据转换。
算法进阶
2024/04/12
7070
深度学习+度量学习的综述
对比学习(Contrastive Learning)在CV与NLP领域中的研究进展
目前NLP领域的经验,自监督预训练使用的数据量越大,模型越复杂,那么模型能够吸收的知识越多,对下游任务效果来说越好。这可能是自从Bert出现以来,一再被反复证明。
对白
2022/04/01
9370
对比学习(Contrastive Learning)在CV与NLP领域中的研究进展
【损失函数合集】Yann Lecun的Contrastive Loss 和 Google的Triplet Loss
昨天在介绍Center Loss的时候提到了这两个损失函数,今天就来介绍一下。Contrastive Loss是来自Yann LeCun的论文Dimensionality Reduction by Learning an Invariant Mapping,目的是增大分类器的类间差异。而Triplet Loss是在FaceNet论文中的提出来的,原文名字为:FaceNet: A Unified Embedding for Face Recognition and Clustering,是对Contrastive Loss的改进。接下来就一起来看看这两个损失函数。论文原文均见附录。
BBuf
2020/02/14
2.6K0
【损失函数合集】Yann Lecun的Contrastive Loss 和 Google的Triplet Loss
一文教你在Python中打造你自己专属的面部识别系统
人脸识别是用户身份验证的最新趋势。苹果推出的新一代iPhone X使用面部识别技术来验证用户身份。百度也在使“刷脸”的方式允许员工进入办公室。对于很多人来说,这些应用程序有一种魔力。但在这篇文章中,我们的目的是通过教你如何在Python中制作你自己的面部识别系统的简化版本来揭开这个主题的神秘性。 Github库代码:https://github.com/Skuldur/facenet-face-recognition 背景 在讨论实现的细节之前,我想讨论FaceNet的细节,它是我们将在我们的系统中使用的网
AiTechYun
2018/03/02
1.2K0
一文教你在Python中打造你自己专属的面部识别系统
对比表示学习必知的几种训练目标
对比学习的主要思想就是相似的样本的向量距离要近,不相似的要远.对比学习在有监督/无监督场景下都取得了非常亮眼的成绩,所以是我们炼丹的必备知识.早期的对比学习是只有一个正样本和一个负样本进行对比,最近的训练目标变成了一个batch内多个正/负样本进行训练.
炼丹笔记
2022/04/06
8210
对比表示学习必知的几种训练目标
孪生网络入门(上) Siamese Net及其损失函数
以这个孪生网络入门,我想着分成上下两篇,上篇也就是这一篇讲解模型理论、基础知识和孪生网络独特的损失函数;下篇讲解一下如何用代码来复线一个简单的孪生网络。
机器学习炼丹术
2020/12/16
8.7K0
飞桨带你使用度量学习,提升人脸识别准确率
想必在日常生活中,我们总会有一种感觉,身边认识的一些人,明明没有任何血缘关系,但是长得却可能很像,尤其对于脸盲的同学,真的是傻傻分不清楚。
用户1386409
2019/07/02
1.4K0
神经网络中的损失函数
在《神经网络中常见的激活函数》一文中对激活函数进行了回顾,下图是激活函数的一个子集——
半吊子全栈工匠
2023/09/02
1.8K0
神经网络中的损失函数
推荐阅读
相关推荐
孪生网络入门(上) Siamese Net及其损失函数
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档