Press "Enter" to skip to content

如何用卷积神经网络构建图像?

 

来自Pix2PixHD

 

那不是一张真实照片,你可以在新的标签页中打开并放大图片,看到马赛克了没?

 

这张图片其实是由一个叫人工智能的程序生成的。是不是看起来很真实?非常不错,不是吗?

 

这种技术由Alex Krizhevsky和朋友们通过ImageNet比赛而公诸于世,到现在才仅仅七年时间。这个竞赛是每年举行一次的计算机视觉比赛,竞赛内容是把图片分成1000种不同的分类。从阿拉斯加雪橇犬到卫生纸。Alex和朋友们建立了一个叫AlexNet的东西,它以远超第二名的成绩赢得了比赛。

 

这种技术叫作卷积神经网络,它是在图像处理方面表现出卓越的深度神经网络的一个分支。

 

 

来自ImageNet

 

上图是几年前赢得比赛的软件所产生的错误率,人类的错误率是5%。2016年,它的表现实际上已经优于人类了。

 

把深度学习引入到这个领域,已不仅仅是突破性的,而是革命性的了。

 

    卷积神经网络架构

 

那幺,这个技术的原理是什幺呢?

 

 

卷积神经网络表现好于其它深度神经网络架构,是得益于它独特的处理方式。CNN并不每次只处理一个像素,而是把几个像素组合在一起(就像上图中3×3像素的例子),因此它能发现时序模式。

 

换句话说,CNN能“看到”像素群如何形成直线或曲线。因为深度神经网络天然包含多个层级,在下一层,CNN看到的不再是像素群,而是直线和曲线群如何组成某些形状。一步步下去,直到它们构成了完整的图像。

 

 

深度卷积神经网络,由Mynepalli提供

 

想要了解CNN,你必须要学习很多东西,需要从很基础的知识开始,比如内核、池化层等等。但是,如今你可以一头扎进这门技术的众多开源项目中,并使用它们。

 

因为一种叫“迁移学习”的技术,使得这种做法确实有效。

 

    迁移学习

 

迁移学习是一种技术,它把在另外一个特定领域训练好的深度学习模型拿来复用。

 

举个例子,假如你在一家火车管理公司工作,你打算检查你们的火车是否准点,但你不想为这件事增加人手。你可以复用一个ImageNet的卷积神经网络模型,也许是ResNet(2015年的获胜者),然后用你的火车车队的图片重新训练网络。这样就可以解决问题了。

 

用迁移学习,有两个主要的竞争优势。

 

 

相比从头开始训练,只需要较少图片就能达到良好效果。ImageNet竞赛有大约一百万张图片用于训练。使用迁移学习,你可以只用1000张或者甚至100张图片,而且效果良好,因为模型已经用那一百万张照片训练过了。

 

取得好效果所需时间更少。要做到ImageNet的水平,你要花好多天来训练网络,这还不包括效果不好时修改网络所需的时间。使用迁移学习,对于某些任务来说,你只要花几个小时甚至几分钟就完成训练。大大节省了时间。

 

 

    从图像分类到图像生成

 

有了迁移学习之后,很多构想产生了。如果你能处理图像,并且告诉我们图像里的内容是什幺,那能不能自己生成图像呢?

 

我们接受挑战!

 

下面是生成对抗网络登场!

 

 

CycleGAN 由Jun-Yan Zhu提供

 

这项技术能够在获得一些输入后,生成图片。

 

只要给它一种叫CycleGAN的类型的绘图——我已经上面的照片中提供给你,它就能生成真实的照片。在另一个用例中,给出一些草图,它能生成一个袋子的图片。它还可以从低分辨率照片中生成高分辨率的照片。

 

 

超分辨率生成对抗网络

 

很神奇,对吧?

 

当然是的。而你现在就可以开始学习生成这种图片了。你接下来该怎幺做呢?

 

    卷积神经网络教程

 

那幺,让我们开始吧。你会发现开始学习这门课程非常容易,容易到爆。但完全掌握它又是另外一回事。

 

我们现在暂时把完全掌握放到一边。

 

浏览几天后,我发现这个项目非常适合你入门。

 

    仙人掌空中识别

 

本教程中的项目来自Kaggle。你的任务是从航空照片中识别是否有柱状仙人掌存在。

 

很简单,不是吗?

 

给你17,500张图片进行操作,需要标注4,000张尚未标注的图片。如果全部4,000张图片被你的程序正确标注,你的得分将是1或100%。

 

 

仙人掌

 

图片跟你在上面看到的很像。一块区域的照片里,可能有或没有柱状仙人掌,照片是32×32像素的。因为是航空照片,所以照片里的仙人掌有不同的角度。

 

那幺,你还需要什幺?

 

    使用Python的卷积神经网络

 

