2023年12月11日发(作者:粗线条)
卷积神经网络(CNN)mnist手写字python源代码详解
首先介绍下卷积神经网络
输入层我就不讲了,我主要根据代码讲下卷积层,池化层,全连接层。
(一)
卷积层
'''
-1代表着矩阵行不确定我这里用n表示,[-1,28,28,1]的意思是n行28列,
它的子元素是一个28行1列的矩阵,例如
[[[[1]], [[1]], [[1]], [[1]]],
[[[1]], [[1]], [[1]], [[1]]]]
可以表示为【2,4,1,1】它的子元素[[1]]为1行1列。在这里这个1也可以理解为通道数为1
'''
x_image = e(x, [-1, 28, 28, 1])
'''
w_conv1代表着filter【5,5】为卷积核大小,1为通道数,32为卷积核的个数,卷积核个
数的选取需要凭经验,也许有大神知道一定的规律,这里我讲一下卷积核的通道数为什么需
要和输入的通道数一样,其实原理很简单,我们需要x_image和w_conv1相乘,也就需要它们两
个的子元素相乘,上边已经说过x_image的子元素为【28,1】,要想两者相乘,则w_conv1
子元素必须为【1,n]
'''
w_conv1 = weight_variable([5, 5, 1, 32])
卷积的计算包括两部分,输入和filter
卷积的计算(注意,下面蓝色矩阵周围有一圈灰色的框,那些就是上面所说到的填充值)
蓝色的矩阵(输入图像)对粉色的矩阵(filter)进行矩阵内积计算并将三个内积运算的结果与偏置值b相加(比如上面图的计算:2+(-2+1-
2)+(1-2-2) + 1= 2 - 3 - 3 + 1 = -3),计算后的值就是绿框矩阵的一个元素。下面的动态图形象地展示了卷积层的计算过程:
代码中我们需要定义一个方法,来实现卷积
def conv2d(x, w):
b = 2d(x, w, strides=[1, 1, 1, 1], padding='SAME')
return b
卷积运算后,输出图片尺寸缩小;
越是边缘的像素点,对于输出的影响越小,因为卷积运算在移动的时候到边缘就结束了。中间的像素点有可能会参与多次计算,但是边缘像
素点可能只参与一次。所以我们的结果可能会丢失边缘信息。
那么为了解决这个问题,我们引入padding, 什么是padding呢,就是我们认为的扩充图片, 在图片外围补充一些像素点,把这些像
素点初始化为0.
① SAME
输出大小等于输入大小除以步长向上取整,s是步长大小;
我们这里的输入大小为28
28的图像,filter 大小为5
5, 步长strides 为1所以输出大小也为28
28,下面给出图解
假设我们输入矩阵为
我们先把矩阵扩充为
然后再与filter进行卷积运算,这样做是为了保留边界信息,否则的话我们的边界只进行了一次运算,而内部进行了多次
② VALUE
输出大小等于输入大小减去滤波器大小加上1,最后再除以步长(f为滤波器的大小,s是步长大小)。假设我们输入大小为28
28,步长为
1,filter为5
5,那么输出大小为24
24,图片有所缩小。
**(二)**激励层
把卷积层输出结果做非线性映射。
主要是增强输入输出之间的拟合性,
CNN采用的激励函数一般为ReLU(The Rectified Linear Unit/修正线性单元),它的特点是收敛快,求梯度简单,但较脆弱。代码如下
h_conv1 = (conv2d(x_image, W_conv1) + b_conv1)
**(三)**池化层
池化层夹在连续的卷积层中间, 用于压缩数据和参数的量,减小过拟合。
简而言之,如果输入是图像的话,那么池化层的最主要作用就是压缩图像。
这里再展开叙述池化层的具体作用。
1. 特征不变性,也就是我们在图像处理中经常提到的特征的尺度不变性,池化操作就是图像的resize,平时一张狗的图像被缩小了一倍
我们还能认出这是一张狗的照片,这说明这张图像中仍保留着狗最重要的特征,我们一看就能判断图像中画的是一只狗,图像压缩时
去掉的信息只是一些无关紧要的信息,而留下的信息则是具有尺度不变性的特征,是最能表达图像的特征。
2. 特征降维,我们知道一幅图像含有的信息是很大的,特征也很多,但是有些信息对于我们做图像任务时没有太多用途或者有重复,我
们可以把这类冗余信息去除,把最重要的特征抽取出来,这也是池化操作的一大作用。
3. 在一定程度上防止过拟合,更方便优化。
池化层用的方法有Max pooling 和 average pooling,而实际用的较多的是Max pooling。
这里就说一下Max pooling,其实思想非常简单。
对于每个2
2的窗口选出最大的数作为输出矩阵的相应元素的值,比如输入矩阵第一个2
2窗口中最大的数是6,那么输出矩阵的第一个元素
就是6,如此类推。
(四)全连接层
全连接层在我看来不大好理解,下面给出我自己的理解,全连接层的目的是将网络学习到的特征映射到样本的标记空间中。全连接层会把卷
积输出的二维特征图(featureMap)转化成一个一维的向量。本案例中我们进行了2次卷积,最后得到了64个7
7的二维特征图
(featureMap),我们需要把它转化为一维的,即7
7*64,代码如下
h_pool2_flat = e(h_pool2, [-1, 7*7*64]) #reshape成向量
W_fc1 = weight_variable([7 * 7 * 64, 1024]) #1024代表卷积个数,我们可以任意取
b_fc1 = bias_variable([1024])
h_fc1 = ((h_pool2_flat, W_fc1) + b_fc1)
这里我给个例子帮助你们理解e(),请看代码
import numpy as np
import tensorflow as tf
input = le([[[[1]], [[1]], [[1]], [[1]]],
[[[1]], [[1]], [[1]], [[1]]]], dtype=float)
b = e(input, [1, 8])
print((input))
print((b))
运行结果为, 从结果中我们可以看出,转换规则为,2
4
1
1=1
8
同理,因为我们全连接层的输入,就是卷积层的输出,我们经过两次卷积后的输出为h_pool2= [-1, 7, 7, 64],为什么是-1,是因为我们最
初的输入x_image = [-1, 28, 28, 1] , -1 代表着行数不确定。
h_pool2_flat = e(h_pool2, [-1, 7*7*64]) #reshape成向量
我们就把 [-1, 7, 7, 64]转换为 [-1, 7
7
64]。
谨记,全连接层不是卷积层,所以这里是
h_fc1 = ((h_pool2_flat, W_fc1) + b_fc1)
我们用()只是把得到的特征值与权重w相乘再加上偏执b。
最后我们需要加上,
keep_prob = older("float")
h_fc1_drop = t(h_fc1, keep_prob)
t()是tensorflow里面为了防止或减轻过拟合而使用的函数,它一般用在全连接层
最后给出我们整个运算过程并附上代码。
代码
import tensorflow as tf
import tensorflow as tf
import _data as input_data
mnist = input__data_ts("MNIST_data/", one_hot=True)
x = older(32, [None, 784]) # 占位用,因为图片大小为28*28,所以为784,
# 但是我们并不清楚有多少副,所以设为None,后续来添加
y_actual = older(32, shape=[None, 10]) # 同理占位用,因为我们要测的是0-9一共10个数,即一共10个类别
'''
ted_normal(shape, mean, stddev) :shape表示生成张量的维度,mean是均值,stddev是标准差。
这个函数产生正太分布,均值和标准差自己设定。就是说产生正太分布的值如果与均值的差值大于两倍的标准差,那就重新生成。
和一般的正太分布的产生随机数据比起来,这个函数产生的随机数与均值的差距不会超过两倍的标准差,但是一般的别的函数是可能的。
谨记 filter中的值是经过训练后确定的(代表着权重w)
'''
def weight_variable(shape):
initial = ted_normal(shape, stddev=0.1)
return le(initial)
# 偏置b
def bias_variable(shape):
initial = nt(0.1, shape=shape)
return le(initial)
# 卷积
def conv2d(x, w):
return 2d(x, w, strides=[1, 1, 1, 1], padding='SAME')
# 池化层
def max_pool(x):
return _pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
x_image = e(x, [-1, 28, 28, 1])
'''
w_conv1代表着filter【5,5】为卷积核大小,1为通道数,32为卷积核的个数,卷积核个
数的选取需要凭经验,也许有大神知道一定的规律,这里我讲一下卷积核的通道数为什么需
要和输入的通道数一样,其实原理很简单,我们需要x_image和w_conv1,也就表示它们两
个的子元素相乘,上边已经说过x_image的子元素为【28,1】,要想两者相乘,则w_conv1
子元素必须为【1,n]
'''
w_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])
h_conv1 = (conv2d(x_image, w_conv1) + b_conv1)
h_pool1 = max_pool(h_conv1)
w_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])
h_conv2 = (conv2d(h_pool1, w_conv2) + b_conv2)
h_pool2 = max_pool(h_conv2)
'''
7*7*64表示7*7的图片64个,也就表示一共有7*7*64个特征值(包含0),1024是实际上的特征值,使我们需要保留的
'''
w_fc1 = weight_variable([7*7*64, 1024])
w_fc1 = weight_variable([7*7*64, 1024])
b_fc1 = bias_variable([1024])
h_pool2_flat = e(h_pool2, [-1, 7*7*64])
h_fc1 = ((h_pool2_flat, w_fc1) + b_fc1)
'''
Dropout就是在不同的训练过程中随机扔掉一部分神经元。也就是让某个神经元的激活值以一定的概率p,
让其停止工作,这次训练过程中不更新权值,也不参加神经网络的计算。但是它的权重得保留下来(只是暂时不更新而已),
因为下次样本输入时它可能又得工作了,keep_prob表示丢弃的概率
'''
keep_prob = older("float")
h_fc1_drop = t(h_fc1, keep_prob)
w_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])
y_predict = x((h_fc1_drop, w_fc2) + b_fc2)
cross_entropy = -_sum(y_actual * (y_predict)) # 根据公式求和
train_step = ntDescentOptimizer(1e-3).minimize(cross_entropy) # 梯度下降法寻找最优解,训练时,不断的调整权重w
correct_prediction = ((y_predict, 1),
(y_actual, 1)) # 返回的true或fal,返回的是最大值的下标,
# 0表示按列来,1表示按行来
accuracy = _mean(
(correct_prediction, "float")) # dtype = float可以把bool(True or Fal)类型转化为float类型(数据),
# _mean()求平均值,同样,0表示对列求平均,1表示对行求平均,既没有0也没有1的话对整个矩阵求平均
ss = ctiveSession()
(_variables_initializer())
for i in range(20000):
batch = _batch(50)
if i % 100 == 0: # 训练100次,验证一次
train_(feed_dict={x: batch[0], y_actual: batch[1], keep_prob: 0.5})
test_acc = (feed_dict={x: , y_actual: , keep_prob: 1.0})
print("test accuracy %g" % test_acc)
本文发布于:2023-12-11 19:01:50,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/zhishi/a/1702292510118512.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:卷积神经网络(CNN)mnist手写字python源代码详解.doc
本文 PDF 下载地址:卷积神经网络(CNN)mnist手写字python源代码详解.pdf
留言与评论(共有 0 条评论) |