MNIST训练数字识别

文章目录

  • Keras搭建卷积网络训练模型详解
  • 全部代码

Keras搭建卷积网络训练模型详解

  • Keras里面自带了训练和测试数据集,我们要做的就是搭建Keras模块,并且确保训练集和测试集的数据和模块的参数相吻合
  • 导入Sequential 模型:在深度学习中,顺序模型是一种简单的线性堆叠模型,通过将层逐一叠加构建神经网络
import numpy as np
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense,Dropout,Flatten
from keras.layers.convolutional import Conv2D,MaxPooling2D
  • 读入数据,mnist.load_data(): 这是调用 MNIST 模块中的 load_data 函数,该函数用于加载 MNIST 数据集。MNIST 数据集是一个手写数字识别的经典数据集,包含了大量的手写数字图片,每张图片都标注了相应的数字。(x_train, y_train), (x_test, y_test): load_data 函数返回的是两个元组,分别包含了训练数据和测试数据。这两个元组的解构赋值分别为 (x_train, y_train) 和 (x_test, y_test)。x_train: 包含训练图像的 NumPy 数组。每个图像都是一个二维数组,表示手写数字的灰度图像。y_train: 包含训练图像对应的标签,即手写数字的真实数字值。x_test: 包含测试图像的 NumPy 数组。y_test: 包含测试图像对应的标签。
(x_train,y_train),(x_test,y_test) = mnist.load_data()
  • 输出print(x_train[0].shape)这行代码输出了训练数据集中第一个样本的形状。x_train 是一个 NumPy 数组,而每个样本都是一个二维数组(灰度图像)。通过 x_train[0],你获取到了第一个样本的图像数据,而 .shape 则是获取该数组的形状。输出的形状通常是一个元组,例如 (28, 28),表示图像是一个 28x28 像素的二维数组。
  • print(y_train[0]): 这行代码输出了训练数据集中第一个样本的标签。y_train 是一个包含训练样本标签的数组。输出的是该样本的真实标签,表示手写数字的数字值。例如,输出可能是一个介于 0 到 9 之间的整数,对应手写数字的真实值。
print(x_train[0].shape)
print(y_train[0])
  • 下面把训练集中的手写黑白字体变成标准的四维张量形式,即(样本数量,长,宽,1),并把像素值变成浮点格式
  • shape的第一个纬度是样本数量,第二个和第三个纬度是长和宽
  • 通过 reshape 操作,将其变为 (样本数量, 28, 28, 1),就添加了一个额外的维度,表示图像的通道数为 1
x_train = x_train.reshape(x_train.shape[0],28,28,1).astype('float32')
x_test = x_test.reshape(x_test.shape[0],28,28,1).astype('float32')
  • x_train 和 x_test 数组的元素进行归一化的操作,具体而言,每个元素都被除以 255
  • 相当于x_train = x_train / 255
