学习笔记:实现CNN卷积神经网络处理MNIST数据集

学习时间:2021.07.25
学习内容: 实现CNN卷积神经网络处理MNIST数据集
编程环境: Tensorflow2.5、Python3.7、Google Colab
训练模型:EfficientNetB1
代码链接:https://colab.research.google.com/drive/1M4xzJA8mnxMS63mDrSPlkXJdziMzYhCq?usp=sharing

文章目录:

1.导包

# 获取权限:访问云端硬盘中的所有文件
from os.path import join
from google.colab import drive

ROOT = "/content/drive"
drive.mount(ROOT)
import matplotlib.pyplot as plt
import matplotlib as mpl
import matplotlib.ticker as ticker
import tensorflow as tf
from tensorflow.keras import datasets, layers, optimizers, Sequential, metrics
import os, time
import pandas as pd
import numpy as np
!gdown --id 1fsKERl26TNTFIY25PhReoCujxwJvfyHn
zhfont = mpl.font_manager.FontProperties(fname='SimHei .ttf')
zhfont2 = mpl.font_manager.FontProperties(fname='New Times Roman .ttf')
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"] = "0"

2.导入数据集

# 参数设置
# 参数设置
batch_size = 128
class_num = 10
epochs = 100
learning_rate_original = 0.01

# 数据类型转换
def preprocess(x, y):
    
    x = tf.cast(x, dtype=tf.float32) / 255.
    y = tf.cast(y, dtype=tf.int32)
    y = tf.one_hot(y, depth=class_num)
    return x,y

# 导入mnist数据
(x, y), (x_test, y_test) = datasets.mnist.load_data()

x = np.expand_dims(x, axis=3)
x = np.pad(x, ((0,0), (2,2), (2,2),(0,2)), 'edge')
x_test = np.expand_dims(x_test, axis=3)
x_test = np.pad(x_test, ((0,0), (2,2), (2,2),(0,2)), 'edge')

train_num = int(x.shape[0])
val_num = int(x_test.shape[0])

print(x.shape, y.shape, train_num, val_num)

db = tf.data.Dataset.from_tensor_slices((x,y))
db = db.map(preprocess).repeat().shuffle(10000).batch(batch_size)

db_test = tf.data.Dataset.from_tensor_slices((x_test,y_test))
db_test = db_test.map(preprocess).repeat().batch(batch_size)

# 打印数据形状
db_iter = iter(db)
sample = next(db_iter)
print('batch:', sample[0].shape, sample[1].shape)

db_iter = iter(db_test)
sample = next(db_iter)
print('batch:', sample[0].shape, sample[1].shape)
# Ir
import math
def lr_schedule(epoch):

    learning_rate = learning_rate_original*math.exp(0.01)

    if epoch > epochs*0.8:
        learning_rate = learning_rate_original*math.exp(-0.69)
    elif epoch > epochs*0.5:
        learning_rate = learning_rate_original*math.exp(-0.51)
    elif epoch > epochs*0.3:
        learning_rate = learning_rate_original*math.exp(-0.35)

    return learning_rate

lr_callback = tf.keras.callbacks.LearningRateScheduler(lr_schedule)

rng = [i for i in range(epochs)]
y = [lr_schedule(x) for x in rng]
plt.plot(rng, y)
print("Learning rate schedule: {:.3g} to {:.3g} to {:.3g}".format(y[0], max(y), y[-1]))

在这里插入图片描述

学习率变化曲线

3.模型创建

# model_01:EfficientNetB1
from tensorflow.keras.applications import EfficientNetB1

feature = EfficientNetB1(include_top=False, weights='imagenet', input_shape=(32,32,3))
model_01 = tf.keras.Sequential([feature,
                tf.keras.layers.GlobalAvgPool2D(),
                tf.keras.layers.Dropout(rate=0.1),
                tf.keras.layers.Dense(512),
                tf.keras.layers.Dropout(rate=0.1),
                tf.keras.layers.Dense(128),
                tf.keras.layers.Dense(class_num)])

model_01.summary()

在这里插入图片描述

4.模型训练

start_1 =time.perf_counter()
model_01.compile(optimizer=tf.keras.optimizers.SGD(learning_rate = learning_rate_original,momentum=0.9),
              loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
              metrics=["accuracy"])

callback = [tf.keras.callbacks.ModelCheckpoint(filepath='/content/save_weights/modle_01/my_model_{epoch}.h5',
                        save_best_only=True,
                        save_weights_only=True,
                        monitor='val_accuracy'),
                        lr_callback]
history = model_01.fit(x = db,
           steps_per_epoch = train_num // batch_size,
           epochs = epochs,
           validation_data = db_test,
           validation_steps = val_num // batch_size,
           callbacks = callback)
end_1 = time.perf_counter()

history_dict = history.history
train_loss = history_dict["loss"]
train_accuracy = history_dict["accuracy"]
val_loss = history_dict["val_loss"]
val_accuracy = history_dict["val_accuracy"]

print("Accuracy:", max(val_accuracy))
print('Tranning time:\t %s'%(end_1 - start_1))

5.训练效果

for i in range(0,epochs):
    val_accuracy[i] = val_accuracy[i] * 100
    train_accuracy[i] = train_accuracy[i] * 100
# figure 1
plt.figure(dpi = 100)
plt.gca().yaxis.set_major_formatter(ticker.FormatStrFormatter('%.2f'))#设置坐标轴精度
plt.plot(range(epochs), train_loss, label='Train', linestyle='--',linewidth = '0.8')
plt.plot(range(epochs), val_loss, color = 'red', label='Test',linewidth = '0.8')
plt.xlabel(u"训练迭代次数",fontproperties=zhfont,fontsize=14)
plt.ylabel(u"损失值",fontproperties=zhfont,fontsize=14)

plt.xticks(np.arange(0, epochs+1, 5),fontproperties = 'Times New Roman', size = 12)
plt.legend(fontsize=12)
plt.show()

# figure 2
plt.figure(dpi = 100)
plt.plot(range(epochs), train_accuracy, label='Train', linestyle='--',linewidth = '0.8')
plt.plot(range(epochs), val_accuracy,color = 'red', label='Test',linewidth = '0.8')
plt.xlabel(u"训练迭代次数",fontproperties=zhfont,fontsize=14)
plt.ylabel(u"准确率/%",fontproperties=zhfont,fontsize=14)

#设置label位置
plt.legend(loc='lower right',fontsize=12) 

plt.xticks(np.arange(0, epochs+1, 5),fontproperties = 'Times New Roman', size = 12)
plt.yticks(np.arange(0, 101,10),fontproperties = 'Times New Roman', size = 12)

plt.show()

在这里插入图片描述
在这里插入图片描述

训练总结

数据集模型名称模型参数量/M显卡训练时间/s准确率/%
MNISTEfficientNetB17.30NVIDIA Tesla T44574.0699.33

💗💗💗

print("如果文章对你有用,请点个赞呗O(∩_∩)O~")
System.out.println("如果文章对你有用,请点个赞呗O(∩_∩)O~");
cout<<"如果文章对你有用,请点个赞呗O(∩_∩)O~"<<endl;

💗💗💗

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
### 回答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等)具有更高的准确率。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值