Python,一种用于深度学习的流行语言。针对此语言,有很多深度学习框架可供选择,你实际上可以对每个选择进行反复试验  。下面是几个常用的深度学习框架:

 

 

Tensorflow,最受欢迎的深度学习库。由谷歌的工程师建造,拥有最大的贡献者基础和大多数粉丝。由于社区规模如此之大,您可以轻松找到问题的解决方案。它将Keras作为高级抽象包装器,对新手来说非常容易入门。

 

Pytorch。我最喜欢的深度学习库。纯粹基于Python构建并遵循Python的优缺点。Python开发人员将非常熟悉这个库。它有另一个名为FastAI的库,它提供了Keras对Tensorflow的抽象。

 

MXNet。Apache的深度学习库。

 

Theano。Tensorflow的前身

 

CNTK。微软自己的深度学习库。

 

 

在本教程中,让我们使用我最喜欢的一个深度学习框架,Pytorch,以及其抽象FastAI。

 

在开始之前,你需要安装Python。前往Python网站下载你所需的内容。你需要确保安装版本3.6+,否则你使用的库将可能不支持它。

 

现在,打开命令行或终端并安装这些东西:

 

pip install numpy pip install pandas pip install jupyter

 

Numpy包用于存储输入图像,pandas包用于处理CSV文件,Jupyter notebook是用Python编辑器。

 

然后,前往Pytorch官网下载相应版本的Pytorch。为了加速训练速度,你可能需要下载相应的CUDA版本,但是要确保你的Pytorch版本在1.0以上。

 

然后,安装torchvision和FastAI:

 

pip install torchvision pip install fastai

 

在命令行或者终端输入jupyter notebook打开Jupyter,它会显示在浏览器中。

 

 

现在,你已经准备妥当了。

 

    数据准备

 

导入必要的代码:

 

import numpy as npimport pandas as pd from pathlib import Path from fastai import * from fastai.vision import * import torch %matplotlib inline

 

Numpy和Pandas库基本上所有任务都需要导入,FastAI和Torch是深度学习库,Matpoltlib Inline 用于显示图表。

 

现在,从比赛网站下载数据文件。

 

解压zip压缩包到jupyter notebook的目录下。

 

假设你的notebook文件名是Cacti,那幺你的目录结构将如图所示:

 

train文件夹含有你训练时用到的所有图片。

 

test文件夹包含提交时要用的到所有图片。

 

train.csv文件包含所有的训练数据:如果某图片中含有仙人掌,则该图片名对应的行中has_cactus字段将为1,否则为0。

 

sample_submission.csv文件中含有提交格式。文件名对应于test文件中所有图片的名字。

 

train_df = pd.read_csv("train.csv")

 

把train.csv文件加载到一个data frame中。

 

data_folder = Path(".") train_images = ImageList.from_df(train_df, path=data_folder, folder='train')

 

使用ImageList中的from_df方法创建一个加载器来将train_df中的data frame与train文件夹中的图片关联起来。

 

    数据增强

 

这是一种从已有数据生成更多数据的方法。一只猫的图片垂直翻转之后还是一直猫。通过这种方法,你可以获得两倍,四倍,甚至十六倍的数据。

 

如果你的数据量比较少的话,你可以使用这种方法。

 

transformations = get_transforms(do_flip=True, flip_vert=True, max_rotate=10.0, max_zoom=1.1, max_lighting=0.2, max_warp=0.2, p_affine=0.75, p_lighting=0.75)

 

FastAI提供了一个叫做get_transform的方法可以很好的完成该任务。你可以对图片进行垂直翻转,水平翻转,旋转,缩放,补光,扭曲。

 

你可以通过运行上面代码来查看这些参数的增强效果,或者你也可以查看通过查看官方文档来详细阅读相关说明。

 

当然,需要在你的数据集上运用该变换:

 

train_img = train_img.transform(transformations, size=128)

 

参数size是为了调整图像大小以适应网络输入。我使用的网络是获得2017年ImageNet最好论文奖的DenseNet,其输入大小为128 x 128.

 

    训练准备

 

加载数据之后,需要对数据进行预处理才能开始进行训练。训练,可以说成是神经网络在学习,为了在你的数据集上获得好的性能,它从你的数据中学习,并进行自我更新。

 

test_df = pd.read_csv("sample_submission.csv") test_img = ImageList.from_df(test_df, path=data_folder, folder='test')

 

 

train_img = train_img           .split_by_rand_pct(0.01)           .label_from_df()           .add_test(test_img)           .databunch(path='.', bs=64, device=torch.device('cuda:0'))                       .normalize(imagenet_stats)

 

为了检测训练性能,你需要从你的训练数据中划分出来一小部分作为验证集。训练时不能采用验证集数据,因为它需要用于验证网络性能。如果你的CNN能够在验证集上获得较好性能,说明其具有较好的泛化能力,同样能在测试集上获得较好性能。

 

