python+tensorflow CNN卷积神经网络手写字体识别

2023-05-16

导入所需的库模块:

import os
import cv2
import numpy as np
import tensorflow as tf2
import matplotlib.pyplot as plt
import tensorflow.compat.v1 as tf

import tensorflow.compat.v1 as tf
这句话是为了将tensorflow 2.x转为1.x,tensorflow1.x更能表现网络结构
import os
是调用系统,可有可无,为了不显示警告内容所以调用该模块

小批量训练法的数据分割:

def nextBatch(data,batch_size,n):#小批量梯度下降法获取当前数据集函数
    #data为全部数据[X,Y],batch_size为当前子数据集大小,n为第n个子数据集
    a=n*batch_size
    b=(n+1)*batch_size
    limdata=len(data[0])
    if b>limdata:
        b=limdata
        a=b-batch_size
    data_x=data[0][a:b]
    data_y=data[1][a:b]
    return data_x,data_y

这里是为了将数据集切割成小批量数据,完成训练,小批量训练结果更好。

CNN网络:

def main_train():
    (x_tr0,y_tr0),(x_te0,y_te0)=tf2.keras.datasets.mnist.load_data()#手写数据库
    y_tr=np.zeros((len(y_tr0),10))
    y_te=np.zeros((len(y_te0),10))
    for i in range(len(y_tr0)):
        y_tr[i][y_tr0[i]]=1
    for i in range(len(y_te0)):
        y_te[i][y_te0[i]]=1
    x_tr=x_tr0.reshape(-1,28,28,1)
    x_te=x_te0.reshape(-1,28,28,1)
    training_epochs=100#训练步数
    batch_count=20#小批量训练子集数量
    L=32#卷积层1所提取特征个数
    M=64#卷积层2所提取特征个数
    N=128#卷积层3所提取特征个数
    O=625#全连接就层神经元数
