如何用Python和深度神经网络寻找近似图片?

给你10万张图片,让你找出与其中某张图片最为近似的10张,你会怎么作?不要轻言放弃,也不用一张张浏览。使用Python,你也能够轻松搞定这个任务。python

疑问

如何用Python和深度神经网络识别图像?》一文写完后,我收到了很多读者的反馈。其中一个很广泛的疑问是:git

识别相同或类似的图像,有什么好的方法么?github

我虽然乐于帮助读者解决问题,但实话实说,一开始不太理解这种需求。浏览器

我文章里的样例图片(哆啦a梦和瓦力),都是从网络搜集来的。若是你须要从网上找到跟某张图片近似的图像,可使用Google的“以图搜图”功能啊。安全

很快,我忽然醒悟过来。bash

这种需求,每每不是为了从互联网上大海捞针,寻找近似图片。而是在一个私有海量图片集合中,找到近似图像。微信

这种图片集合,也许是你团队的科研数据。例如你研究鸟类。某天浏览野外拍摄设备传回来的图像时,忽然发现一个新奇品种。网络

你因而很想搞清楚这种鸟类的出现时间、生活状态等。这就须要从大量图片里,找到与其近似的图片(最有多是拍到了同一种鸟)。app

这种图片集合,也许是社会安全数据。例如你在反恐部门,系统忽然发现某个疑似恐怖分子出如今敏感区域。这家伙每一次现身,都伴随着恶性刑事案件的发生,给人民群众的生命财产安全带来严重威胁。框架

这时候不管对其衣着、外貌仍是交通工具的类似度搜索,就显得相当重要了。

上述例子中,由于你都没有把图像上传到互联网,Google的“以图搜图”引擎功能再强大,也无能为力。

好吧,解决这个问题,颇有意义。

下一个问题天然是:这种需求,解决起来复杂吗?

是否是须要跨过很高的技术门槛才能实现?是否是须要花大量经费雇佣专家才能完成?

本文,我为你展现如何用10几行Python代码,解决这个问题。

数据

为了讲解的方便,咱们依然采用《如何用Python和深度神经网络识别图像?》一文中使用过的哆啦a梦和瓦力图片集合。

我给你准备好了119张哆啦a梦的照片,和80张瓦力的照片。图片已经上传到了这个Github项目

请点击这个连接,下载压缩包。而后在本地解压。做为我们的演示目录

解压后,你会看到目录下有个image文件夹,其中包含两个子目录,分别是doraemon和walle。

doraemon的目录下,都是各式各样的蓝胖子图片。

瓦力目录下的图片是这个样子的:

数据已经有了,下面咱们来准备一下环境配置。

环境

本文中,咱们须要使用到苹果公司的机器学习框架TuriCreate。

请注意TuriCreate发布时间不久,目前支持的操做系统列表以下:

这就意味着,若是你用的操做系统是Windows 7及如下版本,那么目前TuriCreate还不支持。如需使用,有两种办法:

第一种,请升级到Windows 10,而且使用WSL。关于如何使用WSL,我帮你找到了一个中文教程。请按照教程一步步完成安装。

第二种,采用虚拟机。推荐采用Virtualbox虚拟机,开源免费。一样地,我也帮你找到了很详尽的Virtualbox安装Ubuntu Linux的中文教程。你能够参照它安装好Linux。

解决了系统兼容性问题,下面咱们在TuriCreate支持的系统中,安装Python集成运行环境Anaconda。

请到这个网址 下载最新版的Anaconda。下拉页面,找到下载位置。根据你目前使用的系统,网站会自动推荐给你适合的版本下载。我使用的是macOS,下载文件格式为pkg。

下载页面区左侧是Python 3.6版,右侧是2.7版。请选择2.7版本。

双击下载后的pkg文件,根据中文提示一步步安装便可。

装好Anaconda后,咱们安装TuriCreate。

请到你的“终端”下面,进入我们刚刚下载解压后的样例目录。

执行如下命令,咱们来建立一个Anaconda虚拟环境,名字叫作turi。若是你以前跟随我在《如何用Python和深度神经网络识别图像?》一文中创立过这个虚拟环境,此处请跳过。

conda create -n turi python=2.7 anaconda
复制代码

而后,咱们激活turi虚拟环境。

source activate turi
复制代码

在这个环境中,咱们安装(或者升级到)最新版的TuriCreate。

pip install -U turicreate
复制代码

安装完毕后,执行:

jupyter notebook
复制代码

这样就进入到了Jupyter笔记本环境。咱们新建一个Python 2笔记本。

浏览器里出现了一个空白笔记本。

