CNN实现手写数字识别

手写数字识别数据集简介

&nbsp MNIST数据集(修改的国家标准与技术研究所——Modified National Institute of Standards and Technology),是一个大型的包含手写数字图片的数据集。该数据集由0-9手写数字图片组成,共10个类别。每张图片的大小为28 * 28。
&nbsp MNIST数据集共有70000张图像,其中训练集60000张,测试集10000张。训练集分为55000张训练图像与5000张验证图像。MNIST图像为单通道。

使用CNN来实现

&nbsp 卷积神经网络:CNN(Convolutional neural network),即卷积神经网络。卷积理解为一个信号与另外一个信号进行叠加,产生新的信号的过程。(在卷积神经网络中,可认为具有固定权重的滑动窗口与原窗口的数据进行对位相乘再相加的过程。)

CNN主要层次:

&nbsp
&nbsp 1.输入层------输入的是图片。
&nbsp 2.卷积层------有几组卷积和就有几个输出通道,卷积之后能改变输入的大小。
&nbsp 3.激励层------卷积之后进行激活,激励不会改变大小。
&nbsp 4.池化层------分为最大池化(取最大值)和平均池化(取平均值)。对激励之后的结果进行融合,也会有一个滑动窗口,与经过激励层的结果进行叠加,叠加后取最大值或平均值;经过池化后矩阵变小,相当于变相的减少神经元的个数。以此降低模型的复杂度,防止出现过拟合。池化不会改变通道数。
&nbsp 功能:提取有效特征,降低模型复杂度,防止过拟合。
&nbsp 5.全连接层-----对提取的局部特征信息进行融合构成一个完整的图像。(全连接层不设置连接层的个数,可以为一层,也可以为两层。)

&nbsp 卷积神经网络为了防止过拟合在全连接层设置了一个神经元的随机失活率。
&nbsp 卷积神经网络的特点:局部感知;权值共享

jupyter

1.加载必要的库

&nbsp import tensorflow as tf
&nbsp from tensorflow.examples.tutorials.mnist import input_data
&nbsp import matplotlib.pyplot as plt

2.下载数据集

&nbsp 调用read_data_sets,可以下载mnist数据集到指定的目录,如果目录不存在,可自定创建。如果数据已经下载,则直接从文件中提取数据。
&nbsp mnist = input_data.read_data_sets("data/", one_hot=True)
&nbsp # 通过指定的路径(第1个参数)获取(加载)手写数字数据集。如果指定的路径中文件不存在,则会进行下载。如果文件已经存在,则直接使用。

3.查看数据集

&nbsp display(mnist.train.images.shape)#(55000, 784)
&nbsp display(mnist.train.labels.shape)#(55000, 10)

4.显示指定图片

&nbsp plt.imshow(mnist.train.images[1].reshape((28, 28)), cmap="gray")
&nbsp 保存模型的权重时,默认为 checkpoint 格式。 通过save_format ='h5'使用HDF5。

具体程序实现:

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

if __name__ == '__main__':
    # 读入数据。
    mnist = input_data.read_data_sets("data/", one_hot=True)
    with tf.name_scope("input"):
        # 训练图像的占位符。
        x = tf.placeholder(tf.float32, [None, 784])
        # 训练图像对应分类(标签)的占位符。
        y = tf.placeholder(tf.float32, [None, 10])
        # 因为卷积要求输入的是4维数据,因此对形状进行转换。
        # NHWC(默认)   NCHW
        # N number样本的数量
        # H height图像的高度
        # W width图像的宽度
        # C channel图像的通道数
        x_image = tf.reshape(x, [-1, 28, 28, 1])

    # 卷积层1。
    with tf.name_scope("conv_layer1"):
        # 定义权重。(w就是滑动窗口)
        # 5, 5, 1, 32  =>  滑动窗口的高度,滑动窗口的宽度,输入通道数,输出通道数。
        w = tf.Variable(tf.truncated_normal([5, 5, 1, 32], stddev=0.1), name="w")
        # 定义偏置。
        b = tf.Variable(tf.constant(0.0, shape=[32]), name="b")
        # 进行卷积计算。
        # strides=[1, 1, 1, 1] 步幅。针对输入的NHWC定义的增量。
        # padding: SAME 与VALID。SAME,只要滑动窗口不全移除输入区域就可以。
        # VALID,滑动窗口必须完全在输入区域之内。
        conv = tf.nn.bias_add(tf.nn.conv2d(x_image, w, strides=[1, 1, 1, 1], padding='SAME'), b, name="conv")
        # 使用激活函数进行激活。
        activation = tf.nn.relu(conv)
        # 池化操作。
        # ksize:池化的窗口。
        pool = tf.nn.max_pool(activation, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

    # 卷积层2。
    with tf.name_scope("conv_layer2"):
        w = tf.Variable(tf.truncated_normal([5, 5, 32, 64], stddev=0.1), name="w")
        b = tf.Variable(tf.constant(0.0, shape=[64]), name="b")
        conv = tf.nn.bias_add(tf.nn.conv2d(pool, w, strides=[1, 1, 1, 1], padding='SAME'), b, name="conv")
        activation = tf.nn.relu(conv)
        pool = tf.nn.max_pool(activation, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
        
    # 全连接层1。
    with tf.name_scope("full_layer1"):
        # 7 * 7 * 64
        # 原始图像是28 * 28,经过卷积与激励后,没有改变,经过2 * 2池化后,变成 14 * 14。
        # 第一层卷积之后结果为14 * 14,经过第二层卷积与激励后,没有改变,经过2 * 2池化后,变成 7 * 7。
        # 第二层卷积之后,我们图像的形状为  NHWC  =>  [N, 7, 7, 64]
        # 4维变成2二维,将后面三维拉伸成为1维。  =》  [N, 7 * 7 * 64]
        w = tf.Variable(tf.truncated_normal([7 * 7 * 64, 1024], stddev=0.1), name="w")
        b = tf.Variable(tf.constant(0.0, shape=[1024]), name="b")
        # 将第二层卷积之后的结果转换成二维结构。
        pool = tf.reshape(pool, [-1, 7 * 7 * 64])
        activation = tf.nn.relu(tf.matmul(pool, w) + b)
        # 执行dropout(随机丢弃)
        keep_prob = tf.placeholder(tf.float32)
        # 进行随机丢弃,keep_prob指定神经元的保留率。
        drop = tf.nn.dropout(activation, keep_prob)
        
    # 全连接层2。
    with tf.name_scope("full_layer2"):
        w = tf.Variable(tf.truncated_normal([1024, 10], stddev=0.1), name="w")
        b = tf.Variable(tf.constant(0.0, shape=[10]), name="b")
        logits = tf.matmul(drop, w) + b
    
    # 损失值与准确率计算层。
    with tf.name_scope("compute"):                   
        # 计算损失值。
        loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y, logits=logits))
        # 将损失值加入到tensorboard中。