#     with tf.device('/cpu:0'):
    with tf.device('/gpu:0'):
        Xin=tf.placeholder(tf.float32,[None,28,28,1],name='Xin')#28×28维输入特征
        Yout=tf.placeholder(tf.float32,[None,10],name="Yout")#10类分类结果标签
        W1=tf.Variable(tf.random_normal([3,3,1,L],stddev=0.01))#卷积层1的卷积核权值张量,卷积核大小3×3,输入数据为1通道,输出特征为32通道
        W2=tf.Variable(tf.random_normal([3,3,L,M],stddev=0.01))#卷积层2的卷积核权值张量,卷积核大小3×3,输入数据为32通道,输出特征为64通道
        W3=tf.Variable(tf.random_normal([3,3,M,N],stddev=0.01))#卷积层3的卷积核权值张量,卷积核大小3×3,输入数据为64通道,输出特征为128通道
        W4=tf.Variable(tf.random_normal([N*4*4,O],stddev=0.01))#全连接层权值张量,输入数据为128×4×4个,输出为625个,这里需要把上一层的高维张量扁平化
        W5=tf.Variable(tf.random_normal([O,10],stddev=0.01))#输出层权值张量,输入数据为625,输出为10类
        b1=tf.Variable(tf.random_normal([L],stddev=0.01))#卷积层1的输出特征阈值,输出特征为32通道,每个通道共享一个阈值
        b2=tf.Variable(tf.random_normal([M],stddev=0.01))#卷积层2的输出特征阈值,输出特征为64通道,每个通道共享一个阈值
        b3=tf.Variable(tf.random_normal([N],stddev=0.01))#卷积层3的输出特征阈值,输出特征为128通道,每个通道共享一个阈值
        b4=tf.Variable(tf.random_normal([O],stddev=0.01))#全连接层阈值
        b5=tf.Variable(tf.random_normal([10],stddev=0.01))#输出层阈值
        '''卷积层一'''
        conv1a=tf.nn.conv2d(Xin,W1,strides=[1,1,1,1],padding='SAME')
        conv1b=tf.nn.bias_add(conv1a,b1)
        conv1c=tf.nn.relu(conv1b)
        '''池化层一'''
        conv1=tf.nn.max_pool(conv1c,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
        '''卷积层二'''
        conv2a=tf.nn.conv2d(conv1,W2,strides=[1,1,1,1],padding='SAME')
        conv2b=tf.nn.bias_add(conv2a,b2)
        conv2c=tf.nn.relu(conv2b) 
        '''池化层二'''
        conv2=tf.nn.max_pool(conv2c,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
        '''卷积层三'''
        conv3a=tf.nn.conv2d(conv2,W3,strides=[1,1,1,1],padding='SAME')
        conv3b=tf.nn.bias_add(conv3a,b3)
        conv3c=tf.nn.relu(conv3b) 
        '''池化层三'''
        conv3d=tf.nn.max_pool(conv3c,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
        conv3=tf.reshape(conv3d,[-1,W4.get_shape().as_list()[0]])#扁平化
        '''全连接层'''
        FCa=tf.matmul(conv3,W4)+b4
        FC=tf.nn.relu(FCa)
        '''输出层'''
        Y_=tf.matmul(FC,W5)+b5 
        Y=tf.nn.softmax(Y_,name="output")#经历softmax分类激活函数后的数值
        '''损失'''
        cross_entropy=tf.nn.softmax_cross_entropy_with_logits(logits=Y_, labels=Yout)
        loss=tf.reduce_mean(cross_entropy)*100#交叉损失
        correct_prediction=tf.equal(tf.argmax(Y,1),tf.argmax(Yout,1))
        accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32),name='accuracy')#正确率
        '''优化器'''
        trainer=tf.train.RMSPropOptimizer(learning_rate=0.001,momentum=0.9).minimize(loss)
        init=tf.global_variables_initializer()#变量初始化赋值器
    with tf.Session() as sess: 
        sess.run(init)#变量初始化
        out_init=sess.run(accuracy,feed_dict={Xin:x_tr[0:20000],Yout:y_tr[0:20000]})#计算初始误差
        print("初始准确率为:{:.4f}%".format(out_init*100))#输出初始误差
        for epoch in range(training_epochs):#训练步数
            print("当前训练步为第{}步".format(epoch+1))
            batch_size=int(len(y_tr)/batch_count)#当前子集大小
            for i in range(batch_count):#对每个子集遍历训练
                batch_x,batch_y=nextBatch([x_tr[0:20000],y_tr[0:20000]],batch_size,i)#当前子集的训练集特征和标签数据
                sess.run(trainer,feed_dict={Xin:batch_x,Yout:batch_y})
            out=sess.run(accuracy,feed_dict={Xin:x_tr[0:20000],Yout:y_tr[0:20000]})#计算当前误差
            print("当前准确率为:{:.4f}%".format(out*100))#当前初始误差
            '''当前会话存储'''
            if out>out_init:
                out_init=out
                saver=tf.train.Saver()
                saver.save(sess,r".\savefile\CNN\FigureCNN.ckpt")

下面做详细分析。
首先要导入手写数据库,tensorflow2.0自带手写字体数据库,用下面语句导入:

(x_tr0,y_tr0),(x_te0,y_te0)=tf2.keras.datasets.mnist.load_data()

x_tr0,y_tr0是60000个训练集的图片和标签。图片是28×28像素,标签是该图像所对应的数字。
x_te0,y_te0是10000个测练集的图片和标签。图片是28×28像素,标签是该图像所对应的数字。
在神经网络中,我们输出是10类,利用softmax函数做输出,因此标签的形式应为10位的,数字0应为“1000000000”,数字1为“0100000000”,数字2为“0010000000”,…,数字9为“0000000001”。
下面改变输出标签的格式:

	y_tr=np.zeros((len(y_tr0),10))
    y_te=np.zeros((len(y_te0),10))
    for i in range(len(y_tr0)):
        y_tr[i][y_tr0[i]]=1
    for i in range(len(y_te0)):
        y_te[i][y_te0[i]]=1

此外,数据输入格式也要做改变,输入数据是28×28像素黑白图片,读入信息是2阶矩阵,在网络中改为3阶矩阵,这里进行形式变换:

    x_tr=x_tr0.reshape(-1,28,28,1)
    x_te=x_te0.reshape(-1,28,28,1)

接下来输入网络计算的相关参数:

    training_epochs=100#训练步数
    batch_count=20#小批量训练子集数量
    L=32#卷积层1所提取特征个数
    M=64#卷积层2所提取特征个数
    N=128#卷积层3所提取特征个数
    O=625#全连接就层神经元数

接下来,神经网络可以使用cpu计算,也可以使用gpu计算,cpu计算格式为:

with tf.device('/cpu:0'):

gpu计算格式为:

with tf.device('/gpu:0'):

如果不写这两句话,按照安装的tensorflow版本默认计算。我安装的tensorflow是gpu版本,默认进行gpu计算。

下面,定义网络的权值阈值:

		W1=tf.Variable(tf.random_normal([3,3,1,L],stddev=0.01))#卷积层1的卷积核权值张量,卷积核大小3×3,输入数据为1通道,输出特征为32通道
        W2=tf.Variable(tf.random_normal([3,3,L,M],stddev=0.01))#卷积层2的卷积核权值张量,卷积核大小3×3,输入数据为32通道,输出特征为64通道
        W3=tf.Variable(tf.random_normal([3,3,M,N],stddev=0.01))#卷积层3的卷积核权值张量,卷积核大小3×3,输入数据为64通道,输出特征为128通道
        W4=tf.Variable(tf.random_normal([N*4*4,O],stddev=0.01))#全连接层权值张量,输入数据为128×4×4个,输出为625个,这里需要把上一层的高维张量扁平化
        W5=tf.Variable(tf.random_normal([O,10],stddev=0.01))#输出层权值张量,输入数据为625,输出为10类
        b1=tf.Variable(tf.random_normal([L],stddev=0.01))#卷积层1的输出特征阈值,输出特征为32通道,每个通道共享一个阈值
        b2=tf.Variable(tf.random_normal([M],stddev=0.01))#卷积层2的输出特征阈值,输出特征为64通道,每个通道共享一个阈值
        b3=tf.Variable(tf.random_normal([N],stddev=0.01))#卷积层3的输出特征阈值,输出特征为128通道,每个通道共享一个阈值
        b4=tf.Variable(tf.random_normal([O],stddev=0.01))#全连接层阈值
        b5=tf.Variable(tf.random_normal([10],stddev=0.01))#输出层阈值

下面构建CNN网络:

		Xin=tf.placeholder(tf.float32,[None,28,28,1],name='Xin')#28×28维输入特征
        Yout=tf.placeholder(tf.float32,[None,10],name="Yout")#10类分类结果标签
        '''卷积层一'''
        conv1a=tf.nn.conv2d(Xin,W1,strides=[1,1,1,1],padding='SAME')
        conv1b=tf.nn.bias_add(conv1a,b1)
        conv1c=tf.nn.relu(conv1b)
        '''池化层一'''
        conv1=tf.nn.max_pool(conv1c,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
        '''卷积层二'''
        conv2a=tf.nn.conv2d(conv1,W2,strides=[1,1,1,1],padding='SAME')
        conv2b=tf.nn.bias_add(conv2a,b2)
        conv2c=tf.nn.relu(conv2b) 
        '''池化层二'''
        conv2=tf.nn.max_pool(conv2c,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
        '''卷积层三'''
        conv3a=tf.nn.conv2d(conv2,W3,strides=[1,1,1,1],padding='SAME')
        conv3b=tf.nn.bias_add(conv3a,b3)
        conv3c=tf.nn.relu(conv3b) 
        '''池化层三'''
        conv3d=tf.nn.max_pool(conv3c,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
        conv3=tf.reshape(conv3d,[-1,W4.get_shape().as_list()[0]])#扁平化
        '''全连接层'''
        FCa=tf.matmul(conv3,W4)+b4
        FC=tf.nn.relu(FCa)
        '''输出层'''
        Y_=tf.matmul(FC,W5)+b5 
        Y=tf.nn.softmax(Y_,name="output")#经历softmax分类激活函数后的数值

tf.placeholder()占位符是用于接收外界输入
tf.nn.conv2d()进行卷积操作
tf.nn.bias_add()偏置的加法操作
tf.nn.relu()Relu函数,用作卷积层激活函数
tf.nn.max_pool()最大池化函数,池化是用于减少特征量,避免数据爆炸,但是也减少其中的信息量
tf.reshape()用于改变数据形态,全连接层之前要将数据扁平化,变为一维,便于输出计算
Y_=tf.matmul(FC,W5)+b5 这是全连接层的计算,权值相乘,阈值相加
tf.nn.softmax()是softmax函数,计算输出的概率

下面定义损失函数以及正确率计算函数:

		cross_entropy=tf.nn.softmax_cross_entropy_with_logits(logits=Y_, labels=Yout)
        loss=tf.reduce_mean(cross_entropy)*100#交叉损失
        correct_prediction=tf.equal(tf.argmax(Y,1),tf.argmax(Yout,1))
        accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32),name='accuracy')#正确率

下面定义优化器:

trainer=tf.train.RMSPropOptimizer(learning_rate=0.001,momentum=0.9).minimize(loss)

这里是RMS优化算法,参数包括学习率和动量

下面进行数据训练计算:

    with tf.Session() as sess: 
        sess.run(init)#变量初始化
        out_init=sess.run(accuracy,feed_dict={Xin:x_tr[0:20000],Yout:y_tr[0:20000]})#计算初始准确率
        print("初始准确率为:{:.4f}%".format(out_init*100))#输出初始准确率
        for epoch in range(training_epochs):#训练步数
            print("当前训练步为第{}步".format(epoch+1))
            batch_size=int(len(y_tr)/batch_count)#当前子集大小
            for i in range(batch_count):#对每个子集遍历训练
                batch_x,batch_y=nextBatch([x_tr[0:20000],y_tr[0:20000]],batch_size,i)#当前子集的训练集特征和标签数据
                sess.run(trainer,feed_dict={Xin:batch_x,Yout:batch_y})
            out=sess.run(accuracy,feed_dict={Xin:x_tr[0:20000],Yout:y_tr[0:20000]})#计算当前误差
            print("当前准确率为:{:.4f}%".format(out*100))#当前初始误差

x_tr[0:20000]和y_tr[0:20000]的说明:我的gpu是gtx1050Ti,显存是4G,两万张图片数据的输入是网络中数据的显存极限,再多的数据量就溢出了,不能完成训练。因此,我选择前两万张训练集数据作为输入,这个根据每个人的电脑不一样而不同。
with tf.Session() as sess:是构建会话且自动关闭

为了防止模型丢失,需要将模型存储下来。我们存储准确率最好的会话:

            if out>out_init:
                out_init=out
                saver=tf.train.Saver()
                saver.save(sess,r".\savefile\CNN\FigureCNN.ckpt")

读取模型和自己的图片测试:

def main_test():
    (x_tr0,y_tr0),(x_te0,y_te0)=tf2.keras.datasets.mnist.load_data()#手写数据库
    y_tr=np.zeros((len(y_tr0),10))
    y_te=np.zeros((len(y_te0),10))
    for i in range(len(y_tr0)):
        y_tr[i][y_tr0[i]]=1
    for i in range(len(y_te0)):
        y_te[i][y_te0[i]]=1
    x_tr=x_tr0.reshape(-1,28,28,1)
    x_te=x_te0.reshape(-1,28,28,1)
    road=[r".\savefile\CNN\FigureCNN.ckpt.meta",r".\savefile\CNN\FigureCNN.ckpt"]
    sess=tf.InteractiveSession()
    new_saver=tf.train.import_meta_graph(road[0])
    new_saver.restore(sess,road[1])
    tf.get_default_graph().as_graph_def()
    Xin=sess.graph.get_tensor_by_name('Xin:0')
    Yout=sess.graph.get_tensor_by_name("Yout:0") 
    accuracy=sess.graph.get_tensor_by_name('accuracy:0')
    Y=sess.graph.get_tensor_by_name('output:0')
    Ote=sess.run(accuracy,feed_dict={Xin:x_te,Yout:y_te})
    print("测试集准确率为:{:.4f}%".format(Ote*100))
    Ote=sess.run(accuracy,feed_dict={Xin:x_tr[30000:40000],Yout:y_tr[30000:40000]})
    print("训练集集准确率为:{:.4f}%".format(Ote*100))
    u=eval(input("输入0-9999之间的一个整数:"))
    if (u<0) or (u>9999):
        print('错误!')
        sess.close()
        return
    Otem=sess.run(Y,feed_dict={Xin:[x_te[u]]})
    print('手写的数字为:{}'.format(Otem.argmax()))
    plt.imshow(x_te[u].reshape(28,28))
    plt.show()#手写数字展示
    for i in [0,2,4,5,9]:
        roadpic=r'.\picturefile\handwriting'+str(i)+'.jpg'
        pic=cv2.imread(roadpic,flags=0)
        pic1=255-pic
        pic=pic1.reshape(-1,28,28,1)
        Otem=sess.run(Y,feed_dict={Xin:pic})
        print('手写的数字为:{}'.format(Otem.argmax()))
        plt.imshow(pic1)
        plt.show()#手写数字展示
    sess.close()
    return

下面进行详细分析,先导入数据和测试集输出数据变换形态:

	(x_tr0,y_tr0),(x_te0,y_te0)=tf2.keras.datasets.mnist.load_data()#手写数据库
    y_tr=np.zeros((len(y_tr0),10))
    y_te=np.zeros((len(y_te0),10))
    for i in range(len(y_tr0)):
        y_tr[i][y_tr0[i]]=1
    for i in range(len(y_te0)):
        y_te[i][y_te0[i]]=1
    x_tr=x_tr0.reshape(-1,28,28,1)
    x_te=x_te0.reshape(-1,28,28,1)

读取已存储的模型:

    road=[r".\savefile\CNN\FigureCNN.ckpt.meta",r".\savefile\CNN\FigureCNN.ckpt"]
    sess=tf.InteractiveSession()
    new_saver=tf.train.import_meta_graph(road[0])
    new_saver.restore(sess,road[1])
    tf.get_default_graph().as_graph_def()
    Xin=sess.graph.get_tensor_by_name('Xin:0')
    Yout=sess.graph.get_tensor_by_name("Yout:0") 
    accuracy=sess.graph.get_tensor_by_name('accuracy:0')
    Y=sess.graph.get_tensor_by_name('output:0')

计算测试集和训练集其他数据的准确率:

    Ote=sess.run(accuracy,feed_dict={Xin:x_te,Yout:y_te})
    print("测试集准确率为:{:.4f}%".format(Ote*100))
    Ote=sess.run(accuracy,feed_dict={Xin:x_tr[30000:40000],Yout:y_tr[30000:40000]})
    print("训练集集准确率为:{:.4f}%".format(Ote*100))

随机选择测试集的一个数据,输出模型预测结果并查看这个数据,看看结果:

    u=eval(input("输入0-9999之间的一个整数:"))
    if (u<0) or (u>9999):
        print('错误!')
        sess.close()
        return
    Otem=sess.run(Y,feed_dict={Xin:[x_te[u]]})
    print('手写的数字为:{}'.format(Otem.argmax()))
    plt.imshow(x_te[u].reshape(28,28))
    plt.show()#手写数字展示

将自己写的28×28的图片预测结果:

    for i in [0,2,4,5,9]:
        roadpic=r'.\picturefile\handwriting'+str(i)+'.jpg'
        pic=cv2.imread(roadpic,flags=0)
        pic1=255-pic
        pic=pic1.reshape(-1,28,28,1)
        Otem=sess.run(Y,feed_dict={Xin:pic})
        print('手写的数字为:{}'.format(Otem.argmax()))
        plt.imshow(pic1)
        plt.show()#手写数字展示

roadpic是图片的位置,共5张自己制作的图片:
handwriting0.jpg
handwriting2.jpg
handwriting4.jpg
handwriting5.jpg
handwriting9.jpg

所有程序:

'''
Created on 2021年11月2日

@author: 紫薇星君
'''
import os
import cv2
import numpy as np
import tensorflow as tf2
import matplotlib.pyplot as plt
import tensorflow.compat.v1 as tf

def nextBatch(data,batch_size,n):#小批量梯度下降法获取当前数据集函数
    #data为全部数据[X,Y],batch_size为当前子数据集大小,n为第n个子数据集
    a=n*batch_size
    b=(n+1)*batch_size
    limdata=len(data[0])
    if b>limdata:
        b=limdata
        a=b-batch_size
    data_x=data[0][a:b]
    data_y=data[1][a:b]
    return data_x,data_y

def main_train():
    (x_tr0,y_tr0),(x_te0,y_te0)=tf2.keras.datasets.mnist.load_data()#手写数据库
    y_tr=np.zeros((len(y_tr0),10))
    y_te=np.zeros((len(y_te0),10))
    for i in range(len(y_tr0)):
        y_tr[i][y_tr0[i]]=1
    for i in range(len(y_te0)):
        y_te[i][y_te0[i]]=1
    x_tr=x_tr0.reshape(-1,28,28,1)
    x_te=x_te0.reshape(-1,28,28,1)
    training_epochs=100#训练步数
    batch_count=20#小批量训练子集数量
    L=32#卷积层1所提取特征个数
    M=64#卷积层2所提取特征个数
    N=128#卷积层3所提取特征个数
    O=625#全连接就层神经元数
#     with tf.device('/cpu:0'):
    with tf.device('/gpu:0'):
        Xin=tf.placeholder(tf.float32,[None,28,28,1],name='Xin')#28×28维输入特征
        Yout=tf.placeholder(tf.float32,[None,10],name="Yout")#10类分类结果标签
        W1=tf.Variable(tf.random_normal([3,3,1,L],stddev=0.01))#卷积层1的卷积核权值张量,卷积核大小3×3,输入数据为1通道,输出特征为32通道
        W2=tf.Variable(tf.random_normal([3,3,L,M],stddev=0.01))#卷积层2的卷积核权值张量,卷积核大小3×3,输入数据为32通道,输出特征为64通道
        W3=tf.Variable(tf.random_normal([3,3,M,N],stddev=0.01))#卷积层3的卷积核权值张量,卷积核大小3×3,输入数据为64通道,输出特征为128通道
        W4=tf.Variable(tf.random_normal([N*4*4,O],stddev=0.01))#全连接层权值张量,输入数据为128×4×4个,输出为625个,这里需要把上一层的高维张量扁平化
        W5=tf.Variable(tf.random_normal([O,10],stddev=0.01))#输出层权值张量,输入数据为625,输出为10类
        b1=tf.Variable(tf.random_normal([L],stddev=0.01))#卷积层1的输出特征阈值,输出特征为32通道,每个通道共享一个阈值
        b2=tf.Variable(tf.random_normal([M],stddev=0.01))#卷积层2的输出特征阈值,输出特征为64通道,每个通道共享一个阈值
        b3=tf.Variable(tf.random_normal([N],stddev=0.01))#卷积层3的输出特征阈值,输出特征为128通道,每个通道共享一个阈值
        b4=tf.Variable(tf.random_normal([O],stddev=0.01))#全连接层阈值
        b5=tf.Variable(tf.random_normal([10],stddev=0.01))#输出层阈值
        '''卷积层一'''
        conv1a=tf.nn.conv2d(Xin,W1,strides=[1,1,1,1],padding='SAME')
        conv1b=tf.nn.bias_add(conv1a,b1)
        conv1c=tf.nn.relu(conv1b)
        '''池化层一'''
        conv1=tf.nn.max_pool(conv1c,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
        '''卷积层二'''
        conv2a=tf.nn.conv2d(conv1,W2,strides=[1,1,1,1],padding='SAME')
        conv2b=tf.nn.bias_add(conv2a,b2)
        conv2c=tf.nn.relu(conv2b) 
        '''池化层二'''
        conv2=tf.nn.max_pool(conv2c,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
        '''卷积层三'''
        conv3a=tf.nn.conv2d(conv2,W3,strides=[1,1,1,1],padding='SAME')
        conv3b=tf.nn.bias_add(conv3a,b3)
        conv3c=tf.nn.relu(conv3b) 
        '''池化层三'''
        conv3d=tf.nn.max_pool(conv3c,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
        conv3=tf.reshape(conv3d,[-1,W4.get_shape().as_list()[0]])#扁平化
        '''全连接层'''
        FCa=tf.matmul(conv3,W4)+b4
        FC=tf.nn.relu(FCa)
        '''输出层'''
        Y_=tf.matmul(FC,W5)+b5 
        Y=tf.nn.softmax(Y_,name="output")#经历softmax分类激活函数后的数值
        '''损失'''
        cross_entropy=tf.nn.softmax_cross_entropy_with_logits(logits=Y_, labels=Yout)
        loss=tf.reduce_mean(cross_entropy)*100#交叉损失
        correct_prediction=tf.equal(tf.argmax(Y,1),tf.argmax(Yout,1))
        accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32),name='accuracy')#正确率
        '''优化器'''
        trainer=tf.train.RMSPropOptimizer(learning_rate=0.001,momentum=0.9).minimize(loss)
        init=tf.global_variables_initializer()#变量初始化赋值器
    with tf.Session() as sess: 
        sess.run(init)#变量初始化
        out_init=sess.run(accuracy,feed_dict={Xin:x_tr[0:20000],Yout:y_tr[0:20000]})#计算初始误差
        print("初始准确率为:{:.4f}%".format(out_init*100))#输出初始误差
        for epoch in range(training_epochs):#训练步数
            print("当前训练步为第{}步".format(epoch+1))
            batch_size=int(len(y_tr)/batch_count)#当前子集大小
            for i in range(batch_count):#对每个子集遍历训练
                batch_x,batch_y=nextBatch([x_tr[0:20000],y_tr[0:20000]],batch_size,i)#当前子集的训练集特征和标签数据
                sess.run(trainer,feed_dict={Xin:batch_x,Yout:batch_y})
            out=sess.run(accuracy,feed_dict={Xin:x_tr[0:20000],Yout:y_tr[0:20000]})#计算当前误差
            print("当前准确率为:{:.4f}%".format(out*100))#当前初始误差
            '''当前会话存储'''
            if out>out_init:
                out_init=out
                saver=tf.train.Saver()
                saver.save(sess,r".\savefile\CNN\FigureCNN.ckpt")
    return

def main_test():
    (x_tr0,y_tr0),(x_te0,y_te0)=tf2.keras.datasets.mnist.load_data()#手写数据库
    y_tr=np.zeros((len(y_tr0),10))
    y_te=np.zeros((len(y_te0),10))
    for i in range(len(y_tr0)):
        y_tr[i][y_tr0[i]]=1
    for i in range(len(y_te0)):
        y_te[i][y_te0[i]]=1
    x_tr=x_tr0.reshape(-1,28,28,1)
    x_te=x_te0.reshape(-1,28,28,1)
    road=[r".\savefile\CNN\FigureCNN.ckpt.meta",r".\savefile\CNN\FigureCNN.ckpt"]
    sess=tf.InteractiveSession()
    new_saver=tf.train.import_meta_graph(road[0])
    new_saver.restore(sess,road[1])
    tf.get_default_graph().as_graph_def()
    Xin=sess.graph.get_tensor_by_name('Xin:0')
    Yout=sess.graph.get_tensor_by_name("Yout:0") 
    accuracy=sess.graph.get_tensor_by_name('accuracy:0')
    Y=sess.graph.get_tensor_by_name('output:0')
    Ote=sess.run(accuracy,feed_dict={Xin:x_te,Yout:y_te})
    print("测试集准确率为:{:.4f}%".format(Ote*100))
    Ote=sess.run(accuracy,feed_dict={Xin:x_tr[30000:40000],Yout:y_tr[30000:40000]})
    print("训练集集准确率为:{:.4f}%".format(Ote*100))
    u=eval(input("输入0-9999之间的一个整数:"))
    if (u<0) or (u>9999):
        print('错误!')
        sess.close()
        return
    Otem=sess.run(Y,feed_dict={Xin:[x_te[u]]})
    print('手写的数字为:{}'.format(Otem.argmax()))
    plt.imshow(x_te[u].reshape(28,28))
    plt.show()#手写数字展示
    for i in [0,2,4,5,9]:
        roadpic=r'.\picturefile\handwriting'+str(i)+'.jpg'
        pic=cv2.imread(roadpic,flags=0)
        pic1=255-pic
        pic=pic1.reshape(-1,28,28,1)
        Otem=sess.run(Y,feed_dict={Xin:pic})
        print('高攀手写的数字为:{}'.format(Otem.argmax()))
        plt.imshow(pic1)
        plt.show()#手写数字展示
    sess.close()
    return

if __name__=="__main__":
    tf.disable_v2_behavior()
    os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
    main_train()
    main_test()

运行结果:
main_test结果1
第9953张测试集图片
5个自己制作的手写数字图片的模型预测结果

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python+tensorflow CNN卷积神经网络手写字体识别 的相关文章

随机推荐

  • C++——三种继承方式与三种访问权限的相互组合

    三种访问权限 public 可以被任意实体访问 protected 只允许子类及本类的成员函数访问 private 只允许本类的成员函数访问 三种继承方式 public 继承 protect 继承 private 继承 组合结果 基类中 继
  • Maven setting.xml国内镜像仓库(全)

    打开setting xml 位置在apache maven 3 6 1 conf下面 Ctrl 43 F 查找mirror标签位置加入即可 lt maven官方镜像 gt lt mirror gt lt id gt mirrorId lt
  • Android Studio创建项目

    一 创建新项目 二 选择空白页项目类型 三 设置项目信息 四 下载SDK 只有初次创建时会下载 下载完成 五 初始化项目工程 初始化完成
  • 解决MATLAB"尝试将 SCRIPT open 作为函数执行"的问题

    解决MATLAB 34 尝试将 SCRIPT open 作为函数执行 34 的问题 当关闭MATLAB一个脚本的时候 xff0c 再次双击打开 xff0c 会出现下图的情况 xff1a 脚本无法打开 xff0c 只能用实时脚本的方式打开 x
  • SMM(Spring+SpringMVC+MyBatis)

    Spring amp SpringMVC amp MyBatis 一 Spring的体系结构 自下往上 xff1a TestCore Container 核心容器 Beans xff1a 容器Core xff1a 核心Context xff
  • 二、SpringBoot基础配置

    二 SpringBoot基础配置 二 SpringBoot基础配置1 复制工程2 属性配置3 配置文件分类3 1 配置文件优先级3 2 教你一招 xff1a 自动提示功能消失解决方案 4 yaml文件5 yaml数据读取5 1 读取单一数据
  • FSK和ASK区别

    简介 市面上的遥控器常见的有FSK和ASK两种 xff0c 一种是有应答 xff0c 一种无应答 xff0c 现将主要区别罗列如下 FSK和ASK区别 FSK xff1a 频率调制 ASK xff1a 振幅调制 ASK IC一般只发射不接受
  • 关闭集群机器命令脚本

    背景 没有脚本时 xff0c 关闭集群里的Linux机器 xff0c 需要分别在每台机器执行关机命令 xff0c 费时费力 hadoop 64 node2 sudo init 0 hadoop 64 node3 sudo init 0 ha
  • ubuntu系统如何建立可执行文件

    第一步 xff1a 在桌面建立一个新建文档 gt 空文件 xff0c 文档重命名为test txt 第二步 xff1a 打开test txt xff0c 在文档的最顶端写入 bin bash xff08 独占一行 xff09 如 xff1a
  • 自己动手写操作系统(高清图书+源代码)分享

    很喜欢 自己动手写操作系统 这本书 xff0c 但现在这本书已经绝版了 在这里分享一下这本书的高清电子版和源代码 xff0c 感兴趣的人可以下载一下 链接 xff1a https pan baidu com s 1lPXg Airu2NFj
  • Android Studio闪屏页

    现在很多 App 启动都有闪屏页和功能引导页 xff0c 那么接下来我们就来先看看闪屏页是怎么实现的吧 首先创建一个新的工程 xff0c 然后创建一个新的Empty Activity xff0c 在这我就命名为SplashActivity
  • layui图标显示方框

    解决方法 检查一下class里面是不是少了一个图标的默认class layui icon
  • win10下python代码打包成exe文件并作为服务后在后台运行,开机自启

    1 pip安装pyinstaller pip install pyinstaller 2 打包python文件 打开cmd xff0c cd到项目文件夹 xff0c 并将主文件 xff08 我这里是web py xff09 用pyinsta
  • ubuntu为软件设定图标

    第一步 xff1a 进入到usr share applications 文件夹下 cd usr share applications 第二步 xff1a 创建桌面图标 xff1a sudo touch clion desktop 第三步 x
  • ubuntu18.04.1 开机默认进入命令行模式/用户图形界面

    一 开机默认进入命令行模式 1 输入命令 xff1a sudo systemctl set default multi user target 2 重启 xff1a reboot 要进入图形界面 xff0c 只需要输入命令startx 从图
  • ftp上传图片损坏怎么办?

    ftp不适用于普通的传输文件 xff0c 必须使用二进制的传输格式才可以保证图片上传不被损坏 添加这两行代码即可 xff01
  • python基础-古诗词填词游戏

    很久没写爬虫了 xff0c 利用这次接单来顺便写一下爬虫 文章目录 1 项目需求2 思路梳理3 诗句处理遇到的问题有4 目录结构5 实现步骤6 收获7 不足 1 项目需求 用python实现古诗词填词游戏 诗词库的组成 初中古诗 备注 xf
  • 谈谈如何确保数据的一致性

    谈谈如何确保数据的一致性 数据库必须具备的四个特性背景什么是接口的幂等性 xff1f 幂等性在哪里会用到 xff1f 技术方案总结 参考https blog csdn net u011635492 article details 81058
  • vmware esxi 虚拟机管理常用命令

    1 查看所有虚拟机列表 vim cmd vmsvc getallvms 2 挂起虚拟机 vim cmd vmsvc power suspend 13 命令行中的数字都是为vmid xff0c 以下同理 xff01 3 恢复或打开虚拟机 vi
  • python+tensorflow CNN卷积神经网络手写字体识别

    导入所需的库模块 xff1a span class token keyword import span os span class token keyword import span cv2 span class token keyword