近年来,深度学习技术一直都处于科研界的前沿。凭借深度学习,我们开始对图像和视频进行分析,并将其应用于各种各样的设备,比如自动驾驶汽车、无人驾驶飞机,等等。
A Neural Algorithm of Artistic Style是一篇最新发表的研究性论文,论文向我们介绍了如何将一种风格和气质从艺术家身上转移至一张图像,并由此创建出另一张新图像。其他的一些论文,比如Generative Adversarial Networks和Wasserstein GAN,也已经为开发模型铺平了道路,这个模型能够创建出与输入数据相似的新数据。由此,“半监督学习”世界的大门被打开了,未来“无监督学习”的发展也将更加顺利。
尽管这些调查研究的对象现在仅限于一般的图像,但我们的目标是将这些研究运用到医学图像中,帮助医疗保健的发展。在本文中,我将从图像处理和医学图像格式数据入手,并对一些医学数据进行可视化处理。在下一篇文章中,我将进深入剖析一些卷积神经网络,并将其与Keras联合,预测肺癌。
使用Python进行基本的图像处理
OpenCV(开源计算机视觉库)凭借其大量社区支持,以及对C++,Java和Python的可兼容性,在琳琅满目的图像处理库中脱颖而出,成为了图像处理库的主流。
现在,打开你的Jupyter笔记本,并且确定cv2是能够导入至笔记本的。你还需要numpy和matplotlib来查看笔记本内的细节内容。
现在,我们来看一下你能不能打开图片,能不能用下面的代码在你的笔记本上查看图片。
基本的人脸检测
接下来,我们要玩些有趣的——检测人脸。我们将使用一个开源的正脸检测器来进行人脸检测,这个检测器最初是由Rainer Lienhart创建的。下图这个帖子详细地介绍了级联检测的细节:
在下面的文档中还有很多使用OpenCV进行图像处理的例子(点击链接查看文档http://docs.opencv.org/trunk/d6/d00/tutorial_py_root.html),读者们可以任意查看。了解了基本的图像处理以后,接下来我们将开始了解“医学图像格式”。
医学图像数据格式
医学图像与“数字影像和通讯”(DICOM)一样,是一个储存和交换医学图像数据的标准解决方案。该标准自1985年第一版发布以来,已经被修改了好几次。该标准使用的是一个文件格式和一个通讯协议。
- 文件格式——所有病人的医学图像都被保存在DICOM文件格式里。这个格式中保存着病人的受保护健康信息,比如:病人姓名、性别、年龄,还有一些医疗图像的数据。“医学成像设备”创建了DICOM文件。医生们使用DICOM阅读器和能够显示DICOM图像的电脑软件应用程序来查看医学图像,并且根据图像的信息作出诊断。
- 通讯协议——DICOM通讯协议是用来在档案中搜索影像研究,并将影像研究还原显示的。所有连接了医院网络的医学成像应用程序都会使用DICOM协议交换信息,这些信息中的大部分是DICOM图像,不过还包括了一些患者信息和治疗方案。还有一些网络要求是用于控制和跟踪手术、安排手术日程、报告状态,以及分担医生和成像设备之间的工作量的。
下面的博客详细地介绍了DICOM标准:
分析DICOM图像
Pydicom是一个相当不错的、用于分析DICOM图像的Python工具包。在这个部分,我们将会看到DICOM图像是如何在Jupyter笔记本上呈现的。
使用pip安装pydicom下载安装OpenCV
Pydicom工具包安装完毕以后,回到Jupyter笔记本。将dicom工具包和下图中的其他工具包导入笔记本中。
在处理和分析数据时,我们还会用到其他的工具包,比如pandas,scipy,skimage和mpl_toolkit,等等。
网上有很多免费的DICOM数据库,下面的这些数据库可能对你有所帮助:
- Kaggle竞赛和数据库:这是我个人最喜欢的数据库。这里面有关于肺癌和糖尿病视网膜病变的数据。
- Dicom数据库:DICOM数据库是一个免费的线上医学DICOM图像或视频分享的服务器,它主要是以教学和科研为目的的。
- Osirix数据库:这个数据库向我们提供了大量通过各种成像方式获得的人类数据。
- 可视化人体数据集:“可视人计划”的某些部分是分布于这个数据集的,但是这个数据集中的数据是需要收费的。
- Zubal幻影:这个网站提供了关于两名男性CT和MRI图像的多个数据库。
下载dicom文件,并将其上传至你的jupyter笔记本。
现在,将DICOM图像加载到一个列表中。
第一步:在Jupyter笔记本上查看DICOM图像
在第一行,我们加载第一个DICOM文件,然后提取文件名在列表中排第一的元数据。
接下来,我们要计算3DNumpy数组的总维数,它等于片中像素的行数x、片中像素的列数x,还有x,y,z轴。最后,我们要用“像素空间”和“SliceThickness”来计算三个轴上像素间的空间距离。我们需要将数组维度保存在ConstPixelDims中,并将空间保存在ConstPixelSpacing中。
第二步:进一步研究DICOM格式的细节
CT扫描测量的单元是“胡斯菲尔德单元”(HU),这个单元测量的是放射性密度。为了得到精确的测量结果,CT扫描仪经过了严格的校准。下面是关于CT扫描测量的细节内容:
每个像素都会被分配一个数值(CT数),这个数值是相应的voxel内所有衰减值的平均值。这个数字是与水的衰减值相比较得出的,而且是以任意单元的规模显示的,这个任意单元叫做“胡斯菲尔德单元”(HU),是以Godfrey Hounsfield先生的名字命名的。
这个任意单元的规模将水的衰减值定为零。CT数字的范围是2000HU,尽管有一些现代扫描仪的HU范围达到了4000。每个数值都代表了一种灰色阴影,在光谱两端有+1000白色和-1000黑色。
胡斯菲尔德规模(图片来自《CT的介绍》)
有些扫描仪是有柱状扫描边界的,但是其输出的图像确实方形的。在扫描边界之外的像素将被赋予-2000的定值。
CT扫描仪图像(图片来自《CT的介绍》)
第一步通常是将这些值设置为零。接着,我们把得到的数值与重新调节的斜率相乘,再加上截距(通常是记录在扫描的元数据中的),然后回到HU单元。
在接下来的部分,我们将会使用Kaggle的肺癌数据库和Keras的卷积神经网络。我们将根据本文提供的信息,构建下一部分的内容。
在《深度学习下的医学图像分析》系列的第一篇文章中,我们介绍了一些使用OpenCV和DICOM图像基础知识进行图像处理的过程。本文,我们将从“卷积神经网络”的角度讨论深度学习。在系列的第三部分,我们将利用Kaggle的肺癌数据库,重新查看肺癌DICOM图像中的关键内容和信息,并且利用Kera开发一个肺癌预测模型。
“卷积神经网络”(CNN)
在了解“卷积神经网络”之前,我们要先知道什么是“卷积”。
何为“卷积”?
维基百科对“卷积”的定义是:一个关于两个函数的数学运算。这个数学运算将会产生两个原始函数之外的第三个函数,这个函数通常被看作是两个原始函数之一的修正版,实际上是这两个原始函数的点乘式相乘的积分。我们可以简单地将第三个函数理解为“一个矩阵上的滑动窗口函数”。
图片来源:deeplearning.stanford.edu/wiki/index.php/Feature_extraction_using_convolution
如上图所示,绿色表示的是滑动窗口,红色的是滑动窗口矩阵,输出的结果是带有卷积特性的矩阵。下图是两个方形脉冲的卷积及其输出结果。
图片来源:维基百科
Jeremy Howard在他的MOOC课程里,利用一个Excel表格很好地解释了“卷积”。f和g两个矩阵的卷积输出是第三个矩阵卷积的第一层,也是这两个矩阵的点乘结果。这两个矩阵的点乘结果是下图所示的“标量矩阵”,也是一个数学函数的来源。
两个矩阵的点乘结果
像Jeremy一样,我们也来利用Excel表格。我们输入的矩阵是函数f(),滑动窗口矩阵是函数g()。两个函数的点乘结果是表格中的两个矩阵的和积,如下图所示:
两个矩阵的卷积
接下来,我们把这个规律用到大写字母A的一张图像。大家都知道,所有图像都是由像素构成的。因此,我们输入的矩阵f是“A”,把滑动窗口函数定为任意的矩阵g。然后,我们就得到了两个函数的点乘结果,如下图:
何为“卷积神经网络”?
图片来源: cs231n.github.io/convolutional-networks/
在我看来,一个简单的卷积神经网络CNN是所有层的一个序列。每一层都有一些特定的函数。每个卷积层都是三维的,所以我们用体积来作为度量标准。再进一步,卷积神经网络的每一层都会通过一个可微函数来将激活量转化为另一个,这个函数叫做“激活”或者“转化函数”。
“卷积神经网络”包含的不同实体分别是:输入层、过滤器(或内核)、卷积层、激活层、聚积层、批处理层。虽然这些层的组合排列各异,但是在不同的排列中还是存在一些规律的,给我们提供了不同的深度学习架构。
输入层:一般情况下,我们输入至“卷积神经网络”的通常是一个n维数组。如果是一张图像,我们有彩色通道的三维输入——长、宽、高。
图片来源: http://xrds.acm.org/blog/2016/06/convolutional-neural-networks-cnns-illustrated-explanation/
过滤器(或内核):如下图所示,一个过滤器或内核会滑动到图像的所有位置,将一个新像素作为所有像素的加权总和来进行计算。正如上面Excel表格的示例,我们的过滤器g移动到了输入的矩阵f处。
来源: intellabs.github.io/RiverTrail/tutorial/
卷积层:输入矩阵的点乘结果与内核共同创造出的新矩阵就是“卷积矩阵”,也被称作“卷积层”。
来源: https://docs.gimp.org/en/plug-in-convmatrix.html
下面这张非常清晰的视觉图表能够帮助你能更好地了解卷积填充和卷积转置的具体过程:
来源: https://github.com/vdumoulin/conv_arithmetic
激活层:“激活函数”能分成两类——“饱和激活函数”和“非饱和激活函数”。
sigmoid和tanh是“饱和激活函数”,而ReLU及其变体则是“非饱和激活函数”。使用“非饱和激活函数”的优势在于两点:
1.首先,“非饱和激活函数”能解决所谓的“梯度消失”问题。
2.其次,它能加快收敛速度。
Sigmoid函数需要一个实值输入压缩至[0,1]的范围
σ(x) = 1 / (1 + exp(−x))
tanh函数需要讲一个实值输入压缩至 [-1, 1]的范围
tanh(x) = 2σ(2x) − 1
ReLU
ReLU函数代表的的是“修正线性单元”,它是带有卷积图像的输入x的最大函数(x,o)。ReLU函数将矩阵x内所有负值都设为零,其余的值不变。ReLU函数的计算是在卷积之后进行的,因此它与tanh函数和sigmoid函数一样,同属于“非线性激活函数”。这一内容是由Geoff Hinton首次提出的。
ELUs
ELUs是“指数线性单元”,它试图将激活函数的平均值接近零,从而加快学习的速度。同时,它还能通过正值的标识来避免梯度消失的问题。根据一些研究,ELUs分类精确度是高于ReLUs的。下面是关于ELU细节信息的详细介绍:
图片来源: http://image-net.org/challenges/posters/JKU_EN_RGB_Schwarz_poster.pdf
图片来源:维基百科
Leaky ReLUs
ReLU是将所有的负值都设为零,相反,Leaky ReLU是给所有负值赋予一个非零斜率。Leaky ReLU激活函数是在声学模型(2013)中首次提出的。以数学的方式我们可以表示为:
图片来源:《卷积网络中整流激活函数的实证评估》
上图中的ai是(1,+∞)区间内的固定参数。
参数化修正线性单元(PReLU)
PReLU可以看作是Leaky ReLU的一个变体。在PReLU中,负值部分的斜率是根据数据来定的,而非预先定义的。作者称,在ImageNet分类(2015,Russakovsky等)上,PReLU是超越人类分类水平的关键所在。
随机纠正线性单元(RReLU)
“随机纠正线性单元”RReLU也是Leaky ReLU的一个变体。在RReLU中,负值的斜率在训练中是随机的,在之后的测试中就变成了固定的了。RReLU的亮点在于,在训练环节中,aji是从一个均匀的分布U(I,u)中随机抽取的数值。形式上来说,我们能得到以下结果:
下图是ReLU、Leaky ReLU、PReLU和RReLU的比较:
图片来源 :https://arxiv.org/pdf/1505.00853.pdf
PReLU中的ai是根据数据变化的;Leaky ReLU中的ai是固定的;RReLU中的aji是一个在一个给定的范围内随机抽取的值,这个值在测试环节就会固定下来。
噪声激活函数
这些是包含了Gaussian噪声的激活函数,下图能帮助你了解“噪声”是如何与激活函数相结合的:
图片来源:维基百科
聚积层
“聚积层”的目的就是通过逐渐缩减矩阵的空间大小,减少参数和网络内计算的数量,进而控制过度拟合。“聚积层”在输入中独立运行,然后利用最大值或平均值的操作来调整输入矩阵的空间大小。“聚积层”最常见的形式就是带有应用于输入的两个样本中的2x2过滤器的“聚积层”。在这种形式中,每一次最大值操作都会取超过4个的最大数量,深度维数保持不变。更常见的“聚积层”如下图:
图片来源: http://cs231n.github.io/convolutional-networks/#pool
图片来源: https://ujjwalkarn.me/2016/08/11/intuitive-explanation-convnets/
注意:这里我们把2 x 2窗口移动了两个单元格,然后取每个区域的最大值。
批规范化层
“批规范化”是将每个过渡层,包括激活函数,标准化的有效方法。“批规范化”操作的两个主要优点是:
1.在一个模型中添加“批规范”能够加快训练的速度
2.规范化操作大大降低了少数外围输入对训练的制约影响,同时减少了过度拟合的发生。
Jeremy的网络公开课中有更多关于“批规范化”的细节。
全连接层
“全连接层”是一个传统的“多层感知器”,这个感知器在输出层中使用了一个“柔性最大值激活函数”。顾名思义,“全连接”意味着上一层的每一个神经元都与下一层的每个神经元相连接。一个“柔性最大值函数”是逻辑函数的泛化,该函数将一个任意实值的K维向量转化为一个实值在(0,1)范围之间的K维向量。
图片来源:维基百科
“柔性最大值激活函数”一般被用于最后的全连接层,获取实值在0到1之间的概率。现在,我们对“卷积神经网络”中的不同层已经有所了解了,那么具备了这些知识,我们就能建立起肺癌检测所需的深度学习架构了。关于肺癌检测的深度学习架构,我们将在下一篇文章中讨论。
在《深度学习下的医学图像分析》系列的第一篇文章中,我们介绍了一些使用OpenCV和DICOM图像基础知识进行图像处理的过程。本文,我们将从“卷积神经网络”的角度讨论深度学习。在系列的第三部分,我们将利用Kaggle的肺癌数据库,重新查看肺癌DICOM图像中的关键内容和信息,并且利用Kera开发一个肺癌预测模型。
“卷积神经网络”(CNN)
在了解“卷积神经网络”之前,我们要先知道什么是“卷积”。
何为“卷积”?
维基百科对“卷积”的定义是:一个关于两个函数的数学运算。这个数学运算将会产生两个原始函数之外的第三个函数,这个函数通常被看作是两个原始函数之一的修正版,实际上是这两个原始函数的点乘式相乘的积分。我们可以简单地将第三个函数理解为“一个矩阵上的滑动窗口函数”。
图片来源:deeplearning.stanford.edu/wiki/index.php/Feature_extraction_using_convolution
如上图所示,绿色表示的是滑动窗口,红色的是滑动窗口矩阵,输出的结果是带有卷积特性的矩阵。下图是两个方形脉冲的卷积及其输出结果。
图片来源:维基百科
Jeremy Howard在他的MOOC课程里,利用一个Excel表格很好地解释了“卷积”。f和g两个矩阵的卷积输出是第三个矩阵卷积的第一层,也是这两个矩阵的点乘结果。这两个矩阵的点乘结果是下图所示的“标量矩阵”,也是一个数学函数的来源。
两个矩阵的点乘结果
像Jeremy一样,我们也来利用Excel表格。我们输入的矩阵是函数f(),滑动窗口矩阵是函数g()。两个函数的点乘结果是表格中的两个矩阵的和积,如下图所示:
两个矩阵的卷积
接下来,我们把这个规律用到大写字母A的一张图像。大家都知道,所有图像都是由像素构成的。因此,我们输入的矩阵f是“A”,把滑动窗口函数定为任意的矩阵g。然后,我们就得到了两个函数的点乘结果,如下图:
何为“卷积神经网络”?
图片来源: cs231n.github.io/convolutional-networks/
在我看来,一个简单的卷积神经网络CNN是所有层的一个序列。每一层都有一些特定的函数。每个卷积层都是三维的,所以我们用体积来作为度量标准。再进一步,卷积神经网络的每一层都会通过一个可微函数来将激活量转化为另一个,这个函数叫做“激活”或者“转化函数”。
“卷积神经网络”包含的不同实体分别是:输入层、过滤器(或内核)、卷积层、激活层、聚积层、批处理层。虽然这些层的组合排列各异,但是在不同的排列中还是存在一些规律的,给我们提供了不同的深度学习架构。
输入层:一般情况下,我们输入至“卷积神经网络”的通常是一个n维数组。如果是一张图像,我们有彩色通道的三维输入——长、宽、高。
图片来源: http://xrds.acm.org/blog/2016/06/convolutional-neural-networks-cnns-illustrated-explanation/
过滤器(或内核):如下图所示,一个过滤器或内核会滑动到图像的所有位置,将一个新像素作为所有像素的加权总和来进行计算。正如上面Excel表格的示例,我们的过滤器g移动到了输入的矩阵f处。
来源: intellabs.github.io/RiverTrail/tutorial/
卷积层:输入矩阵的点乘结果与内核共同创造出的新矩阵就是“卷积矩阵”,也被称作“卷积层”。
来源: https://docs.gimp.org/en/plug-in-convmatrix.html
下面这张非常清晰的视觉图表能够帮助你能更好地了解卷积填充和卷积转置的具体过程:
来源: https://github.com/vdumoulin/conv_arithmetic
激活层:“激活函数”能分成两类——“饱和激活函数”和“非饱和激活函数”。
sigmoid和tanh是“饱和激活函数”,而ReLU及其变体则是“非饱和激活函数”。使用“非饱和激活函数”的优势在于两点:
1.首先,“非饱和激活函数”能解决所谓的“梯度消失”问题。
2.其次,它能加快收敛速度。
Sigmoid函数需要一个实值输入压缩至[0,1]的范围
σ(x) = 1 / (1 + exp(−x))
tanh函数需要讲一个实值输入压缩至 [-1, 1]的范围
tanh(x) = 2σ(2x) − 1
ReLU
ReLU函数代表的的是“修正线性单元”,它是带有卷积图像的输入x的最大函数(x,o)。ReLU函数将矩阵x内所有负值都设为零,其余的值不变。ReLU函数的计算是在卷积之后进行的,因此它与tanh函数和sigmoid函数一样,同属于“非线性激活函数”。这一内容是由Geoff Hinton首次提出的。
ELUs
ELUs是“指数线性单元”,它试图将激活函数的平均值接近零,从而加快学习的速度。同时,它还能通过正值的标识来避免梯度消失的问题。根据一些研究,ELUs分类精确度是高于ReLUs的。下面是关于ELU细节信息的详细介绍:
图片来源: http://image-net.org/challenges/posters/JKU_EN_RGB_Schwarz_poster.pdf
图片来源:维基百科
Leaky ReLUs
ReLU是将所有的负值都设为零,相反,Leaky ReLU是给所有负值赋予一个非零斜率。Leaky ReLU激活函数是在声学模型(2013)中首次提出的。以数学的方式我们可以表示为:
图片来源:《卷积网络中整流激活函数的实证评估》
上图中的ai是(1,+∞)区间内的固定参数。
参数化修正线性单元(PReLU)
PReLU可以看作是Leaky ReLU的一个变体。在PReLU中,负值部分的斜率是根据数据来定的,而非预先定义的。作者称,在ImageNet分类(2015,Russakovsky等)上,PReLU是超越人类分类水平的关键所在。
随机纠正线性单元(RReLU)
“随机纠正线性单元”RReLU也是Leaky ReLU的一个变体。在RReLU中,负值的斜率在训练中是随机的,在之后的测试中就变成了固定的了。RReLU的亮点在于,在训练环节中,aji是从一个均匀的分布U(I,u)中随机抽取的数值。形式上来说,我们能得到以下结果:
下图是ReLU、Leaky ReLU、PReLU和RReLU的比较:
图片来源 :https://arxiv.org/pdf/1505.00853.pdf
PReLU中的ai是根据数据变化的;Leaky ReLU中的ai是固定的;RReLU中的aji是一个在一个给定的范围内随机抽取的值,这个值在测试环节就会固定下来。
噪声激活函数
这些是包含了Gaussian噪声的激活函数,下图能帮助你了解“噪声”是如何与激活函数相结合的:
图片来源:维基百科
聚积层
“聚积层”的目的就是通过逐渐缩减矩阵的空间大小,减少参数和网络内计算的数量,进而控制过度拟合。“聚积层”在输入中独立运行,然后利用最大值或平均值的操作来调整输入矩阵的空间大小。“聚积层”最常见的形式就是带有应用于输入的两个样本中的2x2过滤器的“聚积层”。在这种形式中,每一次最大值操作都会取超过4个的最大数量,深度维数保持不变。更常见的“聚积层”如下图:
图片来源: http://cs231n.github.io/convolutional-networks/#pool
图片来源: https://ujjwalkarn.me/2016/08/11/intuitive-explanation-convnets/
注意:这里我们把2 x 2窗口移动了两个单元格,然后取每个区域的最大值。
批规范化层
“批规范化”是将每个过渡层,包括激活函数,标准化的有效方法。“批规范化”操作的两个主要优点是:
1.在一个模型中添加“批规范”能够加快训练的速度
2.规范化操作大大降低了少数外围输入对训练的制约影响,同时减少了过度拟合的发生。
Jeremy的网络公开课中有更多关于“批规范化”的细节。
全连接层
“全连接层”是一个传统的“多层感知器”,这个感知器在输出层中使用了一个“柔性最大值激活函数”。顾名思义,“全连接”意味着上一层的每一个神经元都与下一层的每个神经元相连接。一个“柔性最大值函数”是逻辑函数的泛化,该函数将一个任意实值的K维向量转化为一个实值在(0,1)范围之间的K维向量。
图片来源:维基百科
“柔性最大值激活函数”一般被用于最后的全连接层,获取实值在0到1之间的概率。现在,我们对“卷积神经网络”中的不同层已经有所了解了,那么具备了这些知识,我们就能建立起肺癌检测所需的深度学习架构了。关于肺癌检测的深度学习架构,我们将在下一篇文章中讨论。
本文将从卷积神经网络的角度讨论深度学习。在本文中,我们将使用Keras和Theano,重点关注深度学习的基本原理。本文将展示两个例子——其中一个例子使用Keras进行基本的预测分析,另外一个使用VGG进行图像分析。
我们谈论的话题其实是相当广泛和深入的,需要更多的文章进行探讨。在接下来的一些文章中,我们将会讨论医学影像中DICOM和NIFTI格式之间的不同,并且研究如何使用深度学习进行2D肺分割分析。除此之外,我们还将讨论在没有深度学习时,医学图像分析是如何进行的;以及我们现在如何使用深度学习进行医学图像分析。在这里,我非常欢迎和感谢我的新伙伴Flavio Trolese——4Quant的联合创始人和ETH Zurich的讲师——他将协助我整合所有讨论的内容。
在本文中,我们将讨论Keras并且展示两个示例——其中一个使用Keras完成简单的预测性分析任务,另一个进行图像分析。
何为Keras?
根据Keras官网的介绍,Keras是Theanos和Tensor Flow的一个深度学习库。
运行于Theano和TensorFlow之上的Keras api
Keras是一个高级Python神经网络API,它能够运行于TensorFlow和Theano之上。Keras的开发重点在于支持快速实验。
何为Theano和Tensor Flow?
James Bergstra教授等人在2010年的Scipy曾说,Theano是一个CPU和GPU的数学表达式编译器。换句话来说,Theano是一个能够让你高效地对数学表达式进行定义、优化和评估的Python学习库。Theano是由一些高级研究人员,如Yoshua Bengio,和“蒙特罗学习算法研究所”(MILA)共同研发的。下图是发布于2010年Scipy上的Theano教程,图中对比了Theano下的GPU和CPU与当年其他的工具。这张图片发表于原创论文——《Theano——CPU和GPU的Python数学编译器》。
《Theano——CPU和GPU的Python数学编译器》作者:James Bergstra, Olivier Breuleux, Frédéric Bastien, Pascal Lamblin, Razvan Pascanu, Guillaume Desjardins,Joseph Turian, David Warde-Farley, Yoshua Bengio
建立在Theano之上的还有一些其他的深度学习库,包括Pylearn2、GroundHog(同样是由MILA开发的)、Lasagne和Blocks and Fuel等。
《使用Theano计算的透明GPU》——James Bergstra
TensorFlow是由“谷歌机器智能研究所”组织下的“谷歌大脑”团队研发完成的。TensorFlow的开发是为了进行机器学习和深度神经网络的研究,除此之外,它还广泛适用于其他的领域。根据TensorFlow官网介绍,TensorFlow是一个使用数据流图表进行数值计算的开源软件库。图表中的节点代表数学运算,而表格边缘则代表沟通节点的多维数据数组(tensors)。其中的代码视觉上正如下图所展示的:
图片来源:《TensorFlow:异构分布系统上的大规模机器学习》
使用Keras进行预测性分析的示例
在本文中,我们将使用来自UCI网站的Sonar数据集来完成一个简单的预测模型示例。在下面的代码中,我们直接从UCI网站获取数据,并将这些数据按照60::40的比例分为训练数据和测试数据。我们使用Keras进行预测建模,使用sklearn对标签进行编码。
在下一个代码片段中,我们使用之前定义好的函数来读取数据集中的数据。打印数据集之后,我们会发现我们的独立变量是需要进行编码的。
我们使用来自Scikit-learn的LabelEncoder(标签编码器)对标签进行编码,将字母R和M分贝转换为数字0和1。一种热编码还将分类特征转换成为了一种与算法更合适的格式。在这个示例中,我们的Y变量与R和M一样是分类对象,使用标签编码器,我们将这些字母变量转换为了1或0。
Scikit-learn的标签编码器
之后,我们创建了一个使用Keras的模型:
在没有任何预处理操作的情况下,使用简单模型的准确度为81.64%
使用Keras进行图像分析的示例
为了更好地用Keras解释图像处理过程,我们将使用来自“Kaggle猫狗竞赛”的数据。这个竞赛的目的是开发一个能够用来区分图像中包含的是一只狗还是一只猫的算法。对于人类来说,区分猫狗是很简单的,但对于计算机来说可就复杂的多了。在这项“区分猫狗”的挑战中,有25000张标记了猫狗的训练图片,测试数据库中还有12500张等着我们去标记。根据Kaggle官网,当这个竞赛开始时(2013年年底):
“目前的文献表明,机器分类器在这个任务上的准确度能达到80%以上。”因此,如果我们能成功突破80%的准确度,我们就能跃居2013年的技术发展最前沿。
想要了解更多细节、进行下一步的学习或对深度学习进行尖端研究,我强烈推荐Fast.ai的网络公开课程。我在下面的代码中引用了fast.ai,它为我们的学习提供了一个很好的起点。
第一步:完成设置
从Kaggle网站上下载猫、狗的图片数据,将其保存在你的电脑上。在本文提到的示例中,我会在我的iMac电脑上运行代码。
基本的设置
Jeremy Howard提供了一个Python实用文件,帮助我们获取已封装的基础函数。我们要做的第一步就是使用这个实用文件。下图就是这个实用文件。随着细节的深入,我们将一步步打开这个文件,看看隐藏在文件背后的信息。
第二步:使用VGG
我们在第一步中简单地使用了一个完全为我们建立的模型,这个模型能够识别各种各样的图像。第二步,我们将使用VGG。VGG是一个非常容易创建和理解的模型,它赢得了2014年的“ImageNet挑战赛”。VGG imagenet团队创建了两个模型——VGG 19和VGG 16。VGG 19是一个大型的、操作性能慢的、准确度稍佳的模型;而VGG 16是一个小型的、操作性能快的模型。我们将会使用VGG 16,因为VGG 19的操作性能比较慢,通常不值得在精确度上再做改进。
我们建立了一个Python类——Vgg16。Vgg16能让VGG 16模型的使用更加简单。在fast.ai的github上同样能找到Vgg16,具体细节如下图:
第三步:实例化VGG
Vgg16建立于Keras(我们将在稍后讨论更多关于Keras的内容)之上。Keras是一个灵活的、易于使用的、建立在Theano和TensorFlow上的深度学习库。Keras使用一个固定的目录结构来分批查看大量的图像和标签,在这个目录结构下,每一类训练图像都必须放置在单独的文件夹里。
下面是我们从文件夹中随意抓取的数据:
第四步:预测猫、狗
第五步:将图像和代码文件汇总
为了汇总这些图像和文件,我推荐的方法如下图:
总结:
阅读到这里,就证明你就已经采纳了我们在上一篇文章中讨论的理论,并做了一些实际的编程。如果你按照上面的指示和说明完成了两个示例,那么你就已经成功建立了你的第一个预测模型,并完成了图像分析。