基于Keras的LetNet深度神经网络学习

本文介绍了卷积神经网络(CNN)在图像分类中的优势,尤其是对于空间信息的保留。通过对比2层神经网络与LeNet深度卷积神经网络在MNIST手写体识别任务上的表现,展示了LeNet如何通过卷积层、池化层和全连接层提高识别精度。在训练和测试过程中,LeNet达到了99.1%的准确率。文章还提供了详细的代码实现,包括网络结构定义和训练过程,并给出了训练和测试的损失及准确率曲线图。
摘要由CSDN通过智能技术生成

卷积神经网络

上一章对于MNIST手写体识别使用2层神经网络,accuracy = 92.2%。然而,这样的策略并未提取出空间结构和图像关系信息。其中,以下代码把每个位图表示的手写体数组转换成扁平向量,导致空间局部性消失。

# X_train是6000028*28的数据,变形为60000*784
X_train = X_train.reshape(60000, 784)
X_test = X_test.reshape(10000, 784)

卷积神经网络保留了空间信息,因此可以更好地使用于图像分类问题。如科学研究表明,我们的视觉基于多个皮质层,每层识别越来越多的结构性信息。首先,我们看到的是很多单个的像素;然后从这些像素中,我们识别出几何组成;再然后……这样越来越多的复杂的元素,最终物体、面部、人体躯干、动物被识别出来。

深度卷积神经网络——LeNet

用以训练MNIST手写字符集的识别,它对简单几何变换和扭转具有很好的鲁棒性。这里的关键点是让较低的网络层交替进行卷积和最大池化运算。
卷积操作基于仔细甄选的局部感受野,它们在多个特征平面共享权值。之后,更高的全连接网络层基于传统的多层感知机,它们包含隐藏层并将softmax作为输出层。
LeNet主要思路,第一层(20个卷积层),第二层(Max池化层),第三层(50个卷积层),第四层(Max池化层),第五层(全连接层),第六层(全连接输出层),以下就是程序:

# import the necessary packages
from keras import backend as K
from keras.models import Sequential
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.layers.core import Activation
from keras.layers.core import Flatten
from keras.layers.core import Dense
from keras.datasets import mnist
from keras.utils import np_utils
from keras.optimizers import SGD, RMSprop, Adam
import numpy as np

import matplotlib.pyplot as plt

np.random.seed(1671)  # for reproducibility


# define the convnet
class LeNet:
    @staticmethod
    def build(input_shape, classes):
        model = Sequential()
        # CONV => RELU => POOL
        #进行pad零填充 padding = 'same' ,kernel_size 声明了二维卷积窗的宽度和高度, 20个卷积滤波器
        # 因为使用零填充,所以输出与输入一致,输出28*28*1
        model.add(Conv2D(20, kernel_size=(5, 5), padding="same",
                         input_shape=input_shape))
        model.add(Activation("relu"))
        # stride=(2,2) 表示将使图片在两个维度上变成原来的一半,所以输出为14*14*1
        model.add(MaxPooling2D(pool_size=(2, 2), strides=2))
        # CONV => RELU => POOL
        #50个卷积滤波器,在更深的网络层增加滤波器数目使深度学习中一个普遍采用的技术,输入于输出一致
        model.add(Conv2D(50, kernel_size=(5, 5), padding="same"))
        model.add(Activation("relu"))
        model.add(MaxPooling2D(pool_size=(2, 2), strides=2))
        # Flatten => RELU layers
        #相当标准和扁平的全连接网络, 包含500个神经元, 其后是具有10个类别的softmax分类器
        model.add(Flatten())
        model.add(Dense(500))
        model.add(Activation("relu"))

        # a softmax classifier
        model.add(Dense(classes))
        model.add(Activation("softmax"))

        return model


# network and training
NB_EPOCH = 9
BATCH_SIZE = 128
VERBOSE = 1
OPTIMIZER = Adam()
VALIDATION_SPLIT = 0.2

IMG_ROWS, IMG_COLS = 28, 28  # input image dimensions
NB_CLASSES = 10  # number of outputs = number of digits
INPUT_SHAPE = (IMG_ROWS, IMG_COLS, 1)

# data: shuffled and split between train and test sets
(X_train, y_train), (X_test, y_test) = mnist.load_data()
K.image_data_format() == "channels_first"

# consider them as float and normalize
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_test /= 255

# we need a 60K x [28*28*1] shape as input to the CONVNET
X_train = X_train.reshape(-1, 28, 28, 1)  # normalize
X_test = X_test.reshape(-1, 28, 28, 1)      # normalize

print(X_train.shape[0], 'train samples')
print(X_test.shape[0], 'test samples')

# convert class vectors to binary class matrices
y_train = np_utils.to_categorical(y_train, num_classes=NB_CLASSES)
y_test = np_utils.to_categorical(y_test, num_classes=NB_CLASSES)

# initialize the optimizer and model
model = LeNet.build(input_shape=INPUT_SHAPE, classes=NB_CLASSES)
model.compile(loss="categorical_crossentropy", optimizer=OPTIMIZER,
              metrics=["accuracy"])

history = model.fit(X_train, y_train,
                    batch_size=BATCH_SIZE, epochs=NB_EPOCH,
                    verbose=VERBOSE, validation_split=VALIDATION_SPLIT)

score = model.evaluate(X_test, y_test, verbose=VERBOSE)
print("\nTest score:", score[0])
print('Test accuracy:', score[1])

# list all data in history
print(history.history.keys())
# summarize history for accuracy
# if val 'accuracy' is wrong, please use 'acc' replace it.
# if val 'history' is wrong, please use 'hist' replace it.
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.show()
# summarize history for loss
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.show()

总结

经过LeNet深度神经网络,MNIST手写体识别准确性可达到99.1%,相当于100张图片只有1张识别错误。顺便包括,训练和测试中的损失以及准确率曲线图。至此MNIST数据集完结,之后为CIFAR-10的数据集识别。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值