暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MNIST数据集-单层卷积神经网络数值计算详解

大碗岛星期天下午的梦 2021-02-17
473

这是刚开始学习深度学习敲的第一篇代码,先学的原理,花了一个多月的时间,想着原理都理顺了,代码还不简单吗。上来就敲卷积神经网络,结果就像看天书一样,每一行代码都需要百度,三十行代码断断续续百度了一个月,放弃了。开始反思,开始正视tensorflow这个工具,并不是会python,就可以玩的转。事实上tensorflow提供了C++ ,go等等语言的api,不是python的专属包,像numpy、panada调用一样,甚至已经不是python的语法,也没有了代码补全,简直灾难。于是,那就从头学起吧,从创建一个变量,到加减乘除,从机器学习,到神经网络,然后就到了今天,单层卷积神经网络,回到起点。


系统性学习tf选对教程很重要,有的书偏理论,有的书偏实践,有的啥也不是,之前就有人给我推荐西瓜书,翻了一下,可怕,不可能看得懂,于是知乎了一下这本书的评价,有一个神级评论说:这是一本想入门的人看不懂,入门的人不会去看的书。。。然后很幸运,知乎给我推送了这本《TensorFlow深度学习应用实践》王晓华著,这本书偏实践,原理和代码解释部分都是一笔带过,所以这也是今天写这篇推文的原因,来讲讲原著中没有解释的,数据的演算。



一条正经的分割线


完整代码源自:《TensorFlow深度学习应用实践》王晓华

