利用卷积神经网络识别手写数字

冷不防 2022-04-15 06:39 433阅读 0赞

1.测试数据准备

1.我们使用的测试数据,可以直接从keras.datasets.mnist导入

  1. import numpy as np
  2. import seaborn as sns
  3. import matplotlib.pyplot as plt
  4. plt.rcParams['figure.figsize']=(7,7)
  5. from keras.datasets import mnist
  6. from keras.models import Sequential
  7. from keras.utils import np_utils
  8. import keras
  9. from keras.preprocessing.image import ImageDataGenerator
  10. from keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPool2D
  11. from keras.layers.normalization import BatchNormalization
  12. epochs = 20
  13. input_shape = (28, 28, 1)
  14. nb_classes = 10
  15. (X_train, y_train), (X_test, y_test) = mnist.load_data()
  16. print('X_train shape:', X_train.shape)
  17. print('X_test shape:', X_test.shape)

能看到一共有6W条训练数据和1W条测试数据
在这里插入图片描述
由于被墙的原因,mnist可能无法下载,可以换成本地数据导入的方式。下载数据请点击这里,数据导入方式换成

  1. path='./mnist.npz'
  2. f = np.load(path)
  3. X_train, y_train = f['x_train'], f['y_train']
  4. X_test, y_test = f['x_test'], f['y_test']
  5. f.close()

2.查看数据

  1. for i in range(9):
  2. plt.subplot(3, 3, i+1)
  3. plt.imshow(X_train[i], cmap='gray', interpolation='none')
  4. plt.title("Class {}".format(y_train[i]))

在这里插入图片描述
3.将数据格式转换为keras接受的数据结构

  1. X_train = X_train.reshape(X_train.shape[0], 28, 28, 1)
  2. X_test = X_test.reshape(X_test.shape[0], 28, 28, 1)
  3. print('X_train shape:', X_train.shape)
  4. print('X_test shape:', X_test.shape)

在这里插入图片描述
使用seaborn观察训练数据集的y值分布

  1. sns.countplot(y_train)

在这里插入图片描述

  1. Y_train = np_utils.to_categorical(y_train, nb_classes)
  2. Y_test = np_utils.to_categorical(y_test, nb_classes)
  3. print("Y_train:", Y_train.shape)

在这里插入图片描述

2.定义深度神经网络结构

  1. model = Sequential()
  2. model.add(Conv2D(32, kernel_size=(3,3), activation='relu', kernel_initializer='he_normal', input_shape=input_shape))
  3. model.add(Conv2D(32, kernel_size=(3,3), activation='relu', kernel_initializer='he_normal'))
  4. model.add(MaxPool2D(2,2))
  5. model.add(Dropout(0.2))
  6. model.add(Conv2D(64, kernel_size=(3,3), activation='relu', kernel_initializer='he_normal', padding='same'))
  7. model.add(Conv2D(64, kernel_size=(3,3), activation='relu', kernel_initializer='he_normal', padding='same'))
  8. model.add(MaxPool2D(2,2))
  9. model.add(Dropout(0.25))
  10. model.add(Conv2D(128, kernel_size=(3,3), activation='relu', kernel_initializer='he_normal', padding='same'))
  11. model.add(Dropout(0.25))
  12. model.add(Flatten())
  13. model.add(Dense(128, activation='relu'))
  14. model.add(BatchNormalization())
  15. model.add(Dropout(0.25))
  16. model.add(Dense(nb_classes, activation='softmax'))
  17. model.compile(loss=keras.losses.categorical_crossentropy,
  18. optimizer=keras.optimizers.Adam(),
  19. metrics=['accuracy'])
  20. model.summary()

在这里插入图片描述

3.训练模型

完成数据训练并保存训练好的模型

  1. datagen = ImageDataGenerator(featurewise_center=True, featurewise_std_normalization=True)
  2. datagen.fit(X_train)
  3. filepath = 'model.hdf5'
  4. from keras.callbacks import ModelCheckpoint
  5. # monitor计算每一个模型validation_data的准确率
  6. # save_best_only 只保存最好的一个模型
  7. checkpointer = ModelCheckpoint(filepath, monitor='val_acc', save_best_only=True, mode='max')
  8. # steps_per_epoch指定循环次数
  9. h = model.fit_generator(datagen.flow(X_train, Y_train, batch_size=500),
  10. steps_per_epoch=len(X_train)/1000, epochs=epochs,
  11. validation_data=datagen.flow(X_test, Y_test, batch_size=len(X_test)),
  12. validation_steps=1, callbacks=[checkpointer])

训练完成后可以看到模型在测试数据上的准确率已经达到了99.39%
在这里插入图片描述
我们可以用pyplot打印一下,随着epochs的执行,模型在训练数据和测试数据集的准确率的表现情况

  1. history = h.history
  2. accuracy = history['acc']
  3. val_accuracy = history['val_acc']
  4. loss = history['loss']
  5. val_loss = history['val_loss']
  6. epochs = range(len(accuracy))
  7. plt.plot(epochs, accuracy, 'bo', label='Training Accuracy')
  8. plt.plot(epochs, val_accuracy, 'b', label='Validation Accuracy')
  9. plt.title('Training and validation accuracy')
  10. plt.legend()
  11. plt.show()

在这里插入图片描述

4.模型评估

  1. from keras.models import load_model
  2. model = load_model('model.hdf5')
  3. score = model.evaluate(X_test, Y_test)
  4. print('Test score:', score[0])
  5. print('Test accuracy:', score[1])

可以看到一共有1W组数据,损失函数约为0.24,准确率达到了0.984,已经比较高了。
在这里插入图片描述

我们可以抽取一些预测数据,与真实值进行对比

  1. predicted_classes = model.predict_classes(X_test)
  2. correct_indices = np.nonzero(predicted_classes == y_test)[0]
  3. incorrect_indices = np.nonzero(predicted_classes != y_test)[0]

选取9个预测正确的进行打印

  1. plt.figure()
  2. for i, correct in enumerate(correct_indices[:9]):
  3. plt.subplot(3,3,i+1)
  4. plt.imshow(X_test[correct].reshape(28, 28), cmap='gray', interpolation='none')
  5. plt.title("Predicted {}, Class {}".format(predicted_classes[correct], y_test[correct]))

在这里插入图片描述
当然我们也可以选择9个错误的进行打印

  1. plt.figure()
  2. for i, incorrect in enumerate(incorrect_indices[:9]):
  3. plt.subplot(3,3,i+1)
  4. plt.imshow(X_test[incorrect].reshape(28, 28), cmap='gray', interpolation='none')
  5. plt.title("Predicted {}, Class {}".format(predicted_classes[incorrect], y_test[incorrect]))

在这里插入图片描述
可以看到,有一些真实值为1的图片,被识别错误了,说明模型还有一些改进的空间。

所有源码、测试数据以及训练好的模型已上传至git,点击这里可直接查看,有疑问的同学请在博客下方留言或提Issuees,谢谢!

发表评论

表情:
评论列表 (有 0 条评论,433人围观)

还没有评论,来说两句吧...

相关阅读