LeNet架构实施

我们将使用简单的LeNet在网络经过MNIST数据集训练后对其进行序列化。

LeNet实施:

让我们构建一个简单的最基本的卷积神经网络(CNN)架构--LeNet(识别手写数字)。在许多方面,LeNet + MNIST是应用于图像分类的“Hello,World”等效的深度学习。LeNet架构简单明了,体积小(就内存占用而言),非常适合教授卷积神经网络(CNN)的基础知识。

LeNet架构由以下层组成,使用CONV => ACT => POOL的模式

LeNet架构实施

LeNet架构总结

上表总结了LeNet架构的参数。我们的输入层采用28行,28列和单个通道(灰度)的输入图像作为深度(即MNIST数据集内图像的尺寸)。然后我们有20个filters,每个filter都是5×5。CONV层之后是ReLU激活,然后是2×2大小和2×2步幅的最大池。该架构的下一个块遵循相同的模式,这次学习50个5×5 filters。随着实际空间输入尺寸的减小,在网络的更深层中看到CONV层的数量增加是常见的。然后我们有两个FC层。第一个FC包含500个隐藏的音符,然后是ReLU激活。最后的FC层控制输出类标签的数量(0-9;每个可能的十个数字一个)。最后,原始架构:

INPUT => CONV => TANH => POOL => CONV => TANH => POOL => FC => TANH => FC

在今天实施LeNet时,将TANH替换为RELU是很常见的 - 我们将遵循相同的准则并使用ReLU作为我们的激活函数。

创建一个文件夹结构,并在新创建的文件夹cnn中添加一个名为lenet.py的新文件,并将其插入下面的Python代码中。

LeNet架构实施

#lenet.py
# import the necessary packages
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 import backend as K
class LeNet:
 @staticmethod
 def build(width, height, depth, classes):
 model = Sequential()
 inputShape =(height, width, depth)
 # if we are using "channels first", update the input shape
 #if K.image_data_format() == "channels_first":
 # inputShape = (depth, height, width)
 # first set of CONV => RELU => POOL layers
 model.add(Conv2D(20, (5, 5), padding="same",input_shape=inputShape))
 model.add(Activation("relu"))
 model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
 # second set of CONV => RELU => POOL layers
 model.add(Conv2D(50, (5, 5), padding="same"))
 model.add(Activation("relu"))
 model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
 # second set of CONV => RELU => POOL layers
 model.add(Conv2D(50, (5, 5), padding="same"))
 model.add(Activation("relu"))
 model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
 # first (and only) set of FC => RELU layers
 model.add(Flatten())
 model.add(Dense(500))
 model.add(Activation("relu"))
 # softmax classifier
 model.add(Dense(classes))
 model.add(Activation("softmax"))
 # return the constructed network architecture
 return model

LeNet架构实施

现在在cnn文件夹中,添加另一个名为lenet_mnist.py的文件并开始使用。lenet_mnist.py是一个驱动程序脚本,负责:

  1. 从磁盘加载MNIST数据集。
  2. 实例化LeNet架构。
  3. 训练LeNet。
  4. 评估网络性能。
# lenet_mnist.py
# USAGE
# python lenet_mnist.py
# import the necessary packages
from lenet import LeNet
from keras.optimizers import SGD
from sklearn.preprocessing import LabelBinarizer
from sklearn.datasets import fetch_mldata
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn import datasets
from keras import backend as K
import matplotlib.pyplot as plt
import numpy as np
# grab the MNIST dataset (if this is your first time using this
# dataset then the 55MB download may take a minute)
print("[INFO] accessing MNIST...")
dataset = datasets.fetch_mldata('MNIST original')
data = dataset.data
# if we are using "channels first" ordering, then reshape the
# design matrix such that the matrix is:
# num_samples x depth x rows x columns
if K.image_data_format() == "channels_first":
 data = data.reshape(data.shape[0], 1, 28, 28)
# otherwise, we are using "channels last" ordering, so the design
# matrix shape should be: num_samples x rows x columns x depth
else:
 data = data.reshape(data.shape[0], 28, 28, 1)
# scale the input data to the range [0, 1] and perform a train/test
# split
(trainX, testX, trainY, testY) = train_test_split(data / 255.0,
 dataset.target.astype("int"), test_size=0.25, random_state=42)
# convert the labels from integers to vectors
le = LabelBinarizer()
trainY = le.fit_transform(trainY)
testY = le.transform(testY)
# initialize the optimizer and model
print("[INFO] compiling model...")
opt = SGD(lr=0.01)
model = LeNet.build(width=28, height=28, depth=1, classes=10)
model.compile(loss="categorical_crossentropy", optimizer=opt,
 metrics=["accuracy"])
# train the network
print("[INFO] training network...")
H = model.fit(trainX, trainY, validation_data=(testX, testY),
 batch_size=128, epochs=20, verbose=1)
# evaluate the network
print("[INFO] evaluating network...")
predictions = model.predict(testX, batch_size=128)
print(classification_report(testY.argmax(axis=1),
 predictions.argmax(axis=1),
 target_names=[str(x) for x in le.classes_]))
# plot the training loss and accuracy
plt.style.use("ggplot")
plt.figure()
plt.plot(np.arange(0, 20), H.history["loss"], label="train_loss")
plt.plot(np.arange(0, 20), H.history["val_loss"], label="val_loss")
plt.plot(np.arange(0, 20), H.history["acc"], label="train_acc")
plt.plot(np.arange(0, 20), H.history["val_acc"], label="val_acc")
plt.title("Training Loss and Accuracy")
plt.xlabel("Epoch #")
plt.ylabel("Loss/Accuracy")
plt.legend()
plt.show()

LeNet架构实施

要执行我们的脚本,只需发出以下命令:

$ python lenet_mnist.py

然后应从磁盘下载和/或加载MNIST数据集,并开始训练:

LeNet架构实施

LeNet架构实施

这个图表显示了LeNet在MNIST上的损失和准确性,可以说是我们正在寻找的典型图:训练和验证损失和准确性相互模拟(几乎)完全没有过度拟合的迹象。正如我们所看到的,通常很难获得这种行为非常好的训练图,表明我们的网络正在学习基础模式而不会过度拟合。

还有一个问题是,MNIST的数据集是经过大量预处理的,这不能代表我们在现实世界中遇到的图像分类问题。研究人员倾向于使用MNIST数据集作为评估新分类算法的基准。如果他们的方法不能获得> 95%的分类准确度,那么(1)算法的逻辑或(2)实现本身存在缺陷。

相关推荐