摘要: 还在为搜索引擎的工做原理感到困惑吗?看完本篇就能够本身动手构建搜图服务了。
一张图片赛过千言万语,甚至N行代码。网友们常用的一句留言是,no picture, you say nothing。随着生活节奏的加快,人们愈来愈没有耐心和时间去看大段的文字,更喜欢具备视觉冲击性的内容,好比,图片,视频等,由于其所含的内容更加生动直观。数据库
许多产品是在外观上吸引到咱们的目光,好比在浏览购物网站上的商品、寻找民宿上的房间租赁等,看起来怎么样每每是咱们决定购买的重要因素。感知事物的方式能强有力预测出咱们想要的东西是什么,所以,这对于评测而言是一个有价值的因素。网络
然而,让计算机以人类的方式理解图像已经成为计算机科学的挑战,且已持续一段时间了。自2012年以来,深度学习在图像分类或物体检测等感知任务中的效果慢慢开始超越或碾压经典方法,如直方梯度图(HOG)。致使这种转变的主要缘由之一是,深度学习在足够大的数据集上训练时,可以自动地提取有意义的特征表示。架构
这就是为何许多团队,好比Pinterest、StitchFix和Flickr 都开始使用深度学习来学习图像特征,并基于用户认为视觉上使人愉悦的内容提供推荐。一样,Insight的研究员也使用深度学习为应用程序创建模型,例如推荐购买太阳镜以及寻找艺术风格等。机器学习
目前,许多的推荐系统都是基于协同过滤(collaboratiove filtering):利用用户关联来提出建议(即,假设喜欢你喜欢的东西的用户也会喜欢”)。可是,这些基于协同过滤的模型须要大量数据,其效果才能准确,而且难以处理还没有被任何人查看过的新内容。若是将内容表示应用于基于内容的推荐系统中,那么该系统不会遇到上述问题。函数
此外,这些表示还容许消费者高效地搜索照片库,以寻找到与他们刚刚拍摄的自拍(经过图像查询)类似的图像,或者用于特定物品(经过文本查询)的照片,这方面的常见示例包括关键字搜图以及以图搜图功能。学习
根据咱们多年语义理解项目的技术经验,但愿编写一个教程,介绍如何构建本身的特征表示,包括图像和文本数据,以及如何有效地进行类似性搜索。但愿看完本文,读者可以对任意大小的数据不管数据集的大小如何,都可以从头开始构建出一个快速语义搜索模型。优化
聊聊优化网站
在机器学习中,就像在软件工程中同样,有不少方法能够解决同一个问题,但每种方法都有不一样的权衡及侧重点。若是是正在进行研究或本地原型设计,就能够摆脱效率很是低的解决方案。可是,若是是要构建一个须要可维护和可扩展的图像类似性搜索引擎,则必须考虑如何适应数据演变以及模型运行的速度。搜索引擎
下面让咱们思考一些方法:spa
在方法1中,咱们构建了一个端到端模型,该模型在全部的图像上进行训练,将图像做为输入,并输出全部图像的类似度得分。预测过程耗时很短(一次前向传播过程便可),可是,当每次添加新图像时,咱们都须要从新训练获得一个新模型。此外,当类别多的时候,也会很难正确地优化它。这种方法虽然看起来很简单且预测过程很快,可是不可以扩展到大型的数据集。此外,咱们还必须手动标记数据集与图像的类似性,这个过程可能很是耗时。
在方法2中,构建一个接收两个图像的模型,并输出0到1之间的成对类似得分(例如,孪生网络Siamese Networks)。这些模型对于大型数据集是准确的,但会另外致使一个可伸缩性问题。咱们一般但愿经过查看大量图像来查找类似的图像,所以咱们必须为数据集中的每一个图像对都运行一次类似度模型。若是模型采用的是CNN网络,而且有十几个图像时,那么这个过程就很是慢了。此外,这个方法仅适用于图像类似性搜索,而不适用于文本搜索。虽然此方法可扩展到大型数据集,但运行速度很慢。
方法3是一种更简单的方法,相似于字嵌入。若是找到一个富有表现力的矢量表示或嵌入图像,就能够经过观察矢量彼此之间的距离来计算类似性。这种类型的搜索是深刻研究的常见问题,许多库都实现了快速解决方案(本文使用Annoy)。此外,提早计算出数据库中全部图像的矢量,这种方法既快速(一次正向传递就是一种有效的类似性搜索),又能够进行扩展。最后,若是咱们设法为图像和单词找到常见的嵌入,就可使用它们来进行文本到图像的搜索!因为其简单性和高效性,第三种方法做为本文的实现方法。
那么,如何实际使用深度学习表示来建立搜索引擎呢?咱们的最终目标是拥有一个搜索引擎,能够接收图像并输出类似的图像或标签,还能接收文本并输出相似的单词或图像。为了实现这一目标,将经历三个连续的步骤:
一、根据输入图像搜索相似图像(图像→图像)
二、根据输入词搜索相似的单词(文本→文本)
三、为图像生成标签,并使用文本搜索图像(图像↔文本)
为此,将使用嵌入、图像和文本的矢量表示。一旦有了嵌入,搜索过程就转变为只需找到靠近输入矢量的矢量。咱们采用的方法是计算图像嵌入和其余图像嵌入之间的余弦类似度。相似的图像将具备相似的嵌入,意味着嵌入之间具备高余弦类似性。
下面从数据集开始实验。
图像
图像数据集由1000张图像组成,分为20个类别,每类图像包含50个图像。该数据集可在此处找到,此数据集包含每一个图像的类别和一组说明。为了使这个问题的难度更高,而且为了代表本方法的归纳性,本文只使用了类别,而忽略说明。总共有20个类别,以下所示:
aeroplane bicycle bird boat bottle bus car cat chair cow dining_table dog horse motorbike person potted_plant sheep sofa train tv_monitor
从上图中能够看到,标签很是嘈杂:许多图像都包含多个类别,图像的标签并不老是来自最突出的内容。例如,在右下方,图像被标记为chair(椅子)而不是person(人),而该图的中心是有3我的,且几乎看不见椅子。
此外,加载已在Wikipedia上预训练的单词嵌入(本文使用GloVe模型中的单词嵌入),使用这些向量将文本合并到语义搜索中。
如今要加载一个在大型数据集(Imagenet)上预先训练过的模型,而且能够在线免费获取。本文使用VGG16网络为图像生成嵌入,注意,这里本文采用的方法适用于任何最新的CNN架构(不局限于VGG16)。
生成嵌入是什么意思?咱们将使用预先训练模型倒数第二层前的网络结构,并存储对应的权重值。在下图中,用绿色突出显示表示嵌入层,该嵌入层位于最终分类层以前。
一旦使用该模型生成图像特征,就能够将其存储到磁盘中,从新使用时无需再次进行推理!这也是嵌入在实际应用中如此受欢迎的缘由之一,由于能够大幅提高效率。除了将它们存储到磁盘以外,还将使用Annoy构建嵌入的快速索引,这将容许咱们很是快速地找到任何给定嵌入的最近嵌入。
如下是本文获得的嵌入。如今每一个图像都由一个大小为4096的稀疏向量表示。注意:向量稀疏的缘由是在激活函数以后将负数归零。
如今能够简单地接收图像,得到其嵌入后,并查看快速索引以查找相似的嵌入,从而找到相似的图像。这是特别有用的,由于图像标签一般很嘈杂,且图像比标签更多。例如,在数据集中,有一个类别cat(猫)和一个类别bottle(瓶子)。您认为下面这张图片会被标记为哪一个类别?
正确的答案是瓶子,这是一个常常在真实数据集中出现的实际问题。将图像标记为惟一类别是很是受限的,这就是为何但愿使用更细粒的表示。幸运的是,这也正是深度学习所擅长的!下面看看使用嵌入的图像搜索是否比经过人为标记的更好。
搜索类似的图片todataset / bottle / 2008_000112.jpg,能够看见该图像位于bottle(瓶子)类别。
结果出人意料的好,搜索获得不少猫的图像,而不是瓶子的图像,这看起来很合理!因为预训练网络的训练集中包含各种图像,这样包括猫,所以它可以准确地找到类似的图像,即便它以前从未接受过本文选定数据集的训练。
可是,最下面一行中间的一幅图像显示了一个瓶架。通常而言,这种方法执行后找到相似的图像,但有时咱们只对图像的一部分感兴趣。
例如,给定一张包含猫和瓶子的图像,咱们可能只对和猫相似的图像感兴趣,而不是瓶子。
本文做者:【方向】
本文为云栖社区原创内容,未经容许不得转载。