#         tf.summary.scalar('loss',loss)
        train_step = tf.train.AdamOptimizer(1e-4).minimize(loss)
        # 计算准确率
        correct = tf.equal(tf.argmax(logits, 1), tf.argmax(y, 1))
        accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))
#         tf.summary.scalar('accuracy',accuracy)
        
    #合并所有的summary
#     merged = tf.summary.merge_all()

    # 创建Session。
    with tf.Session() as sess:
        # 对全局变量进行初始化。
        sess.run(tf.global_variables_initializer())
#         train_writer = tf.summary.FileWriter('logs/train',sess.graph)
#         test_writer = tf.summary.FileWriter('logs/test',sess.graph)
        # 可以尝试更大的次数,可以将准确率提升到99%以上。
        for i in range(1, 3001):
            batch = mnist.train.next_batch(64)
            # 每100步报告一次在验证集上的准确度
            if i % 100 == 0:
                train_accuracy = accuracy.eval(
                    feed_dict={x: batch[0], y: batch[1], keep_prob: 1.0})
                test_accuracy = accuracy.eval(
                    feed_dict={x: mnist.test.images[:5000], y: mnist.test.labels[:5000], keep_prob: 1.0})
                print(f"step {i}, training accuracy {train_accuracy * 100:.2f}%")
                print(f"step {i}, test accuracy {test_accuracy * 100:.2f}%")
            train_step.run(feed_dict={x: batch[0], y: batch[1], keep_prob: 0.5})
            # 计算并写入训练集计算的结果。
#             summary = sess.run(merged,feed_dict={x:batch[0], y:batch[1] ,keep_prob:1.0})
#             train_writer.add_summary(summary, i)
            # 计算并写入测试集计算的结果。
#             summary = sess.run(merged,feed_dict={x:mnist.test.images, y:mnist.test.labels, keep_prob:1.0})
#             test_writer.add_summary(summary,i) 

部分运行结果:

step 100, training accuracy 81.25%
step 100, test accuracy 85.28%
step 200, training accuracy 90.62%
step 200, test accuracy 91.00%
step 300, training accuracy 100.00%
step 300, test accuracy 92.14%
step 400, training accuracy 96.88%
step 400, test accuracy 93.88%
step 500, training accuracy 93.75%
step 500, test accuracy 94.34%
step 600, training accuracy 98.44%
step 600, test accuracy 94.64%

转载于:https://www.cnblogs.com/wisteria68/p/10848632.html

手写数字识别是一个经典的机器学习问题,可以使用卷积神经网络(CNN)来解决。下面是一个简单的CNN实现手写数字识别的步骤: 1. 加载数据集:使用MNIST数据集,它包含60,000个训练样本和10,000个测试样本,每个样本都是28×28像素的灰度图像。 2. 数据预处理:将每个像素值缩放到0到1的范围内,并将标签进行one-hot编码。 3. 构建CNN模型:使用卷积层、池化层和全连接层来构建模型。模型的输入是28×28像素的图像,输出是10个数字类别的概率分布。 4. 训练模型:使用训练集进行模型训练,可以使用交叉熵损失函数和随机梯度下降优化器。 5. 评估模型:使用测试集进行模型评估,可以计算模型的准确率。 下面是一个简单的CNN手写数字识别代码示例: ```python import tensorflow as tf from tensorflow.keras.datasets import mnist # 加载数据集 (x_train, y_train), (x_test, y_test) = mnist.load_data() # 数据预处理 x_train = x_train / 255.0 x_test = x_test / 255.0 y_train = tf.keras.utils.to_categorical(y_train) y_test = tf.keras.utils.to_categorical(y_test) # 构建CNN模型 model = tf.keras.models.Sequential([ tf.keras.layers.Conv2D(32, (3,3), activation='relu', input_shape=(28,28,1)), tf.keras.layers.MaxPooling2D((2,2)), tf.keras.layers.Flatten(), tf.keras.layers.Dense(128, activation='relu'), tf.keras.layers.Dense(10, activation='softmax') ]) # 编译模型 model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) # 训练模型 model.fit(x_train.reshape(-1,28,28,1), y_train, epochs=5, batch_size=32, validation_data=(x_test.reshape(-1,28,28,1), y_test)) # 评估模型 model.evaluate(x_test.reshape(-1,28,28,1), y_test) ``` 这个模型包含了一个卷积层、一个池化层、一个flatten层和两个全连接层。在训练模型之前,我们预处理了数据并将其reshape成了28×28×1的张量。在训练模型时,我们使用了交叉熵损失函数和Adam优化器。最后,我们使用测试集评估了模型的准确率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值