FastAI提供了一个叫做split_by_rand_pac的方法可以很方便的划分验证集。

 

它也包含一个叫做databunch的方法用于batch的处理。由于我的GPU显存限制,我采用的batch大小为64。如果你没有GPU,请删去device这个参数。

 

然后,由于你需要采用预训练好的网络,因此你需要采用一个叫做normalize的方法正则化你的图片。参数image_stats是为了按照ImageNet竞赛中预训练网络的规则化方式规则化你的图片。

 

把测试集数据加入训练集列表的目的是为了在预测时不再进行预处理。但是,请记住训练集数据不会用于训练,也不会归为验证集。这样做只是为了使所有数据采用相同的规则化方式。

 

learn = cnn_learner(train_img, models.densenet161, metrics=[error_rate, accuracy])

 

准备好训练数据之后,你可以使用cnn_learner创建一个训练方法。正如前面所说,我使用DenseNet作为预训练好的网络。你也可以使用TorchVision提供的其他网络

 

    单循环技术

 

现在可以开始训练了。但是当训练所有DNN和CNN的时候,都会有这样一个疑惑,学习率选多大呢?有一个算法叫做梯度下降,它能随着学习率减小误差。

 

 

如果学习率过大,可能倾向于越过边界。想左图显示的那样,这可能导致误差非常大。但是如果学习率过小,训练会非常慢,但是误差不会失控。

 

因此,选择正确的学习率至关重要,要选取一个足够大、但不会大到使误差失控的学习率。

 

说起来容易,做起来难。

 

因此,一个叫做Leslie Smith的人提出了一个称为1-cycle的方法。

 

从直觉上讲,您可能希望找到/蛮力的几种学习速度,并找到一个错误几乎最小,但仍有一些改进空间的学习速度。让我们在代码中尝试一下。

 

learn.lr_find() learn.recorder.plot()

 

它会打印出下面的东西:

 

 

最小值应为10 -1。所以,我认为我们可以使用比这更小的东西,但不能太小。也许3 * 10 – 2是个不错的选择。我们来试试吧!

 

lr = 3e-02 learn.fit_one_cycle(5, slice(lr))

 

训练几个步骤(我选择5,不要太大也不要太小),让我们看看结果。

 

 

等等,什幺!?

 

我们的简单解决方案为我们的验证分割提供100%的准确性!它实际上是有效的。它只需要6分钟的训练。真是太幸运啦!在现实生活中,您将进行多次迭代,以找出哪些算法比其他算法做得更好。

 

我很想提交!哈哈。让我们预测测试文件夹并提交结果。

 

preds,_ = learn.get_preds(ds_type=DatasetType.Test) test_df.has_cactus = preds.numpy()[:, 0]

 

由于您已将测试图像放在训练图像列表中,因此无需预处理和加载测试图像。

 

test_df.to_csv('submission.csv', index=False)

 

此行将创建一个包含图像名称的CSV文件,并为所有4,000个测试图像提供一个cactus(仙人掌)列

 

当我尝试提交时,我发现你需要通过Kaggle内核提交CSV。我错过了!

 

 

由Kaggle提供

 

但是,幸运的是,Kernel(内核)实际上与你的jupyter notebook相同。你可以复制粘贴所有你在笔记本上创建的东西并提交到那里。

 

和BAM!

 

 

太棒了我的公共分数是0.9999。这是很好的。但是,当然,如果我的第一次尝试是那样的话,我想要得到一个完美的分数。

 

 

我做到了!所以你也能,其实也没有那幺难。

 

(顺便说一句,这个排名是在4月13日,所以我可能会放弃我的排名…)

 

    个人经验

 

这个问题很简单。所以你在解它的时候不会遇到任何奇怪的挑战。这使得它会成为最适合入门的项目之一。

 

唉,因为很多人在这方面得到了完美的分数,我认为管理员需要为提交创建另一个测试集,也许这很难。

 

不管什幺原因,你都需要去尝试一下。你现在就可以试试,效果可能会很好噢~

 

    最后思考

 

卷积神经网络(CNN)对各种任务都很有帮助,从图像识别到生成图像,现在分析图像不像以前那幺困难了。当然,你都要去尝试一下。

 

开始吧,选择一个好的卷积神经网络项目,然后,得到一个好的数据。

 

好运!

 

文章最初发布在 thedatamage网站上。

 

本文编辑:王立鱼

 

英语原文:https://www.freecodecamp.org/news/everything-you-need-to-know-to-master-convolutional-neural-networks-ef98ca3c7655/

原标题 |  Everything you need to know to master Convolutional Neural Networks

作 者 |  Tirmidzi Faizal Aflahi

译者 | pzSuen(哈尔滨工业大学)、AI小山(工程师)、Brains(前端开发工程师)

 

Be First to Comment

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注