从零开始,搭建CNN(卷积)神经网络识别Mnist手写体

运行环境

  • Windows 10 专业版 x64
  • Python 3.7.2
  • tensorflow 1.9
  • keras 2.2.4

导入工具包

  • 神经网络线性堆叠框架

    from keras.models import Sequential
    

    卷积神经网络拥有卷积层,池化层,展开层,全连接层等,该框架则是容纳各个网络层的东西,可以看做一个容器。

  • 卷积层,池化层,激活层,展开层,全连接层,Dropout层

    from keras.layers import Convolution2D,MaxPooling2D
    from keras.layers import Activation,Flatten,Dense,Dropout
    
  • 数据形态转换工具

    from keras.utils import np_utils
    

搭建模型

  • 加载数据集

    #mnist数据集,含有60000个训练数据以及10000个测试数据,样本图片均为1~9的数字手写体
    from keras.datasets import mnist
    (X_train,y_train),(X_test,y_test)=mnist.load_data()
    

    此处采用网络加载的方法,如果网络加载不可用或网络环境不太好,则可采用本地加载的方法。

    • 本地加载
      如图所示,按住Ctrl点击load_data。
      在这里插入图片描述
      将如图所示的load()改为本地mnist数据集所在的路径,根据自己的情况作修改,我是将mnist数据集放在Anaconda目录下的。
      在这里插入图片描述
      mnist数据集下载地址:https://s3.amazonaws.com/img-datasets/mnist.npz
      也可以采用其他方式下载,不过注意的是下载文件的扩展名要为npz,已经解过压的数据集的导入方式是不同的。
  • 转换图片数据状态

    X_train=X_train.reshape(X_train.shape[0],1,28,28)
    X_test=X_test.reshape(X_test.shape[0],1,28,28)
    

    原本的图片数据状态为:图片数量,图片宽度,图片高度
    转换后为:图片数量,图片深度,图片宽度,图片高度
    mnist数据集图片均为黑白图片,因此图片深度统一为1

  • 转换图片数据类型并限制数据范围

    X_train=X_train.astype('float32')
    X_test=X_test.astype('float32')
    X_train /=255
    X_test /=255
    

    黑白图片每个像素点都代表了0–255之间的一个数字,此时图片在计算机里是一个二维矩阵,将矩阵中的每个元素转换为浮点型,为了便于分析计算,将矩阵中每个元素限制到0–1之间

  • 转换标签的数据形态

    Y_train=np_utils.to_categorical(y_train,10)
    Y_test=np_utils.to_categorical(y_test,10)
    

    每个图片对应一个标签,标签即是图片识别的结果。
    一张标签对应一张图片,那么每个标签不外乎是0–9之间的数字,但这不是我们想要的。
    我们要将标签转换为一个列表,比如:
    0就是[1,0,0,0,0,0,0,0,0,0]
    1就是[0,1,0,0,0,0,0,0,0,0]
    2就是[0,0,1,0,0,0,0,0,0,0]

    以此类推

  • 创造模型框架

    model=Sequential()
    

    相当于把容器放好,要往里面添加神经网络了。

  • 添加第一个卷积层和激活层

    model.add(Convolution2D(32,3,3,input_shape=(1,28,28)))
    model.add(Activation('relu'))
    

    32表示过滤器(卷积核)的个数,3 3 表示过滤器的宽和高
    input_shape表示输入图片深度为1,宽为28,高为28
    经过一次卷积后图片大小为 26,26 (原始图片未经处理,卷积后图片缩小)
    激活层其实就是激活函数,最大的作用就是限制通过卷积核的结果(负数变为0,正数不变)

  • 添加第二个卷积层和激活层

    model.add(Convolution2D(32,3,3))
    model.add(Activation('relu'))
    

    经过两次卷积后图片大小为 24,24
    input_shape可以省略,如果要写,注意宽和高是26

  • 添加池化层,池化大小为2,2

    model.add(MaxPooling2D(pool_size=(2,2)))
    

    池化层的作用简单理解就是将上面卷积得到的图片变小变模糊,但保留了主要特征,至少从肉眼观看不影响识别。

  • 添加展开层

    model.add(Flatten())
    

    展开图像像素点,即把图像从二维变为一维

  • 添加全连接层

    model.add(Dense(128,activation='relu'))
    

    128代表神经元的个数,此处可以随意设置

  • 添加Dropout层,防止过拟合

    model.add(Dropout(0.5))
    
  • 再次添加全连接层

    model.add(Dense(10,activation='softmax'))
    

    此处神经元的个数只能为10,因为该全连接层也是输出层,对应10个标签。
    softmax代表非线性函数,输出的结果为“最初输入的图片,属于每个标签的概率”

  • 编译模型

    model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy'])
    

    目标:categorical_crossentropy(误差损失)尽可能小
    为了完成目标,使用方法:adam
    accuracy(准确率)来评估模型的预测效果

  • 训练模型

    model.fit(X_train,Y_train,batch_size=32,nb_epoch=10,validation_split=0.3)
    

    batch_size=32 一批处理32个样本
    nb_epoch=10 有10个周期(训练时比较吃CPU,如果对电脑没把握可以减小训练周期)
    validation_split=0.3 从训练样本中拿出30%作为交叉验证集,因此训练样本为42000个,在训练时有18000个样本参与测试

  • 评估模型(用测试数据集测试准确度)

    score=model.evaluate(X_test,Y_test)
    print(score)
    

