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

简介: 给你10万张图片,让你找出与其中某张图片最为近似的10张,你会怎么做?不要轻言放弃,也不用一张张浏览。使用Python,你也可以轻松搞定这个任务。
img_4555bed21124257514b8c639dd7ff788.png

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

疑问

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

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

img_b2813570b8f08cb4a61eeaf055324bb1.jpe

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

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

img_075d776bb83224fb18f9315f6637fcfe.jpe

很快,我突然醒悟过来。

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

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

img_2f36fe51a36237006ab670c2e0fc6e70.png

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

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

img_83cd6b6fada6e00b38f42ad6e1286a27.png

这时候无论对其衣着、外貌还是交通工具的相似度搜索,就显得至关重要了。

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

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

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

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

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

数据

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

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

请点击这个链接,下载压缩包。然后在本地解压。作为咱们的演示目录

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

img_d6ff18c0041ea9b1e24b017b040a3710.jpe

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

img_1cfc2ccd04e14843e17cfde87606ab7d.jpe

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

img_c85fce05f60ce9c41b1c9b50094e067d.jpe

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

环境

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

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

img_f976d08e9fae25bc0e8f9905d617862a.jpe

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

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

img_e7774f1e8f7478697a400493cc938608.jpe

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

img_90f38eaec50b3fe9679bb30ec05efc7f.png

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

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

img_c7d98363b30b934f433bd01ed877a66d.png

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

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

img_c9551cc7450053e088b8faea3e1c30ed.jpe

装好Anaconda后,我们安装TuriCreate。

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

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

conda create -n turi python=2.7 anaconda

然后,我们激活turi虚拟环境。

source activate turi

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

pip install -U turicreate

安装完毕后,执行:

jupyter notebook
img_de5447fdcea85acf633827ad9fd75072.jpe

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

img_62956f921e80a2d0fbd10b3e883971ef.jpe

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

img_5c4eddcb1d23559c85e8ea65c01f9951.jpe

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

img_c8272dfbdd283c4b7e38afdb68e32d86.jpe

准备工作完毕,下面我们就可以开始编写程序了。

代码

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

import turicreate as tc

我们指定图像所在的文件夹image。让TuriCreate读取所有的图像文件,并且存储到data数据框。

data  = tc.image_analysis.load_images('./image/')

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

data
img_4b3f5102c85e8eef0e8fc0ffbadab4f9.png

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

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

data = data.add_row_number()

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

data
img_4ebb498b6039eee925fa40b67ecd4fd0.png

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

data.explore()

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

img_97e2afee61d826062ba837393ff06d10.png

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

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

img_b9aa5399526defe4b957f159ab5c86b5.png

第二张图片,是瓦力:

img_a7fb493c5b2110909ada7093d99554ea.png

下面,是重头戏。我们让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()
img_a88851e28cc4051231d42753b40c853f.png

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

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

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

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

img_5e028ef1504484072d9c86b46d414e48.png

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

similar_images
img_86402db01a099a1d8e8b0c79d169251a.png

返回的结果一共有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()

系统会弹出以下对话框:

img_49633bb12ba709a305e954d62a0434e2.png

我们可以看到,全部查询结果图片中,只出现了哆啦a梦。瓦力的图片,一张都没有出现。

近似图片查找成功!

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

原理

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

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

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

model = tc.image_similarity.create(data)

然而实际上,TuriCreate在后台为我们做了很多事情。

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

img_d2c45466cfb112c0bad9af140d31dd91.png

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

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

没有。

那就怪了,不是吗?

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

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

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

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

img_5f41507b13c27c277d53b2a8ca8a314d.png

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

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

img_3969ad6f459ceebbe800ea779a771897.png

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

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

你自然可以用它帮你提取一条狗的特征。

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

img_7b125c4732662bf18cc4de52f901e245.png

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

img_37c81857d4a4352b29e894ddd7514c97.png

当然也可以!

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

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

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

img_c338ac650129d3a2e6033a3fc90e348b.png

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

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

img_e3320452134f89bffde06ac7c8c3d55f.png

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

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

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

用成语来描述,大概就是“触类旁通”吧。

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

回到我们的问题里,如果模型可以帮我们把每一张图片,都变成全连接层上的那一长串数字(特征),那么我们分辨这些图片的相似程度,就变得太简单了。因为这变成了一个简单的空间向量距离问题。

img_4f2604f5c5e9558ae897959079856465.png

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

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

小结

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

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

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

讨论

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

