计算机系统应用教程网站

网站首页 > 技术文章 正文

Tensorflow中的卷积神经网络 tensorflow 卷积神经网络

btikc 2024-10-12 11:39:14 技术文章 4 ℃ 0 评论

最令人兴奋的深度学习领域之一是计算机视觉。通过卷积神经网络的最新进展,我们已经能够创造出自动驾驶汽车,面部检测系统和自动医学图像分析,这些都是专家们的专长。在本文中,我将向您展示卷积神经网络的基础知识,以及如何自己创建一个来对手写数字进行分类。

与许多深度学习领域不同,卷积神经网络与人类大脑的生物功能非常接近。早在1959年,David Hubel和Torsten Wiesel对猫和猴进行了研究,这些研究揭示了视觉皮层的功能。他们发现,许多神经元有一个小的局部接受区,只对整个视野中有限的小区域作出反应。他们发现,某些神经元对水平较低的图案,如水平线、垂直线和其他圆形图案有反应。他们还认识到,其他神经元有更大的接受区,并受到更复杂的模式的刺激,这些模式是由较低层次的神经元收集的信息的组合。这些发现为我们现在所说的卷积神经网络奠定了基础。让我们一个一个地分解构成单元。

1.卷积层

每个卷积层由若干特征图构成,这些特征图通过filters 馈送信息,filters 检测诸如水平线或垂直线之类的特征。您可以将每个filter描绘成一个窗口,该窗口在图像的尺寸上滑动并检测属性。filters 在图像上移动的量称为步幅。步幅为1意味着filter一次移动一个像素,因为2的步幅将跳过2个像素跳过。

在上面的例子中,我们有一个垂直线检测器。原始图像为6x6,使用3x3滤镜进行扫描,步长为1,从而产生4x4尺寸输出。过滤器仅对其视野左右列中的部分感兴趣。通过将图像的输入乘以3x3 filter的配置,我们得到3 + 1 + 2 -1 -7-5 = -7。然后filter向右移动一步,然后计算1 + 0 + 3 -2-3-1 = -2。-2然后进入-7右侧的位置。此过程将持续到4x4网格完成为止。然后,下一个要素图将使用它自己的唯一filter/内核矩阵计算自己的值。

2.池化层

池化层的目标是通过池化卷积层收集的值或所谓的子采样来进一步降低维度。这将减少计算负荷,并为您的机器学习模型提供一些正则化,以避免过度拟合。它们遵循与conv层相同的滑动窗口思想,而不是计算它们选择其输入的最大值或平均值的所有值。这分别称为最大池化和平均池化。

这两个组件是卷积层的关键构建块。然后,您通常会重复此方法,进一步减少特征图的尺寸,但会增加其深度。每个特征图将专门识别它自己独特的shape。在卷积结束时,您将放置一个全连接层,其具有激活函数,例如Relu或Selu,用于将尺寸reshape为适合送入分类器的矢量。例如,如果您的最终转换层输出3x3x128矩阵,但您只预测10个不同的类,则需要将其reshape为1x1152向量,并在输入分类器之前逐渐减小其大小。完全连接的层也会学习它们自己的函数,就像典型的深度神经网络一样。

现在让我们看看在MNIST手写数字数据集上的Tensorflow中的实现。首先,我们将加载我们的Python库。使用sklearn中的fetch_mldata,我们加载mnist数据集并将图像和标签分配给X和y变量。然后我们将创建我们的训练/测试数据集。最后,我们将举几个例子来了解未来的任务。

正如您所看到的,有一些具有挑战性的例子。右侧都是1。

接下来,我们将进行一些数据扩充,这是提高模型性能的可靠方法。通过创建训练图像的轻微变化,您实际上可以为模型创建正则化。我们将使用scipy的ndimage模块将图像向右,向左,向上和向下移动1个像素。这不仅提供了更多种类的例子,而且还会大大增加我们训练集的大小,这通常总是一件好事。

我将向您展示的最后一种数据扩充形式是使用cv2库创建图像的水平翻转。我们还需要为这些翻转图像创建新标签,这与复制原始标签一样简单。

设置“flipCode = 0”将产生垂直翻转。