x_train /= 255
x_test /= 255
  • 这个函数的输入是一个表示类别标签的整数 y,输出是一个包含独热编码的 NumPy 数组 y_ohe。独热编码是一种用于表示分类标签的编码方式,其中只有一个元素是1,其余元素都是0。这种编码方式广泛用于分类问题,特别是在深度学习中。
  • 举例来说,如果 y 是 3,那么对应的独热编码就是一个长度为10的数组,第4个元素(索引从0开始)为1,其余元素都为0,如下所示:
    [0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
    这样的独热编码可以使得模型更好地理解和处理类别信息。
def tran_y(y):
    y_ohe = np.zeros(10)
    y_ohe[y] = 1
    return y_ohe
  • 把标签用OneHot编码重新表示一下
y_test_ohe = np.array([tran_y(y_test[i]) for i in range(len(y_test))])
y_train_ohe = np.array([y_train(y_test[i]) for i in range(len(y_train))])
  • 接着搭建卷积神经网络,filters=64: 表示卷积层使用的卷积核(filter)的数量。在这里,有64个卷积核。kernel_size=(3,3): 指定卷积核的大小,这里是一个3x3的卷积核。strides=(1,1): 指定卷积核在水平和垂直方向上的步长。这里是在水平和垂直方向上都是1。padding=‘same’: 指定边界填充的方式。‘same’ 表示采用零填充(zero-padding),使得输出的特征图尺寸与输入的特征图尺寸相同。input_shape=(28,28,1): 指定输入的特征图的形状。这里是一个28x28的灰度图像,因此是 (28, 28, 1)。最后的1表示输入通道的数量。activation=‘relu’: 指定激活函数,这里使用的是 ReLU(Rectified Linear Unit)激活函数。
model.add(Conv2D(filters=64,kernel_size=(3,3),strides=(1,1),padding='same',input_shape=(28,28,1),activation='relu'))
  • 添加一个池化层 pool_size=(2,2): 指定了池化窗口的大小。在这里,使用了一个2x2的窗口。
model.add(MaxPooling2D(pool_size=(2,2)))
  • 具体来说,在这个例子中,每个训练批次中都会随机丢弃50%的输入单元。这有助于防止模型对特定的输入模式过度拟合,提高模型的泛化能力。在测试阶段,Dropout 层不会起作用,而是将所有单元保留,以获得更准确的预测。
model.add(Dropout(0.5))
  • 接着重复构造,搭建深度网络
model.add(Conv2D(filters=128,kernel_size=(3,3),strides=(1,1),padding='same',input_shape=(28,28,1),activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Dropout(0.5))
model.add(Conv2D(filters=256,kernel_size=(3,3),strides=(1,1),padding='same',input_shape=(28,28,1),activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Dropout(0.5))
  • 把当前节点展平,构造全连接网络层
model.add(Flatten())

model.add(Dense(128,activation='relu'))
model.add(Dense(64,activation='relu'))
model.add(Dense(32,activation='relu'))
model.add(Dense(10,activation='softmax'))
  • 最后定义损失函数,一般来说分类问题的损失函数都选择采用交叉熵
model.compile(loss='categorical_crossentropy',optimizer='adagrad',metrics=['accuracy'])
  • model.fit(x_train, y_train_ohe, validation_data=(x_test, y_test_ohe), epochs=20, batch_size=128): 这一行代码用于训练神经网络模型,使用训练数据 x_train 和对应的独热编码标签 y_train_ohe。validation_data 参数指定在训练过程中使用测试数据 (x_test, y_test_ohe) 进行验证。epochs 参数指定了训练的轮数,而 batch_size 参数定义了每个批次中的样本数。
  • scores = model.evaluate(x_test, y_test_ohe, verbose=0): 这一行代码用于在测试集上评估训练好的模型的性能。model.evaluate 函数返回一个包含模型性能指标的列表,这些指标可能包括损失和其他度量。在这里,评估的结果被存储在变量 scores 中。 verbose 参数为0表示在评估过程中不显示任何信息。
model.fit(x_train,y_train_ohe,validation_data=(x_test,y_test_ohe),epochs=20,batch_size=128)

scores = model.evaluate(x_test,y_test_ohe,verbose=0)

全部代码

import numpy as np
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense,Dropout,Flatten
from keras.layers.convolutional import Conv2D,MaxPooling2D

(x_train,y_train),(x_test,y_test) = mnist.load_data()

x_train = x_train.reshape(x_train.shape[0],28,28,1).astype('float32')
x_test = x_test.reshape(x_test.shape[0],28,28,1).astype('float32')

x_train /= 255
x_test /= 255

def tran_y(y):
    y_ohe = np.zeros(10)
    y_ohe[y] = 1
    return y_ohe

y_test_ohe = np.array([tran_y(y_test[i]) for i in range(len(y_test))])
y_train_ohe = np.array([tran_y(y_train[i]) for i in range(len(y_train))])

model = Sequential()

model.add(Conv2D(filters=64,kernel_size=(3,3),strides=(1,1),padding='same',input_shape=(28,28,1),activation='relu'))

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

model.add(Dropout(0.5))

model.add(Conv2D(filters=128,kernel_size=(3,3),strides=(1,1),padding='same',input_shape=(28,28,1),activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Dropout(0.5))
model.add(Conv2D(filters=256,kernel_size=(3,3),strides=(1,1),padding='same',input_shape=(28,28,1),activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Dropout(0.5))

model.add(Flatten())

model.add(Dense(128,activation='relu'))
model.add(Dense(64,activation='relu'))
model.add(Dense(32,activation='relu'))
model.add(Dense(10,activation='softmax'))

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

model.fit(x_train,y_train_ohe,validation_data=(x_test,y_test_ohe),epochs=20,batch_size=128)

scores = model.evaluate(x_test,y_test_ohe,verbose=0)

你可能感兴趣的:(深度学习,人工智能,手写数字识别)