深度学习简介:学习卷积神经网络项目
加载数据
首先我们需要下载数据。 Tensorflow为我们提供了可下载的功能。这个函数read_data_sets
这个函数函数read_data_sets很简单。检查目录中的文件并下载它们。如果有,分析并加载它们。一方面,方便我们获取数据。不过我们直接从盒子里拿出来还是很方便的。不过,由于这个默认下载地址需要绕过防火墙,所以我会提供一个不需要绕过防火墙的地址。您只需加载以下函数
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("input/", one_hot=True, source_url="http://yann.lecun.com/exdb/mnist/")
,稍等几分钟,数据就会下载到当前目录input
文件夹中,这样下次运行时就可以加载图像数据了。直接到本地文件夹
观看数据
首先,查看您下载了哪些数据。打开 input
文件夹。我们可以看到Tensorflow给我下载了四个文件,并将它们分为两组,一组训练集和一组测试集。每组有2个文件,一个是手写图像文件,一个是标签文件(每张手写图像所表示的数字)
加载图像数据对于新手来说是相当有问题的。为了专注于模型而不是编程,Tensorflow 帮助您直接加载数据。其中存储了上面得到的变量mnist
。项目需要的数据,我们看看这个mnist
包含了哪些mnist
。我们推荐笔记本
操作数据集,首先mnist
训练数据是什么
mnist❙❙将图像上面的数据从每个像素值分成两个像素,然后放入一个数组中,每个图像对应一个数组。 .train.images 是一个 A (55000, 784) 二维数组,其中 dimensionmnist.train.s 是两个
(55000, 10)
,现在阿美就在眼前,其实很简单。我们通过图像像素值55000
来训练我们的模型,因此模型可以提供图像像素值来预测图像所代表的数字。
人们很容易识别这些数字。但计算机如何识别他呢?这需要利用卷积神经网络的力量。卷积神经网络,计算机的准确率可以达到99%,这是非常可怕的。我们人类有时候会犯错误
在说卷积之前,先说一下我们之前的做法,这样我们可以通过对比来了解卷积优化达到了什么效果
传统做法
其实从传统的角度来看,看,形象识别,判断图像的含义,通过其值来表征图像的特征,但是图像很特殊,相对于其他机器学习问题来说,它有很多特征值。这里我们使用具有 784 个特征的 28x28 图像。如果我们的图像尺寸比较大,那么这个特征的价值就会非常大,而且我们知道机器学习需要大量的数据来展示它的能力,但是每张图像都非常巨大,训练一个巨大的数据集实在是太多了。计算机
所以我们需要减少数据的维度。机器学习中有很多降维方法,例如PCA、LDA等,但这些方法都存在一个问题。他们必须将图像视为完整输入,即将 28X28 转换为 784 数组。我们知道这个数组失去了一个非常重要的维度。仔细看上面的图片。
mnist数据源网络
事实上,我们关注的是每张图像中数字的二维分布。我们根据闭合圆圈的数量来区分8和0,根据中间空的部分来区分0和1。 ,所以我们希望能够用一种新的方法来确定图像的特征。一方面可以保存图像的空间信息,另一方面得到数据最终的一维结果(图像所代表的数字)。这就是卷积的引入。卷积从二维角度提取图像的特征。与传统的一维提取相比,它可以最大程度地保留图像的信息,并进行深度降维,但我总觉得自己没有深入理解。当我接触到这个项目的时候,突然从代码层面理解了卷积
先说一下吧。下面讲一下Tensorflow库的基础知识。由于Python有点慢,Tensorflow的后端全部用C++编写。你可以这样理解Tensorflow。相当于客户端的 Python。我们可以使用会话(响应)与服务器(C++)进行交互,这样的话我们既可以在客户端享受Python的方便和速度,也可以享受运行C++的效率,但这也是一个问题。事实证明,Python 是所见即所得的,现在我们可以运行一些东西了。必须使用会话来通知服务器运行。我们的很多中间过程都是未知的,只能根据返回的结果来推断。官方教程没有讲大部分中间过程,只是一口气走完了,所以为了更好地理解卷积神经网络,我们以一种丑陋的方式运行Tensorflow,但是从中我们可以理解卷积。过程。更彻底
所以基本上后续的每一次操作都会运行后端并分析返回的结果。为了便于描述,我们假设您将在初始化 让我们从这个项目开始逐行 我们已经知道,卷积的目的是提取所需的特征来自二维空间。首先,我们将数据简化为二维 x,也就是上面给出的数据。我们会检查。首先我们声明一个会话 ,然后我们从数据集中获取 50 张图像 然后我们就看到了。 shapesession.run
.run(tf.global_variables_initializer())之前运行此会话 。 A 我们想要运行它是因为我们使用会话来使用
C++
。如果我们不“声明”变量,c++会报告错误准备数据
x_image = tf.reshape(x, [-1,28,28,1])
session = tf.Session()
data = mnist.train.next_batch(50)[0]
data.shape, x_image_data.shape
(50, 784) (50, 28, 28, 1)
我们可以清楚地看到,我们已经成功地将一维数组图像(784)转换为二维数组图像,三维数组图像(28X28)。我们实际上创建了一个三维(28
好吧,现在我们已经成功地将一维图像转换回二维,是时候将它们卷起来了
第一层
如果你'学过一些信号处理,你会发现深度学习中使用的卷积实际上并不是原始意义上的卷积,它没有“旋转180”操作,但其形式实际上是相似的。这种“乘积”运算主要是利用矩阵运算来实现的。为了更好的理解卷积是如何工作的,从网上找到了前辈们辛苦搞定的动画图
卷积操作 - 来源网络
PS:这张图和我们的数据略有不同。每张图像只有一个颜色通道,而这张图像有三个颜色通道。在这张图中,有两个卷积核,但是我们的第一层将使用32个,但原理实际上是相同的。如果你真的不明白。你可以先看顶行
让我们回到这张图。最左边是图像输入,中间是卷积核,右边最后一个是输出。从图中很容易理解,我们可以清楚地看到卷积和我们平时的操作不同。我们首先输入二维数据,通过二维卷积核进行矩阵运算,最后输出二维结果。这就是卷积的力量。不仅保留了原始的二维信息,而且借助高效的矩阵运算可以加速特征提取
现在我们回到代码
首先是声明卷积核。我们可以使用简单的方法声明所有卷积核。它是一个全0矩阵,但是这会导致0梯度,所以我们添加一些噪声,看看添加噪声的卷积核的值是多少。声明一个函数 32 个 5X5X1 的随机卷积核看起来蛮随机的
PS:前面部分(5,5,1)代表输入的长、宽和颜色通道,后面部分代表输出的输出个数。当然我说的是32个,应该是32个矩阵(颜色通道数(当前维度为(5,5,1,32))
这个卷积核对应的是中间的小矩阵上图,它的长和宽都是5,图中的长和宽都是3,当然我们可以改变长和宽,以5作为经验值,这样大小的卷积核在模型。
接下来,我们执行最重要的卷积操作。如上图所示,要进行卷积,必须将三维数据与合适的卷积核进行卷积。其实我们从图中就可以看出。重要的是,卷积的步长是每一帧运动的位置(图中步长为2)
还有一个更隐秘的知识,你注意到图中显示的数据原来是7X7数据经过卷积核转换后变成3x3。卷积后图像的大小不仅受步长影响,还受帧大小的影响。如果您的帧为 7,则图像中仅保留一个值,因此我们避免减小尺寸。我们使用0的周围填充,使得边缘位置的卷积也成为帧的中心。一方面避免丢失边缘数据,另一方面还可以高亮边缘数据(环境全为0)
Tensorflow 也嵌入了以上方法。通过传递参数,我们可以修改组织者和填充方法。现在开始正式的“卷”吧
session.run(tf.global_variables_initializer())
v = session.run(tf.nn.conv2d(x_image, W_conv1, strides=[1, 1, 1, 1], padding='SAME'), feed_dict={x: data})
现在我们来看看卷好的成品v
形状
v.shape
(50, 28, 28, 32)
50 尺寸是50 2,(28张图片,8张),这是32的卷积核数量,50和32应该被修正,我们不难理解什么现在我们通过卷积核的“体积”来看看为什么图像仍然保持28X28。在知乎上也发现了这个问题。现在让我们通过实验来解决它
我们首先看一下tf。 nn.conv2d
函数接受四个参数,第一个图像,第二个卷积核,第三个步长和第四个卷积方法
第一个问题是在卷积之后你需要。没有0 padding的原因是SAME在图像周围填充0,所以我们得到28个设置(最后两位是输入,第一个是输入图像的数量,最后一个是图像的颜色通道) ,这里我们使用1步,我们尝试2步
v = session.run(tf.nn.conv2d(x_image, W_conv1, strides=[1, 2, 2, 1], padding='SAME'), feed_dict={x: data})
v.shape
(50, 14, 14, 32)
当然,输出图像将是28的1/2
然后我们将卷积的值扔进神经元函数。为了真实感,我们添加一个偏移量 b_conv1
def bias_variable(shape):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial)
b_conv1 = bias_variable([32])
这里我们使用 0.1 来初始化失真,然后将其放入神经元函数中。这里我们利用numpy数组的分布属性将b_conv1传递到所有28x28维度
h_conv1 = tf.nn.relu(tf.nn.conv2d(x_image, W_conv1, strides=[1, 1, 1, 1], padding='SAME') + b_conv1)
v = session.run(h_conv1, feed_dict={x: data})
v.shape
(50, 28, 28, 32)
我们可以看到,神经元函数经过卷积后生成的数据是(50X28X28X32),最终维度从1变成了32,所以我们要使用点的方法来降低数据维度。这里我们使用卷积池的方法
卷积池
从上面可以看到,选择最大的其实是非常容易的
h_pool1 = tf.nn.max_pool(h_conv1, ksize=[1, 2, 2, 1],
strides=[1, 2, 2, 1], padding='SAME')
这里的参数很简单我就不展示了。经过这次“减少”后,数据的维度将是 (50, 28, 28, 32) (50, 14, 14, 32),减少了 4 倍
此时高于我们的第一个卷积层。接下来是第二层卷积。为什么需要再次上弦? ,因为我们从上一层学到的东西还太少,需要加强学习。这一层和第一层没有什么区别,所以我们跳过这一层
直接粘贴代码(函数就不复制了,文档里有)
W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)
全连接层
完成两层之后层卷积后,我们的数据就变成了一个四维数组(50,7,7,64)。我们知道,我们的传统机器学习实际上是使用2D数组作为训练数据(X是特征,Y是样本),所以全连接层“解开”了卷积,这样以后就可以很容易地连接到传统机器学习。 ,并且必要的数据也显示在最终结果中。这也是二维的(统一预测一堆数据,所以我们这里称之为二维),但是这里要注意的是,全连接层不是输出层,所以我们可以设置输出维度,最后连接输出层并创建一个完全连接的执行层。这里我们看全连接层权重变量
W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])
这里声明全连接层权重变量 我们可以看到,这实际上是一个二维数组,维度为(3136,1024),第一维与输入维度相关,第二维与输出相关。 。之前,我们使用卷积运算 矩阵,运算非常有趣。其实我们之前就提到过。 PCA 是使用矩阵运算进行降维的实现。数据分为X(特征)和Y(数量)。经过一次矩阵运算后,能够实现数量保持不变,但特性发生变化,这是非常强大的。我们可以随意修改矩阵的参数来动态改变我们的特征数量 但是矩阵运算也有一定的局限性,就是两个运算的矩阵必须是前者的长度和后者。 。令读者惊讶的是,这与矩阵运算的特性有关。具体可以参见矩阵运算的相关信息 所以,要进行矩阵运算,我们首先要做的是我们需要改变输入 其实输出层和全连接层非常相似。我们只需将前面的变量转换为我们想要输出的值即可。缩放 在执行此输出层之前,我们首先需要创建一个 ,因为它与连接层的原理类似。输出层我就不详细展示了 我们可以看到我们最终的输出是什么 。最后得到一个有50个预测结果的二维数组(输出采用OneHot方法) 我们曾经在初始随机权重下得到输出结果,但这个结果显然是错误的。我们需要通过改变每一层的权重来修改模型,使模型越来越完美。越聪明越好,所以第一步就是“自我反省”,了解我们离真正的结果还有多远。 i错误,让模型“镜像并修正” 到这里基本上就差不多完成了。我们创建了一个闭环,预测->评估->校正->预测->...,只有我们能接受它的误差才能训练我们的模型,才能让它训练 如何使用 卷积神经网络是深度学习中非常重要的一部分。了解卷积是必要的你需要知道为什么使用卷积以及使用它的好处是什么。总而言之,卷积并不是一个很新鲜的东西。它在信号处理中的应用由来已久。然而在图像处理中,它在深度学习领域大放异彩,因为它可以保留图像尺寸信息。这也可以看作是“是金子总会发光的”。W_fc1
和偏移量b_fc1,我们可以看到多少❀,♼❀
value W_fc1
可以将第二个卷积层的输出变量转换为维度(50, 7764),所以直接session.run(tf.global_variables_initializer())
session.run(W_fc1).shape
(3136, 1024)
tf.nn.conv2d
来转换图像。在全连接层中,我们需要使用矩阵运算来转换我们的维度的形状,让它从四维变成二维,这样就可以用我们的权重矩阵来计算了。
W_fc1
很好用 tf.reshape W_fc1 ♼❀这里我们将计算出来的值直接放入激活函数中,完成全连接层功能
输出层
Dropout
层。这有效地避免了神经网络的过拟合问题。详细内容请阅读这篇论文keep_prob = tf.placeholder("float")
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])
y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
session.run(tf.global_variables_initializer())
session.run(y_conv, feed_dict={x:data, keep_prob:0.5}).shape
(50, 10)
反向传播
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
session.run(tf.initialize_all_variables())
for i in range(18000):
batch = mnist.train.next_batch(50)
if i%100 == 0:
train_accuracy = accuracy.eval(feed_dict={
x:batch[0], y_: batch[1], keep_prob: 1.0}, session=session)
print("step %d, training accuracy %g"%(i, train_accuracy))
if abs(train_accuracy - 1) < 0.01:
break
train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5}, session=session)
使用OneHot
方法,我们需要使用tf.argmax
来输出预测变量以获得我们想要的实数,经过20,000个ccura 9%训练后我们可以达到9%。此时,卷积神经网络就展现了它的威力总结
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。