利用CNN识别MNIST手写字,很普通的一个例程。
输入数据经过卷积层,池化层,卷积层,池化层,全连接层,Softmax输出层,使用Relu激活函数。
MNIST数据集:它有60000个训练样本集和10000个测试样本集。
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
LeNet-5各层参数
在卷积层中,神经元的个数 = feature map的像素个数 * feature map 个数
可训练参数个数 = filter参数个数 * filter 个数 + filter 个数
卷积层:

:引用 <<------feature map 的计算公式
为什么要用卷积:在传统的神经网络中,神经元要与图片上的每一个像素相连,参数甚多,采用卷积使神经元与图片中的部分像素连接,参数变少。


权值共享用一个filter去扫整个图片,这个filter中的参数,即权重,是不变的,不同的filter权重才不同。
池化层:对feature map 再进行下采样,把参数再减小。与卷积过程基本类似。
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
sess = tf.InteractiveSession() #建立会话
def Weights_variable(shape): #定义Weights函数,在构造层时可直接使用,
initial = tf.truncated_normal(shape,stddev=0.1) #产生张量shape型的 标准差为 0.1的截断式正太分布,当产生的随机数距离均值大于两倍的标准差时就会重新生成
return tf.Variable(initial) #在tf中,变量是要声明的
def Bias_variable(shape):
initial=tf.constant(0.1,shape=shape) #定义张量shape型的0.1常量
return tf.Variable(initial)
def Conv2d(x,w):
return tf.nn.conv2d(x,w,strides=[1,1,1,1],padding='SAME')
def max_pool_2x2(x):
return tf.nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
with tf.name_scope('inputs'): # tensorboard语句
x = tf.placeholder(tf.float32,[None,784],name='x_images_input')#tf大部分只能处理float32的数据。28 * 28 =784 None代表不知道有多少张
y_ = tf.placeholder(tf.float32,[None,10],name='y_labels_input')
x_image = tf.reshape(x,[-1,28,28,1]) #把1*784 变成28*28
with tf.name_scope('firstlayer'):
w_conv1 = Weights_variable([5,5,1,32]) #5x5的卷积核 输入通道为1 输出32个通道,即输出32个 feature map
b_conv1 = Bias_variable([32])
h_conv1 = tf.nn.relu(Conv2d(x_image,w_conv1)+b_conv1)
h_pool1 = max_pool_2x2(h_conv1)
with tf.name_scope('secondlayer'):
w_conv2 = Weights_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)
with tf.name_scope('fclayer'):
w_fc1 = Weights_variable([7*7*64,1024])#64个7*7的小图 隐藏层节点1024个
b_fc1 = Bias_variable([1024])
h_pool2_flat = tf.reshape(h_pool2,[-1,7*7*64]) #再变为一维
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat,w_fc1)+b_fc1)
keep_prob = tf.placeholder(tf.float32) #dropout 防止过拟合,在训练数据中扔掉一部分
h_fc1_drop = tf.nn.dropout(h_fc1,keep_prob)
with tf.name_scope('softmaxlayer'):
w_fc2 = Weights_variable([1024,10])
b_fc2 = Bias_variable([10])
y = tf.nn.softmax(tf.matmul(h_fc1_drop,w_fc2)+b_fc2)
with tf.name_scope('calculation'):
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_*tf.log(y),reduction_indices=[1]))
#reduction_indices=[1] 按行求解,计算交叉熵。
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
tf.summary.scalar('loss',cross_entropy)
merged = tf.summary.merge_all()
writer = tf.summary.FileWriter("logs/",sess.graph) #WIN10 要用CHROME打开 并且要断网,生成的logs文件夹要放在c盘第一层下
#tensorboard --logdir=文件名
tf.global_variables_initializer().run()
for i in range(1001):
batch_xs,batch_ys = mnist.train.next_batch(50)
train_step.run(feed_dict={x: batch_xs, y_: batch_ys, keep_prob: 0.5})
if i%100==0:
train_accuracy = accuracy.eval(feed_dict={x:batch_xs,y_:batch_ys,keep_prob:1.0})
print("step %d and train_accuracy is %g" %(i,train_accuracy))
result=sess.run(merged,feed_dict={x:batch_xs,y_:batch_ys,keep_prob:1.0})
writer.add_summary(result,i)
print("test accuracy %g"%accuracy.eval
(feed_dict={x:mnist.test.images,y_:mnist.test.labels,keep_prob:1.0}))
tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, name=None)
input : [batch, in_height, in_width, in_channels]
图片数量, 图片高度, 图片宽度, 图像通道数
filter: [filter_height, filter_width, in_channels, out_channels]
[卷积核的高度,卷积核的宽度,图像通道数,卷积核个数]
filter中的in_channels就是input中的in_channels
输出是1x2x2x1,其中2=(3-2)/1+1,即(图片大小-filter大小)/步长+1
strides: 第一个参数表示在batch方向移动的步长,
第四个参数表示在channels上移动的步长,这两个参数都设置为1就好。
重点就是第二个,第三个参数的意义,也就是在height于width方向上的步长,这里也都设置为1。
padding='SAME'时,填充0,卷积后的图片大小计算公式:
out_height = ceil(float(in_height) / float(strides[1]))
out_width = ceil(float(in_width) / float(strides[2]))
='VAILD'时,舍弃元素,计算公式:
out_height = ceil(float(in_height - filter_height + 1) / float(strides[1]))
out_width = ceil(float(in_width - filter_width + 1) / float(strides[2]))
ceil()返回上入整数
网友评论