接下来,我们将创建一个辅助函数,将随机的小批量输入到我们的神经网络输入中。由于卷积层的性质,它们在向前和向后遍历步骤中需要大量的内存。考虑一个带有4x4过滤器的层,输出128个具有1步长和相同填充的feature map, RGB图像输入的尺寸为299x299。参数的数量将相等(4x4x3 + 1)x 128 = 6272.现在考虑这128个特征图中的每一个都计算299x299个神经元,并且这些神经元中的每一个都计算4x4x3输入的加权和。现在是4x4x3x299x299x150 = 643,687,200次计算。这只是一个训练的例子。你可以想象这很快就会失控。解决这一问题的方法是,使用python生成器一次向网络提供小批量的内容,这种生成器本质上是在需要项之前将其保存在内存之外。

我们准备开始创建我们的神经网络架构。首先,我们为我们的训练数据/标签创建占位符。我们将需要将它们reshape为(-1,28,28,1)矩阵,因为tensorflow conv2d层需要4维输入。我们将第一个维度设置为“无”,以允许将任意批量大小提供给占位符。

现在我们将设计我们的卷积层。我将从Le-NET5(由Yann LeCun开创)网络架构中获取灵感,该架构因其在手写数字分类方面的成功而闻名。然而,有很多事情我做了不同的事情。我建议您研究Le-NET5以及其他经过验证的模型,以了解哪种卷积网络适用于不同的任务。

第一层由12个特征图组成,使用3x3 filter,步幅为1.我们选择了SAME填充,通过在输入周围添加一个零填充来保持图像的尺寸。然后,我们应用最大池化层与另一个3x3 filter和步长为2,将输出13x13x12矩阵。所以我们从一个28x28x1的图像开始,并且生成的filter maps 的尺寸小于其尺寸的一半但深度更深。然后我们将这个矩阵传递给第二个conv 层,它具有深度为16,3x3 filter,stride = 1和padding SAME ,与之前相同的最大池化层。这输出一个6 * 6 * 16维矩阵。您可以看到我们正在缩小特征图的维度空间,但要更深入。这是我们学习的地方,在第一层把较低层次的图组合起来,在第二层形成更复杂的图。接下来,我们通过将其reshape为由6x6x16 = 576值组成的1维行向量来准备全连接层的输出。我们使用Selu激活的两个dense 层来减少每层输入的数量大约一半,直到最终将它们输入我们的logits,这将输出10个预测。

我们创建了我们的损失函数,在这种情况下,它将是softmax交叉熵,它将输出多类概率。您可以将交叉熵视为各种数据点之间距离的度量。我们选择AdamOptimizer,当它向下移动梯度时自动调整它的学习率。最后,我们创建了一种评估结果的方法。in_top_k将计算我们的logits并选择最高分。然后我们使用我们的准确度变量输出0-1之间的值。

现在我们已经为训练阶段做好了准备。首先,我将训练模型。让我们看看我们的机器学习模型表现得如何。

在第19 epoch,我们达到最高百分比正确在0.9907。这已经比任何机器学习算法的结果更好,因此卷积已经取得了领先。现在让我们尝试使用我们的移位特征/翻转特征,并为我们的网络添加两个新元素。dropout和批归一化。

我们使用placeholder_with_default节点修改现有占位符,这些节点将保存批归一化和Dropout层生成的值。在训练期间,我们将这些值设置为True,在测试期间,我们将通过设置为False将其关闭。

批归一化只是简单地对每批次的数据进行中心化和归一化。我们指定了0.9的momentum 。Drop out正则化指定概率(在我们的情况下为1 -0.5)以在训练期间完全随机地关闭节点。想象一下,一家公司决定每周随机选择50名员工留在家里。其余的工作人员将不得不有效地处理额外的工作,提高他们在其他领域的技能。不确定这会在现实生活中起作用,但在深度学习中它已被证明是有效的。

我们像以前一样创建我们的损失,训练和评估步骤,然后对我们的执行阶段进行一些修改。通过批归一化化执行的计算在每次迭代期间保存为更新操作。为了访问这些,我们分配一个变量extra_update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)。在我们的训练操作期间,我们将其作为列表项与training_op一起提供给sess.run。最后,在执行验证/测试预测时,我们通过feed_dict为占位符分配False值。我们不会在预测阶段进行任何随机化。为了获得输出,我们使用我们的测试集运行logits操作。让我们看看这个模型现在表现得如何,我们已经添加了正则化/归一化并且正在使用增强特征。

在29 epoch,我们在10,000个数字的测试集上达到了99.5%的准确率。正如你所看到的那样,只有第二个epoch的模型精确度达到了99%,而之前的模型只有16个精度。虽然0.05%听起来可能不是很多,但在处理大量数据时这是一个重大改进。最后,我将向您展示如何在logits输出上使用np.argmax提取预测。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表