喜欢请点赞。还可以微信关注和置顶我的公众号“玉树芝兰”(nkwangshuyi)

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

目录
相关文章
|
3天前
|
机器学习/深度学习 人工智能 算法
猫狗宠物识别系统Python+TensorFlow+人工智能+深度学习+卷积网络算法
宠物识别系统使用Python和TensorFlow搭建卷积神经网络,基于37种常见猫狗数据集训练高精度模型,并保存为h5格式。通过Django框架搭建Web平台,用户上传宠物图片即可识别其名称,提供便捷的宠物识别服务。
92 55
|
1月前
|
数据采集 缓存 定位技术
网络延迟对Python爬虫速度的影响分析
网络延迟对Python爬虫速度的影响分析
|
1月前
|
Python
Python中的异步编程:使用asyncio和aiohttp实现高效网络请求
【10月更文挑战第34天】在Python的世界里,异步编程是提高效率的利器。本文将带你了解如何使用asyncio和aiohttp库来编写高效的网络请求代码。我们将通过一个简单的示例来展示如何利用这些工具来并发地处理多个网络请求,从而提高程序的整体性能。准备好让你的Python代码飞起来吧!
71 2
|
12天前
|
机器学习/深度学习 人工智能 算法
【宠物识别系统】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+图像识别
宠物识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了37种常见的猫狗宠物种类数据集【'阿比西尼亚猫(Abyssinian)', '孟加拉猫(Bengal)', '暹罗猫(Birman)', '孟买猫(Bombay)', '英国短毛猫(British Shorthair)', '埃及猫(Egyptian Mau)', '缅因猫(Maine Coon)', '波斯猫(Persian)', '布偶猫(Ragdoll)', '俄罗斯蓝猫(Russian Blue)', '暹罗猫(Siamese)', '斯芬克斯猫(Sphynx)', '美国斗牛犬
83 29
【宠物识别系统】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+图像识别
|
13天前
|
机器学习/深度学习 人工智能 算法
深度学习入门:用Python构建你的第一个神经网络
在人工智能的海洋中,深度学习是那艘能够带你远航的船。本文将作为你的航标,引导你搭建第一个神经网络模型,让你领略深度学习的魅力。通过简单直观的语言和实例,我们将一起探索隐藏在数据背后的模式,体验从零开始创造智能系统的快感。准备好了吗?让我们启航吧!
40 3
|
18天前
|
网络安全 Python
Python网络编程小示例:生成CIDR表示的IP地址范围
本文介绍了如何使用Python生成CIDR表示的IP地址范围,通过解析CIDR字符串,将其转换为二进制形式,应用子网掩码,最终生成该CIDR块内所有可用的IP地址列表。示例代码利用了Python的`ipaddress`模块,展示了从指定CIDR表达式中提取所有IP地址的过程。
35 6
|
21天前
|
机器学习/深度学习 自然语言处理 语音技术
Python在深度学习领域的应用,重点讲解了神经网络的基础概念、基本结构、训练过程及优化技巧
本文介绍了Python在深度学习领域的应用,重点讲解了神经网络的基础概念、基本结构、训练过程及优化技巧,并通过TensorFlow和PyTorch等库展示了实现神经网络的具体示例,涵盖图像识别、语音识别等多个应用场景。
45 8
|
20天前
|
数据采集 XML 存储
构建高效的Python网络爬虫:从入门到实践
本文旨在通过深入浅出的方式,引导读者从零开始构建一个高效的Python网络爬虫。我们将探索爬虫的基本原理、核心组件以及如何利用Python的强大库进行数据抓取和处理。文章不仅提供理论指导,还结合实战案例,让读者能够快速掌握爬虫技术,并应用于实际项目中。无论你是编程新手还是有一定基础的开发者,都能在这篇文章中找到有价值的内容。
|
1月前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
垃圾识别分类系统。本系统采用Python作为主要编程语言,通过收集了5种常见的垃圾数据集('塑料', '玻璃', '纸张', '纸板', '金属'),然后基于TensorFlow搭建卷积神经网络算法模型,通过对图像数据集进行多轮迭代训练,最后得到一个识别精度较高的模型文件。然后使用Django搭建Web网页端可视化操作界面,实现用户在网页端上传一张垃圾图片识别其名称。
77 0
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
|
1月前
|
机器学习/深度学习 TensorFlow 算法框架/工具
利用Python和TensorFlow构建简单神经网络进行图像分类
利用Python和TensorFlow构建简单神经网络进行图像分类
56 3