import tensorflow as tf
import tensorflow.examples.tutorials.mnist.input_data as input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
# 输入层
x_data = tf.placeholder("float32", [None, 784])
x_iamge = tf.reshape(x_data, [-1,28,28,1])
# 卷积层
w_conv = tf.Variable(tf.ones([5,5,1,32]))
b_conv = tf.Variable(tf.ones([32]))
h_conv = tf.nn.relu(tf.nn.conv2d(x_iamge, w_conv, strides=[1, 1, 1, 1],padding = 'SAME') + b_conv)
# 池化层
h_pool = tf.nn.max_pool(h_conv, ksize=[1,2,2,1], strides=[1,2,2,1],padding='SAME')
# 全连接层
w_fc = tf.Variable(tf.ones([14*14*32, 1024]))
b_fc = tf.Variable(tf.ones([1024]))
h_pool_flat = tf.reshape(h_pool, [-1, 14*14*32])
h_fc = tf.nn.relu(tf.matmul(h_pool_flat, w_fc) + b_fc)
w_fc2 = tf.Variable(tf.ones([1024, 10]))
b_fc2 = tf.Variable(tf.ones([10]))
y_model = tf.nn.softmax(tf.matmul(h_fc, w_fc2) + b_fc2)
#
y_data = tf.placeholder("float32", [None, 10])
loss = -tf.reduce_sum(y_data*tf.log(y_model))
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(loss)
init = tf.initialize_all_variables()
sees = tf.Session()
sees.run(init)
for _ in range(1000):
batch_xs, batch_ys = mnist.train.next_batch(200)
sees.run(train_step, feed_dict={x_data:batch_xs, y_data:batch_ys})
if _ % 50 == 0:
correct_prediction = tf.equal(tf.argmax(y_model, 1), tf.argmax(y_data,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
print(sees.run(accuracy, feed_dict={x_data:mnist.test.images, y_data:mnist.test.labels}))
复制


一个卷积神经网络,包含输入层、卷积层、池化层、全连接层。 


# 输入层

x_data = tf.placeholder("float32", [None, 784])
x_iamge = tf.reshape(x_data, [-1,28,28,1])
复制

1、x_data的shape为[None, 784],是因为mnist数据集的图片为28*28,摊平了就是28*28 = 784

2、tf.reshape(e, [a, b, c ,d]) , 当a=-1的时候,意思是将e不管是有几行几列矩阵,都展开变成一行,然后重新塑形,具体计算公式为a = e / (b * c * d),代入代码中的数值,a = 784 / (28*28 *1) = 1,所以reshape后的shape为[1, 28, 28, 1]


# 卷积层

w_conv = tf.Variable(tf.ones([5,5,1,32]))
b_conv = tf.Variable(tf.ones([32]))
h_conv = tf.nn.relu(tf.nn.conv2d(x_iamge, w_conv, strides=[1, 1, 1, 1],padding = 'SAME') + b_conv)
复制

1、 w_conv是卷积核,前两位5、5是卷积核大小,第三位是通道数量,因为是黑白照所以是1,第四位是输出通道数量。

2、b_conv是线性方程里面那个常量。

3、tf.nn.conv2d(),是TensorFlow里面实现卷积的函数,strides=[1, 1, 1, 1],前后固定为1,中间代表水平和垂直滑动的距离,padding = 'SAME',是边沿填充0。

4、tf.nn.conv2d()返回一个tensor,就是我们常说的feature map。

5、下面计算一下feature map的形状:长、宽 = (28 + 2 - 5)/ 1 + 1 = 26(28是上面x_iamge的长宽,加2是因为padding = 'SAME',边沿填充各加了两位单位长度,5是卷积核的大小,除1是卷积核每次滑动的距离)

6、所以tf.nn.conv2d()返回的tensor为[1, 26, 26 ,32],第一个值1是因为x_iamge的第一个值是1,最后为32,是因为卷积核最后的输出通道为32。

7、计算relu函数里面两个张量相加,我们知道在线性代数里面,两个矩阵相加的前提是两个矩阵大小一样。在tf里面,两个不同形状的矩阵相加,会通过遍历的方式给大矩阵逐个加上小矩阵的值。举例:A = [[1, 2] [3 ,4]],B= [1,1]

A + B = [[2, 3] [4 ,5]]

8、b_conv = tf.Variable(tf.ones([32])) = [1,1,1,1,1........]


# 池化层

h_pool = tf.nn.max_pool(h_conv, ksize=[1,2,2,1], strides=[1,2,2,1],padding='SAME')
复制

1、tf.nn.max_pool(),ksize = [1, height, width, 1],池化窗口,strides=[1,2,2,1],前后固定为1,中间代表水平和垂直滑动的距离,padding = 'SAME',是边沿填充0。

2、长、宽 = (26 + 2 - 2)/ 2 + 1 = 14(26是上面x_iamge进过卷积之后的大小,加2是因为padding = 'SAME',边沿填充各加了两位单位长度,减2是池化窗口大小,除2是池化窗口每次滑动的距离)

3、池化后形状由 [1, 26, 26 ,32]  变成  [1, 14, 14 ,32]


# 全连接层

w_fc = tf.Variable(tf.ones([14*14*32, 1024]))
b_fc = tf.Variable(tf.ones([1024]))
h_pool_flat = tf.reshape(h_pool, [-1, 14*14*32])
h_fc = tf.nn.relu(tf.matmul(h_pool_flat, w_fc) + b_fc)
w_fc2 = tf.Variable(tf.ones([1024, 10]))
b_fc2 = tf.Variable(tf.ones([10]))
y_model = tf.nn.softmax(tf.matmul(h_fc, w_fc2) + b_fc2)
复制

1、h_pool_flat的形状为[1, 14 * 14 * 32],具体算法看输入层的reshape

2、在线性代数里面,两个矩阵相乘A = m x n , B = n x k,那么A * B之后的形状为 m x k,所以,h_pool_flat.shape = [1, 14 * 14 * 32] , w_fc.shape = [14*14*32, 1024],tf.matmul(h_pool_flat, w_fc)之后的形状为[1, 1024]

3、tf.nn.relu(tf.matmul(h_pool_flat, w_fc) + b_fc) ==》 tf.nn.relu([1, 1024] + [1024])


至此,该篇单层卷积神经网络中重要的数值的计算就完成了,之前看到有人说做这一行的一定要数据敏感,也是有点道理。




文章转载自大碗岛星期天下午的梦,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论