Tensorflow框架搭建卷积神经网络CNN训练mnist数据集

本文将用Tensorflow框架训练Mnist数据集,搭建卷积神经网络CNN,损失将以动态折线图方式展示。
卷积如何工作?
首先大家看一下下面的全连接神经网络,从这张图我们知道,全连接神经网络中,每一层的每个神经元输出的特征都被下一层每一个神经元接收,公式表达为 f(wx+b),f为激活函数,w是权重,截取自标准正态分布,b为偏置,上一层的输出作为下一层的输入,即便某一个神经元的输出并没有特征,或者是干扰信息,也会被下一层所接受,那么这就产生了两个问题,第一:计算量太大;第二:获取特征不准确,精度低,对于多特征的提取效果差。
在这里插入图片描述
分析了全连接的工作原理,我们知道全连接特征提取效果不好,那么卷积是如何工作的呢?下图黄色部分可以看作是一个3×3的卷积核,在工作的时候,对应位置相乘,就把3×3的区域卷成了一个1×1的区域,称为特征图。卷积核里面的值为权重w,w初始是随机的,训练的过程中不断更新w的值,直到损失变得很小。在这里插入图片描述
在这里插入图片描述
由此可见,卷积神经网络特征提取的准确度更高,效果更好,计算量也减小了,训练速度加快。
卷积神经网络中其他技术
池化
池化的作用就是把特征图减小,降低计算量,池化分为最大池化和平均池化,一般最大池化用的多。
在这里插入图片描述
Tensorflow框架搭建卷积神经网络CNN训练Mnist数据集
理论讲完了,下面来实现一个基于Tensorflow的CNN网络,用来识别手写数字mnist数据集。
1.首先导入tensorflow和tensorflow中的mnist数据集,设置为one-hot的形式:

import tensorflow as tf
import numpy as np
from tensorflow.examples.tutorials.mnist import input_data
mnist=input_data.read_data_sets(".\MNIST_data",one_hot=True)

2.然后导入PIL库用来画图,展示标签和识别结果,并对比:

import matplotlib.pyplot as plt
import PIL.Image as pimg
import PIL.ImageDraw as pdraw
import PIL.ImageFont as pfont
font_path="msyh.ttf"

3.self.x是神经网络的输入,self.y是神经网络的输出,(这里为什么写成这样参考我上一篇博客https://blog.csdn.net/weixin_44928646/article/details/104519603)
self.w1和self.b1是神经网络的第一层,shape=[N,H,W,C],3×3的卷积核。


self.x=tf.placeholder(shape=[None,784],dtype=tf.float32)
self.y=tf.placeholder(shape=[None,10],dtype=tf.float32)
self.w1=tf.Variable(tf.truncated_normal(shape=[3,3,1,16],stddev=tf.sqrt(1/16),dtype=tf.float32))
self.b1=tf.Variable(tf.zeros(shape=[16],dtype=tf.float32))

4.定义前向通道,首先进行形状变换,把[N,V]=[N,784]->[N,H,W,C]=[-1,28,28,1],因为卷积输入格式为***[N,H,W,C]***,下面就是计算卷积了,每一层卷积完加一层池化。

def forward(self):
    x=tf.reshape(self.x,shape=[-1,28,28,1])
         y1=tf.nn.relu(tf.layers.batch_normalization(tf.nn.conv2d(x,self.w1,strides=[1,1,1,1],padding="SAME")+self.b1))#28*28*16
         dr_y1=tf.nn.dropout(y1,keep_prob=self.dropout)
         pool_y1=tf.nn.max_pool(dr_y1,[1,2,2,1],[1,2,2,1],padding="SAME")#14*14*16
         y2 = tf.nn.relu(tf.layers.batch_normalization(tf.nn.conv2d(pool_y1, self.w2,strides=[1,1,1,1],padding="SAME") + self.b2))#14*14*128
         dr_y2 = tf.nn.dropout(y2, keep_prob=self.dropout)
         pool_y2 = tf.nn.max_pool(dr_y2,[1,2,2,1],[1,2,2,1],padding="SAME")#7*7*128

5.卷积完之后,最后加一层全连接,注意[N,H,W,C]->[N,V],然后用softmax激活后输出

y2=tf.reshape(pool_y2,shape=[-1,7*7*128])
self.y3 =tf.layers.batch_normalization(tf.matmul(y2, self.w3) + self.b3)
self.output=tf.nn.softmax(self.y3)

6.用交叉熵作损失

def loss(self):
     self.error=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=self.y,logits=self.y3))
         +param*tf.reduce_sum(self.w1**2)+param*tf.reduce_sum(self.w2**2)+param*tf.reduce_sum(self.w3**2)

7.Adam优化器优化损失,学习率0.001

def backward(self):
         # self.optimizer=tf.train.GradientDescentOptimizer(0.001).minimize(self.error)
         self.optimizer=tf.train.AdamOptimizer(0.001).minimize(self.error)