点击左上角笔记本名称,修改成有意义的笔记本名“demo-python-image-similarity”。

准备工做完毕,下面咱们就能够开始编写程序了。

代码

首先,咱们读入TuriCreate软件包。

import turicreate as tc
复制代码

咱们指定图像所在的文件夹image。让TuriCreate读取全部的图像文件,而且存储到data数据框。

data  = tc.image_analysis.load_images('./image/')
复制代码

咱们来看看,data数据框的内容:

data
复制代码

data包含两列信息,第一列是图片的地址,第二列是图片的长宽描述。

下面咱们要求TuriCreate给数据框中每一行添加一个行号。这将做为图片的标记,好在后面查找图片时使用。

data = data.add_row_number()
复制代码

再看看此时的data数据框内容:

data
复制代码

咱们来看看数据框里面的这些信息对应的图片。

data.explore()
复制代码

TuriCreate会弹出一个页面,给咱们展现数据框里面的内容。

把鼠标悬停在某张缩略图上面,就能够看到对应清晰大图。

第一张图片,是哆啦a梦:

第二张图片,是瓦力:

下面,是重头戏。咱们让TuriCreate根据输入的图片集合,创建图像类似度判别模型。

model = tc.image_similarity.create(data)
复制代码

这个语句执行起来,可能须要一些时间。若是你是第一次使用TuriCreate,它可能还须要从网上下载一些数据。请耐心等待。

Resizing images...
Performing feature extraction on resized images...
Completed 199/199
复制代码

注意这里的提示,TuriCreate自动帮咱们作了图片尺寸调整等预处理工做,而且对每一张图片,都作了特征提取。

通过或长或短的等待,模型已经成功创建。

下面,咱们来尝试给模型一张图片,让TuriCreate帮咱们从目前的图片集合里,挑出最为类似的10张来。

为了方便,咱们就选择第一张图片做为查询输入。

咱们利用show()函数展现一下这张图片。

tc.Image(data[0]['path']).show()
复制代码

确认无误,仍是那张哆啦a梦。

下面咱们来查询,咱们让模型寻找出与这张图片最类似的10张。

similar_images = model.query(data[0:1], k=10)
复制代码

很快,系统提示咱们,已经找到了。

咱们把结果存储在了similar_images变量里面,下面咱们来看看其中都有哪些图片。

similar_images
复制代码

返回的结果一共有10行。跟咱们的要求一致。

每一行数据,包含4列。分别是:

  • 查询图片的标记
  • 得到结果的标记
  • 结果图片与查询图片的距离
  • 结果图片与查询图片近似程度排序值

有了这些信息,咱们就能够查看到底哪些图片与输入查询图片最为类似了。

注意其中的第一张结果图片,其实就是咱们的输入图片自己。考虑它没有意义。

咱们提取所有结果图片的标记(索引)值,忽略掉第一张(自身)。

similar_image_index = similar_images['reference_label'][1:]
复制代码

剩余9张图片的标记都在结果中:

similar_image_index
复制代码
dtype: int
Rows: 9
[194, 158, 110, 185, 5, 15, 79, 91, 53]
复制代码

下面咱们但愿TuriCreate可以可视化帮咱们展现这9张图片的内容。

咱们要把上面9张图片的标记在全部图片的索引列表中过滤出来:

filtered_index = data['id'].apply(lambda x : x in similar_image_index)
复制代码

看看过滤后的索引结果:

filtered_index
复制代码
dtype: int
Rows: 199
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, ... ]
复制代码

你能够本身数一数,其中标为1的那些图片位置,和咱们存储在similar_image_index中的数字是否一致。

验证完毕之后,请执行如下语句。咱们再次调用TuriCreate的explore()函数,展示类似度查询结果图片。

data[filtered_index].explore()
复制代码

系统会弹出如下对话框:

咱们能够看到,所有查询结果图片中,只出现了哆啦a梦。瓦力的图片,一张都没有出现。

近似图片查找成功!

随着本文操做样例数据后,你不妨换用本身的数据,来动手尝试一番。

原理

展现了如何用10几行Python代码帮你查找类似图形后,咱们来聊聊这种强大、简洁背后的原理。

若是你对原理不感兴趣,请跳过这一部分,看“小结”。

虽然咱们刚刚只是用了一条语句构建模型:

model = tc.image_similarity.create(data)
复制代码

然而实际上,TuriCreate在后台为咱们作了不少事情。

首先,它调用了一个很是复杂的,在庞大数据集上训练好的模型。