到此,一个基本的CNN神经网络搭建完成,可以运行了

运行

ValueError: Negative dimension size caused by subtracting 3 from 1 for 'conv2d_1/convolution' (op: 'Conv2D') with input shapes: [?,1,28,28], [3,3,28,32].

如果出现该错误,则在程序最前面加上:

from keras import backend as K
K.set_image_dim_ordering('th')

运行截图

在这里插入图片描述
loss:误差损失(尽可能小)
acc:准确率
整个运行时间大概需要10分钟,即每个训练周期差不多1分钟,对电脑不自信的可以更改周期次数。

附:

from keras import backend as K
K.set_image_dim_ordering('th')

#导入网络的线性堆叠框架
from keras.models import Sequential

#导入卷积层,池化层
from keras.layers import Convolution2D,MaxPooling2D

#导入激活层,展开层,全连接层,Dropout层
from keras.layers import Activation,Flatten,Dense,Dropout

#导入数据形态转换工具
from keras.utils import np_utils

#加载数据集
#若网络加载异常,可采用本地文件加载,此处为网络加载
#mnist数据集,含有60000个训练数据以及10000个测试数据,样本图片均 为1~9的数字手写体
from keras.datasets import mnist
(X_train,y_train),(X_test,y_test)=mnist.load_data()

#转换图片数据形态  转换为 样本数量,图片深度,图片宽度,图片高度
X_train=X_train.reshape(X_train.shape[0],1,28,28)
X_test=X_test.reshape(X_test.shape[0],1,28,28)

#转换图片数据类型及限制数据范围  将数值范围从[0,255]标准化到[0,1]
X_train=X_train.astype('float32')
X_test=X_test.astype('float32')
X_train /=255
X_test /=255

#转换标签的数据形态
#0=[1,0,0,0,0,0,0,0,0,0]
#1=[0,1,0,0,0,0,0,0,0,0]
#...
Y_train=np_utils.to_categorical(y_train,10)
Y_test=np_utils.to_categorical(y_test,10)

#创造模型框架
model=Sequential()

#添加第一个卷积层和激活层
#32表示过滤器(卷积核)的个数,3 3 表示过滤器的宽和高
#input_shape表示输入图片深度为1,宽为28,高为28
#经过一次卷积后图片大小为 26,26  (原始图片未经处理,卷积后图片缩小)
model.add(Convolution2D(32,3,3,input_shape=(1,28,28)))
model.add(Activation('relu'))

#添加第二个卷积层和激活层
#经过两次卷积后图片大小为 24,24
model.add(Convolution2D(32,3,3))
model.add(Activation('relu'))

#添加池化层,池化大小为2,2
#经过池化处理后图片大小变为12,12
model.add(MaxPooling2D(pool_size=(2,2)))

#添加展开层,展开图像像素点
model.add(Flatten())

#添加全连接层
#128表示神经元个数,可随意设置
model.add(Dense(128,activation='relu'))

#防止过拟合
model.add(Dropout(0.5))

#再次添加全连接层
#此处也是输出层,神经元个数只能为10,对应10个标签
#softmax是非线性函数,输出的结果为“最初输入的图片,属于每个标签的概率”
model.add(Dense(10,activation='softmax'))

#编译模型
#目标:categorical_crossentropy(误差损失)尽可能小
#为了完成目标,使用方法:adam
#accuracy(准确率)来评估模型的预测效果
model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy'])

