TensorFlow实现CNN-MNIST

CNN卷积神经网络原理图:
在这里插入图片描述
详细原理参照:
1.CNN卷积神经网络原理讲解+图片识别应用
2.卷积神经网络–介绍

准备工作
下载并导入MNIST手写数字库

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("mnist_data", one_hot=True)	# 设置使用独热码

定义输入与输出

input_x = tf.placeholder(tf.float32, [None, 28*28]) / 255.  # 输入
output_y = tf.placeholder(tf.int32, [None, 10])     # 输出:10个数字的预测

改变输入形状,满足第一层的输入要求

input_x_images = tf.reshape(input_x, [-1, 28, 28, 1])

第1层卷积
conv2d函数使用给定大小的卷积核,完成对矩阵的卷积操作,函数功能详见:TF-卷积函数 tf.nn.conv2d 介绍

# 第1层
conv1 = tf.layers.conv2d(
    inputs=input_x_images,  # 形状 [28, 28, 1]
    filters=32,   # 32个过滤器,输出深度32
    kernel_size=[5, 5],    # 过滤器二维大小是5*5
    strides=1,    # 步长为1
    padding="same",   # same表示输出大小不变,因此需要在外圈补零两圈
    activation=tf.nn.relu   # 选择激活函数
)   # 输出的形状 [28, 28, 32]

第1层池化
max pooling 的操作:整个图片被不重叠的分割成若干个同样大小的小块,每个小块内只取最大的数字,再舍弃其他节点后,保持原有的平面结构得出 output,具体参考:CNN中的maxpool到底是什么原理

pool1 = tf.layers.max_pooling2d(
    inputs=conv1,   # 形状 [28, 28, 32]
    pool_size=[2, 2],   # 过滤器在二维的大小是 [2, 2]
    strides=2   # 步长为 2
)   # 输出形状 [14, 14, 32]

同理写出第2层卷积和第2层池化:

# 第2层卷积
conv2 = tf.layers.conv2d(
    inputs=pool1,  # 形状 [14, 14, 32]
    filters=64,   # 64个过滤器,输出深度64
    kernel_size=[5, 5],    # 过滤器二维大小是5*5
    strides=1,    # 步长为 1
    padding="same",   # same表示输出大小不变,因此需要在外圈补零两圈
    activation=tf.nn.relu   # 选择激活函数
)   # 输出形状 [14, 14, 64]

# 第2层池化 (亚采样)
pool2 = tf.layers.max_pooling2d(
    inputs=conv2,   # 形状 [14, 14, 64]
    pool_size=[2, 2],   # 过滤器在二维的大小是 [2, 2]
    strides=2   # 步长为 2
)   # 输出形状 [7, 7, 64]

第一层全连接
全连接层的意义参考:深入理解卷积层,全连接层的作用意义
更改形状:

flat = tf.reshape(pool2, [-1, 7 * 7 *64])   # [n, 7, 7, 64]变为[n, 7*7*64]

经过1024个神经元的全连接层:

dense = tf.layers.dense(
    inputs=flat,
    units=1024,
    activation=tf.nn.relu
)

丢弃50%:

dropout = tf.layers.dropout(
    inputs=dense,
    rate=0.5
)

最后一层全连接

# 10个神经元的全连接层
logits = tf.layers.dense(
    inputs=dropout,
    units=10
)   # 输出形状 [1, 1, 10]

计算误差并进行优化

# 计算误差  (计算Cross Entropy交叉熵,再用Softmax计算百分比概率)
loss = tf.losses.softmax_cross_entropy(
    onehot_labels=output_y,     # 实际结果
    logits=logits   # 预测结果
)
# 使用Adam优化器来最小化误差,学习率0.001
train_op = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss)

# 计算精度
# 返回(accuracy, update_op),创建两个局部变量
accuracy = tf.metrics.accuracy(
    labels=tf.argmax(output_y, axis=1),
    predictions=tf.argmax(logits, axis=1)
)[1]

tf.argmax() 与 numpy.argmax() 方法的意思是一致的,以二维数组为例:axis = 0 时,返回每一列最大值的位置索引;axis = 1 时,返回每一行最大值的位置索引。
因为我们使用独热码的方式记录数字,所有最大值的索引表示的就是该数。

训练网络,测试输出

sess = tf.Session()
init = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer())
sess.run(init)
for i in range(200):
    batch = mnist.train.next_batch(50)  # 从训练集中取下一组数据
    train_loss, train_op2 = sess.run([loss, train_op], {input_x:batch[0], output_y:batch[1]})
    if i % 100 == 0:
        test_accuracy = sess.run(accuracy, {input_x:test_x, output_y:test_y})
        print("Step=", i, " Train loss=", train_loss, " Test accuracy=", test_accuracy)


# 测试:打印20个真实值和预测值
test_output = sess.run(logits, {input_x:test_x[:20]})
inferenced_y = np.argmax(test_output, 1)
print(inferenced_y, 'inferenced numbers')   # 推测的数字
print(np.argmax(test_y[:20], 1), 'Real numbers')    # 真实的数字

sess.close()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值