如何用Python和深度神经网络识别图像?》一文中,咱们介绍过,这个模型就是上图中的最后一行。它的名字叫作Resnet-50,足足有50层,训练的图片数以百万计,训练时长也好久。

这里,机智的你必定会问个问题:那些数以百万计的预训练图片里面,是否有哆啦a梦和瓦力呢?

没有。

那就怪了,不是吗?

若是这个复杂的模型以前根本就没有见过哆啦a梦和瓦力,那它怎么知道如何区分它们呢?又怎么可以判别两张哆啦a梦之间的差异,就必定比哆啦a梦和瓦力之间更小呢?

如何用Python和深度神经网络识别图像?》一文里,我已经提示给你一个关键词:迁移学习(transfer learning)。

这里我们就不深刻技术细节了。我只给你在概念层次讲解一下。

还记得这张描述计算机视觉(卷积神经网络)的示意图吗?

在全链接层(Fully Connected Layer)以前,你可能进行了屡次的卷积、抽样、卷积、抽样……这些中间层次,帮咱们描绘了图片的一些基本特征,例如边缘大概是个什么形状,某个区块主要的颜色是哪些等。

到了全链接层,你只剩下了一组数据,这组数据可能很长,它抽取了你输入数据的所有特征。

若是你的输入是一只猫,此时的全链接层里就描述了这只猫的各类信息,例如毛发颜色、面部组成部分排列方式、边缘的形状……

这个模型能够帮你提取猫的特征,但它并不知道“猫”的概念是什么。

你天然能够用它帮你提取一条狗的特征。

同理,哆啦a梦的照片,与猫咪的照片同样,都是二维图片,都是用不一样颜色分层。

那用其余图片训练的模型,可否提取哆啦a梦照片里的特征呢?

固然也能够!

使用迁移学习的关键,在于冻结中间过程的所有训练结果,直接把一幅图,利用在其余图片集合上训练的模型,转化为一个特征描述结果。

后面的工做,只把这个最后的特征描述(全链接层),用来处理分类和类似度计算。

前面的好几十层参数迭代训练,通通都被省却了。

难怪能够利用这么小的数据集得到如此高的准确度;也难怪能够在这么短的时间里,就得到整合后的模型结果。

把在某种任务上积累下的经验与认知,迁移到另外一种近似的新任务上,这种能力就叫作迁移学习。

比起机器来,人的迁移学习能力更为强大。

雨果奖做者郝景芳在最近的一篇文章里,描述了人的这种强大学习能力:

小孩子能够快速学习,进行小数据学习,并且能够获得「类」的概念。小孩子轻易分得清「鸭子」这个概念,和每一只具体不一样的鸭子,有什么不一样。前者是抽象的「类」,后者是具体的东西。小孩子不须要看多少张鸭子的照片,就能获得「鸭子」这个抽象「类」的概念。

用成语来描述,大概就是“举一反三”吧。

若是人类不善于迁移学习,把生活中的全部事物,全都当成新的东西从头学起,那后果简直不堪设想。对比咱们一辈子中所能处理的信息总量,这种认知负荷将是没法承受的。

回到咱们的问题里,若是模型能够帮咱们把每一张图片,都变成全链接层上的那一长串数字(特征),那么咱们分辨这些图片的类似程度,就变得太简单了。由于这变成了一个简单的空间向量距离问题。

处理这种简单的数值计算,咱们人类可能以为很繁琐。可是计算机算起来,那就很欢快了。

根据距离大小排序,找出其中最小的几个向量,它们描述的图片,就被模型断定为类似度最高的。

小结

在《如何用Python和深度神经网络识别图像?》一文的基础上,本文进一步介绍了如下内容:

  • 如何利用TuriCreate快速构建图片类似度模型;
  • 如何查询与某张图片最为类似的k张图片;
  • 如何可视化展现查询图片集合结果;
  • TuriCreate图形分类与类似度计算背后的原理;
  • 迁移学习的基础概念。

若是你没有读过《如何用Python和深度神经网络识别图像?》,强烈建议你读一读。阅读过程能够帮助你更好地理解基于深度神经网络的计算机视觉工做原理。

讨论

你以前遭遇过大海捞针,寻找近似图片的工做吗?你是如何处理的?使用过哪些好的工具与方法?与本文相比较,它们的优点有哪些?欢迎留言,把你的经验和思考分享给你们,咱们一块儿交流讨论。

喜欢请点赞。还能够微信关注和置顶个人公众号“玉树芝兰”(nkwangshuyi)

若是你对数据科学感兴趣,不妨阅读个人系列教程索引贴《如何高效入门数据科学?》,里面还有更多的有趣问题及解法。

相关文章
相关标签/搜索