#训练模型  batch_size=32 一批处理32个样本
#nb_epoch=10 有10个周期
#validation_split=0.3 从训练样本中拿出30%作为交叉验证集
#因此训练样本为42000个,在训练时有18000个样本参与测试
model.fit(X_train,Y_train,batch_size=32,nb_epoch=10,validation_split=0.3)


#评估模型(用测试数据集测试准确度)
score=model.evaluate(X_test,Y_test)
print(score)

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: CNN卷积神经网络可以很好地实现MNIST数字识别数据集。MNIST数据集是一个非常流行的手数字识别数据集,包含60,000个训练样本和10,000个测试样本。CNN卷积神经网络可以通过卷积层、池化层和全连接层等结构,对图像进行特征提取和分类,从而实现对手数字的识别。在实现过程中,需要对数据进行预处理、构建模型、训练模型和评估模型等步骤。 ### 回答2: MNIST是机器学习领域中最基础的图像分类问题之一,目标是将手数字识别成对应的数字。CNN卷积神经网络由于其较高的效果和较快的速度,被广泛应用于此类问题中。 首先,我们需要明确CNN卷积神经网络的基本结构。它由多个卷积层和池化层组成,其中卷积层用于提取图像中的特征,而池化层则用于降低数据维度,减少运算量。在最后一层全连接层,特征将被映射到数字1-10的输出,以进行分类。 对于MNIST数字数据集,我们需要对数据进行预处理和格式化,以适应卷积神经网络的输入。我们可以将每个图片的大小调整为28x28像素,并将其转换为黑白图像。由于图像中的每个像素都代表相应位置的亮度值,我们需要在神经网络中进行标准化和归一化。 接下来,我们可以使用Keras框架搭建一个简单的卷积神经网络。其中,我们可以通过添加卷积层和池化层来实现特征提取和减少数据维度。在第一个卷积层后,我们可以添加一个批标准化层,它可以使每个神经元的输出分布更加均衡,从而提高训练效果。在卷积神经网络的输出端,我们可以添加一个全连接层,用于进行分类。 在完成网络结构的搭建之后,我们需要对卷积神经网络进行训练。我们可以通过设置合适的损失函数和优化算法来实现。针对MNIST数据集,我们可以选择使用交叉熵作为损失函数,随机梯度下降作为优化算法。我们可以通过调整学习率、正则化等参数,来提高训练效果。 最后,我们可以将卷积神经网络应用到MNIST测试集中进行验证,并评估其识别准确率。通过逐步调整网络结构和参数,我们可以不断改进卷积神经网络的性能,并实现更准确的手数字识别。 ### 回答3: MNIST数字识别是计算机视觉领域中一个经典的问题,它要求从图像中识别出手的数字。而CNN卷积神经网络是目前最有效的解决方案之一。 CNN卷积神经网络是一种深度学习模型,通过输入层、卷积层、池化层和全连接层等模块组成。在MNIST数字识别中,图片输入层将长度为28*28的二维像素矩阵作为输入,经过卷积层、池化层、全连接层等几个步骤后输出对应的数字。 卷积层的作用是提取图像的特征,由于MNIST数字数据集的像素尺寸较小,因此用到的卷积核尺寸也较小。这里我们选取的卷积核为5*5,每个卷积核进行卷积时将每个像素与其周围的8个像素做卷积操作,这样可以从图像中提取更多的特征信息。 池化层的作用是减小图像的尺寸,在卷积层中提取的特征信息可能包含了相同重复或无用的信息,因此需要对其进行降维处理。在MNIST数字识别中,我们采取的是平均池化的方式,即将相邻的4个像素取平均值,将这个4*4的图像块变为一个单独的像素。 全连接层的作用是将提取出的特征信息映射到输出层,输出对应的数字。在MNIST数字识别中,我们选取两个全连接层,其中第一层的神经元数量为120,第二层的神经元数量为84。最后,输出层的神经元数为10,每个神经元对应一个数字。 在训练模型时,我们采用交叉熵损失函数和随机梯度下降法更新权重。具体来说,我们将训练集分成若干个批次(batch),每次训练只使用其中一个批次的数据并对网络进行反向传播更新权重。 实验结果表明,CNN卷积神经网络能够在MNIST数字识别数据集上达到98%以上的识别率,比传统的机器学习方法(如SVM等)具有更高的准确率。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值