8.下面的就是主函数,训练次数50000次,每次取100张图片训练,每训练100次验证一次。
完整程序:

import tensorflow as tf
import numpy as np
from tensorflow.examples.tutorials.mnist import input_data
mnist=input_data.read_data_sets(".\MNIST_data",one_hot=True)
import matplotlib.pyplot as plt
import PIL.Image as pimg
import PIL.ImageDraw as pdraw
import PIL.ImageFont as pfont
font_path="msyh.ttf"
param=0.01

class Net:
     def __init__(self):
         self.x=tf.placeholder(shape=[None,784],dtype=tf.float32)
         self.y=tf.placeholder(shape=[None,10],dtype=tf.float32)
         self.w1=tf.Variable(tf.truncated_normal(shape=[3,3,1,16],stddev=tf.sqrt(1/16),dtype=tf.float32))
         self.b1=tf.Variable(tf.zeros(shape=[16],dtype=tf.float32))
         self.w2=tf.Variable(tf.truncated_normal(shape=[3,3,16,128],stddev=tf.sqrt(1/128),dtype=tf.float32))
         self.b2=tf.Variable(tf.zeros(shape=[128],dtype=tf.float32))
         self.w3=tf.Variable(tf.truncated_normal(shape=[7*7*128,10],stddev=tf.sqrt(1/10),dtype=tf.float32))
         self.b3=tf.Variable(tf.zeros(shape=[10],dtype=tf.float32))
         self.dropout=tf.placeholder(dtype=tf.float32)

     def forward(self):
         x=tf.reshape(self.x,shape=[-1,28,28,1])

         y1=tf.nn.relu(tf.layers.batch_normalization(tf.nn.conv2d(x,self.w1,strides=[1,1,1,1],padding="SAME")+self.b1))#28*28*16
         dr_y1=tf.nn.dropout(y1,keep_prob=self.dropout)
         pool_y1=tf.nn.max_pool(dr_y1,[1,2,2,1],[1,2,2,1],padding="SAME")#14*14*16
         y2 = tf.nn.relu(tf.layers.batch_normalization(tf.nn.conv2d(pool_y1, self.w2,strides=[1,1,1,1],padding="SAME") + self.b2))#14*14*128
         dr_y2 = tf.nn.dropout(y2, keep_prob=self.dropout)
         pool_y2 = tf.nn.max_pool(dr_y2,[1,2,2,1],[1,2,2,1],padding="SAME")#7*7*128

         y2=tf.reshape(pool_y2,shape=[-1,7*7*128])

         self.y3 =tf.layers.batch_normalization(tf.matmul(y2, self.w3) + self.b3)
         self.output=tf.nn.softmax(self.y3)

     def loss(self):
         self.error=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=self.y,logits=self.y3))
         +param*tf.reduce_sum(self.w1**2)+param*tf.reduce_sum(self.w2**2)+param*tf.reduce_sum(self.w3**2)

     def backward(self):
         # self.optimizer=tf.train.GradientDescentOptimizer(0.001).minimize(self.error)
         self.optimizer=tf.train.AdamOptimizer(0.001).minimize(self.error)

     def accuracy(self):
         y=tf.equal(tf.argmax(self.output),tf.argmax(self.y))
         self.acc=tf.reduce_mean(tf.cast(y,dtype=tf.float32))

if __name__ == '__main__':
    net=Net()
    net.forward()
    net.loss()
    net.backward()
    net.accuracy()
    init=tf.global_variables_initializer()
    plt.ion()
    a=[]
    b=[]
    c=[]

    with tf.Session() as sess:
        sess.run(init)
        for i in range(50000):
            xs,ys=mnist.train.next_batch(100)
            error,_=sess.run([net.error,net.optimizer],feed_dict={net.x:xs,net.y:ys,net.dropout:0.5})

            if i%100==0:
                xss,yss=mnist.validation.next_batch(100)
                _error,_output,acc=sess.run([net.error,net.output,net.acc],feed_dict={net.x:xss,net.y:yss,net.dropout:1})
                label=np.argmax(yss[0])
                out=np.argmax(_output[0])
                print("acc", acc)
                print("label:",label,"output:",out,"error:",_error)
                a.append(i)
                b.append(error)
                c.append(_error)

                plt.clf()
                plt.subplot(1,2,1)
                train,=plt.plot(a,b,color="red")
                validation,=plt.plot(a,c,color="blue")
                plt.legend([train,validation],["train","validation"])


                plt.subplot(1,2,2)
                font = pfont.truetype(font=font_path, size=10)
                arr = np.reshape(xss[0], [28, 28]) * 255
                img = pimg.fromarray(arr)
                imagedraw = pdraw.ImageDraw(img)
                imagedraw.text(xy=(1, 1), text=str(out), fill=255, font=font)
                plt.imshow(img)

                plt.pause(0.01)


    plt.ioff()


