作者:Tirmidzi Aflahi
原文链接:https://thedatamage.com/convolutional-neural-network-explained/Tirmidzi AflahiApril 14, 2019
让我们先来看看下面这张照片。
上面的图片并不是真实的,你可以打开图像并放大,就能看到那些马赛克了。这张照片实际上是人工智能生成的,是不是感觉和现实中的图片没什么不同?
从 Alex Krizhevsky 等人通过 ImageNet 竞赛将这项技术公诸于众,到现在只有短短 7 年时间。(ImageNet 是一年一度的计算机视觉大赛,比赛会将图片分成 1000 个不同的类别——跨度从阿拉斯加雪橇犬到厕纸。)Alex 和他的朋友们建立了 AlexNet 的程序,最后赢得了比赛的第二名。
这种技术被称为卷积神经网络(Convolutional Neural Network,CNN)。它是深度神经网络的一个分支,在图像处理方面表现得尤其好。
上图统计了几年前这项比赛夺冠算法的识别错误率。在2016年,这些算法实际上已经可以比表现得人类还要好(人类的错误率约为 5%)。
在图像识别领域引入深度学习实际上是一种突破——而不仅仅是改变。
那么,卷积神经网络技术是如何实现的呢?
卷积神经网络由于其独特的处理过程而优于其他深度神经网络结构。主要在于,它一次不止查看一个像素,而是将多个像素分组 (如上图中的 3×3 像素),以便理解其模式(pattern)。另一种说法是,它可以“看到”一组像素组成的一条直线或曲线。由于深度神经网络的深层性质,在下一个层次上,它看到的就不是一组像素,而是一组形成某种形状的直线和曲线。以此类推,直到形成一个完整的图像。
如果你想从最基本的方面了解人工神经网络,比如卷积核、池化层等等,你要学的还有很多。但是现在,不必自己训练,你可以直接使用很多相关开源技术。这完全不是在开玩笑,因为现在有一种技术叫做迁移学习。
迁移学习是一种将训练好的深度学习模型运用到其它更具体任务中的技术。例如,你在火车管理公司工作,想要评估火车是否准时,但你又不想仅仅为了这个任务而增加额外的劳动力。这时你就可以选择 ImageNet 卷积神经网络模型,或者使用 ResNet ( 2015 年 ImageNet 比赛的赢家),然后使用你的火车图像对网络进行重新训练,效果肯定不错。
使用迁移学习有两个主要优势:
在迁移学习的支持下,出现了许多新的项目。现在的项目已经能够处理一些图像,并告诉我们这些图像的内容是什么。那么如何去生成图像呢?
于是,生成式对抗网络(Generative Adversarial Network,GAN)出现了。
这项技术可以使用一些输入图像来生成新图像。
如上图所示,CycleGAN 技术可以实现:通过给定一幅画的类型来生成一个现实的照片。在其他应用中,它还可以依据草图,生成一系列图片。或者输入低分辨率图像,输出高分辨率图像。
太神奇了,不是吗?
你随时都可以开始去学习建造它们,那么问题就是,要怎样去建造呢?
来吧!让我们开始。你会发现其实这个话题很简单,非常简单,但能否掌握它则是另一个层面。我们先不考虑掌握它的问题。
经过几天的浏览,我觉得下面这个项目非常适合新手开始。
航拍仙人掌图像识别:https://www.kaggle.com/c/aerial-cactus-identification
这是 Kaggle 的一个教程项目,任务是在航拍图像中确定是否有柱状仙人掌。是不是很简单?
你将得到 17500 幅图像,并需要标记 4000 幅未标记的图像。如果你的程序正确地标记了 4000 张图片,你的分数就能达到 1 或 100% 。
图像就像上图这样。一个地区的照片,可能会包含也可能不包含柱状仙人掌。这些照片只有 32×32 像素,并且因为是航拍图像,所以仙人掌的朝向会有所不同。
那么你需要做什么呢?
卷积神经网络与 Python
是的,就是 Python ——一种流行的深度学习编程语言。其实现在有许多技术可供选择,你可以对每个选择进行试错。这些选择包括:
在本教程中,让我们使用我最喜欢的 Pytorch 。加上它的库,FastAI。
在开始之前,你需要安装 Python 。可以到 Python 网站下载,注意需要确保安装了 3.6 及以上版本,否则你使用的库可能不支持它。
现在,打开命令行或终端并安装这些东西。
pip install numpypip install pandaspip install jupyter
Numpy 用于存储输入的图像,pandas 处理 CSV 文件。借助 Jupyter notebook 就可以用 Python 进行交互式编程。
然后,到 Pytorch 网站下载你需要的内容。你可能需要 CUDA 版本来加快你的训练速度。但是请确保你下载的 Pytorch 是 1.0 及以上版本。
然后,安装 torchvision 和 FastAI 。
pip install torchvisionpip install fastai
使用 Jupyter notebook 命令运行 Jupyter ,它将打开一个浏览器窗口。
现在,你可以开始了。
准备数据
导入必要的代码。
import numpy as npimport pandas as pdfrom pathlib import Pathfrom fastai import *from fastai.vision import *import torch%matplotlib inline
你想做的任何事情都需要 Numpy 和 Pandas 。FastAI 和 Torch 是你的深度学习库。而 Matplotlib inline 将用于显示图表。
现在,从比赛网站下载数据文件。
比赛网站:https://www.kaggle.com/c/aerial-cactus-identification/data
提取 zip 数据文件并将其放入 jupyter notebook 文件夹中。
让我们看一下,当你将你的笔记本命名为 Cacti,你的文件夹结构将是这样的。
Train folder 文件夹包含训练需要的所有图像。
Test folder 文件夹包含所有要识别的图像。
Train CSV 文件包含训练数据。将图像名称映射到列 has_cactus ,如果图像中有cactus,则该列的值为1,否则为0。
Sample Submission CSV 文件包含你需要做的所有提交格式。这里声明的文件名等于测试文件夹中的所有文件。
train_df = pd.read_csv("train.csv")
将 Train CSV 文件加载到数据框。
data_folder = Path(".")train_img = ImageList.from_df(train_df, path=data_folder, folder='train')
使用 ImageList from_df 方法创建一个负载生成器,将 train_df 数据框与 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 。你可以做垂直翻转、水平翻转、旋转、缩放、添加光照/亮度和扭曲图像。
你可以使用上面提到的参数来了解它是什么样的,或者打开文档去详细阅读它。
训练准备
加载数据后,你需要为深度学习中最重要的训练阶段做好准备。深度学习就是,从数据中学习,获取模型参数,完成相应的任务。
当然,接下来就是需要将转换方法应用到图像列表。
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) .transform(transformations, size=128) .databunch(path='.', bs=64, device=torch.device('cuda:0')) .normalize(imagenet_stats)
训练中,你需要将一些训练数据分割出一小部分,称为验证集。你不能对这些数据进行任何处理,它是你验证模型的工具。当你的卷积神经网络模型在验证集上表现好时,它就有可能在测试集上表现好。
FastAI 有一个很方便 split_by_rand_pct 的方法,用于生成验证集。
还有 databunch 方法可以来执行批处理。我选择的 batch size 为 64 ,这是我 GPU 限制。如果你没有 GPU ,就使用设备参数。
然后,调用 normalize 方法对图像进行标准化,因为你将使用的是预训练的网络。imagenet_stats 将根据 ImageNet 比赛中预训练网络使用的数据标准,来对图像进行规范化。
转换方法中的参数大小将用于放大或缩小输入,来方便匹配你使用的神经网络。我使用的网络是 DenseNet ,它获得了2017年 ImageNet 最佳论文奖,使用的图片是 128×128 像素大小的图片。
将测试数据添加到训练图像列表中,以便稍后进行预测。不会有另一个预处理,记住,这些图像不会经过训练,也不会经过验证。你只需使用与训练图像相同的方法对数据进行预处理。
learn = cnn_learner(train_img, models.densenet161, metrics=[error_rate, accuracy])
到现在为止,你已经准备好了你的训练数据。现在,用 cnn_learner 创建一个训练方法。如前所述,我将使用 DenseNet 作为预训练网络。你可以使用 TorchVision 提供的另一个网络。
一个周期的技巧
你现在就可以开始训练了。但是,在训练任何深度神经网络( 包括卷积神经网络 )时,总是会存在一定的问题。这就涉及到如何选择正确的学习率了。下面这个算法被称为梯度下降算法,它是被用来减少由于学习率的参数的设置引起的误差。
学习速度越高,训练速度越快,但也越容易越界,错误很有可能失控,如左上图所示。虽然较低的学习速度使训练速度变慢,但它不会失控。
所以,选择正确的学习率是非常重要的,我们需要考虑的是如何让它足够大而不失控。
事实上,这件事说起来容易做起来难。
有一个叫 Leslie Smith 的人创造了一种叫做 1-cycle 的技术。
从直觉上讲,你可能希望从几种学习率中,找到一个错误几乎最小,但仍有一些改进空间的学习率参数。让我们在代码中尝试一下。
learn.lr_find()learn.recorder.plot()It will print something like this
最小值应该是10-1。所以,我们可以用比这个小一点的学习率,但不要太小。也许 3 * 10-2 是个不错的选择。
lr = 3e-02learn.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 ,我忘记了。
但是,幸运的是,内核实际上与你的 jupyter notebook 是一样的。你可以复制粘贴所有你在笔记本上创建的东西并提交到那里。
还有BAAM !
天啊!公共分数是 0.9999 ,这已经很好了。但是,当然,在我的第一次尝试已经是那样的结果的情况下,我想要得到一个完美的分数。
所以,我在网络和BAAM做了几个调整!
我能做到,你当然也能做到,其实没有那么难。(顺便说一句,这张照片是4月13日拍的,所以我的级别可能已经下降了)
我学到了什么
这个问题很简单。所以,你在解它的时候不会遇到任何奇怪的挑战。这让它成为了最适合新手开始的项目之一。
唉,但是因为很多人在这方面得到了满分,所以我认为管理员需要为创建另一个更难一点的测试集。
不管什么原因,你都可以尝试一下这个项目。就现在吧!相信我,效果会很好的。
卷积神经网络对各种任务都很有帮助,从图像识别到图像生成。现在分析图像不像以前那么困难了。按照上面的方法,你也可以做到。选择一个好的卷积神经网络实践项目,你会得到一个好的结果的。
当然,你可以阅读我的另一篇关于机器学习的教程。
Machine Learning:https://thedatamage.com/machine-learning-with-python/
祝你好运!
编辑:刘杨珂