9.训练结果以动态方式展现,下面是两张截图,开始训练和训练结束
在这里插入图片描述
在这里插入图片描述
train:训练损失
validation:验证损失
大数字:标签label
坐上小数字:训练输出
10.结论:用卷积神经网络CNN识别手写数字,速度是很快的,只需训练不到100次,就可以得到接近0的损失,准确率很高,速度很快。
11.训练的动态视频可以点击这个链接看:https://www.bilibili.com/video/av91959887/

转载或引用请注明来源!

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: MNIST 数据集是一个用来识别手写数字的常见数据集。要使用 CNN 实现 MNIST 数据集的识别,需要执行以下步骤: 1. 准备数据。MNIST 数据集包含 60000 张训练图像和 10000 张测试图像。图像是 28x28 的灰度图像,每张图像都有一个与之对应的标签(数字)。 2. 构建 CNN 模型。CNN 通常由输入层、卷积层、池化层和全连接层组成。首先,输入层接受图像数据。然后,卷积层会使用不同的卷积核(又称滤波器)对输入进行卷积,从而提取图像的特征。池化层则会将提取的特征缩小,以减小模型的复杂度。最后,全连接层会将特征映射到输出,即对应的标签。 3. 训练模型。使用训练数据训练模型。训练过程中,模型会自动调整权重和偏置,以使模型的预测更准确。 4. 评估模型。使用测试数据评估模型的准确率。这有助于检查模型是否过拟合或欠拟合,并且可以为进一步提升模型性能提供线索 ### 回答2: CNN卷积神经网络(Convolutional Neural Network)的缩写,它是一种深度学习网络结构,可以用于图像识别任务。MNIST数据集是一个常用的手写数字识别数据集,包含了60000个训练样本和10000个测试样本,每个样本都是一个28×28像素的灰度图像。下面是使用CNN实现MNIST数据集识别的步骤: 1. 数据准备:首先,我们需要将MNIST数据集导入到程序中。可以使用Python的numpy和matplotlib库来加载和处理数据。数据集包含了训练集和测试集,每个样本都有对应的标签。 2. 构建CNN模型:我们需要设计一个合适的卷积神经网络模型来训练和识别MNIST数据集CNN通常由卷积层、池化层和全连接层组成。可以使用Keras或PyTorch等深度学习库来构建模型,选择适当的网络结构和参数进行训练。 3. 模型训练:将准备好的训练数据输入到CNN模型中进行训练训练过程中,模型会自动调整参数,通过反向传播算法更新权重。训练可以通过设置合适的超参数(如学习率、批次大小和训练轮数)来进行。 4. 模型评估:训练完成后,使用测试集评估模型的性能。将测试集输入到已训练好的模型进行预测,并与测试集中的真实标签进行对比。可以使用准确率等指标来评估模型的性能。 5. 模型应用:训练好的CNN模型可以应用于实际图像识别任务中。使用模型对新的手写数字图像进行预测,输出对应的数字标签。 通过以上步骤,我们可以使用CNN实现对MNIST数据集的识别。CNN在图像识别任务中取得了很好的效果,其卷积和池化操作可以有效地提取图像的特征,从而实现高精度的识别。 ### 回答3: CNN是一种深度学习算法,可以应用于图像识别任务,其中非常经典的一个应用就是用CNN实现MNIST数据集的识别。 MNIST数据集是一个由手写数字组成的数据集,其中包含了60000个训练样本和10000个测试样本,每个样本是一个28×28像素的灰度图像。 CNN的结构通常由卷积层、池化层和全连接层构成。首先,卷积层通过使用卷积核对输入图像进行卷积操作,提取图像的特征。卷积操作可以捕获图像中的边缘、纹理等特征。接下来,经过池化层的操作,通过降低特征图的维度,减少参数数量,同时保留主要的特征。最后,通过全连接层将提取的特征输入到 softmax 分类器中,实现对不同数字的分类。 具体实现中,可以使用Python语言和深度学习框架TensorFlow来实现CNN模型。首先,加载MNIST数据集,并对图像进行预处理,将其归一化到0-1之间。然后,搭建CNN模型,可以选择合适的卷积核大小、池化方式和激活函数等。接着,定义损失函数,一般使用交叉熵损失函数。最后,使用优化算法,如梯度下降法,来不断调整模型参数,使得损失函数最小化。 训练模型时,将训练样本输入CNN模型中,通过反向传播算法进行参数的更新,直到达到预设的停止条件。训练完成后,使用测试集评估模型的性能,计算准确率等指标。 通过实现CNN模型对MNIST数据集的识别,可以获得很高的准确率,达到甚至超过人类的识别能力。这个实验可以帮助我们理解深度学习CNN在图像识别领域的应用,并为以后深入研究和实践提供基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值