深度学习——卷积神经网络来龙去脉和MINST图像识别应用
共 5735字,需浏览 12分钟
·
2021-09-26 23:58
点击下方卡片,关注“新机器视觉”公众号
视觉/图像重磅干货,第一时间送达
写在前面
在此之前,我总结记录了一些机器学习的实战,包括《机器学习应用——电影评论情感分析模型构建》《多分类器集成学习:多数票机制、Bagging、Adaboost实例分析》《基于sklearn库的机器学习模型与调优实践详细步骤》等,感兴趣的伙伴可以查看,偏向实践更加有趣!
这次准备总结之前学习到的CNN,整理了卷积神经网络的详细内容,了解其原理来龙去脉,掌握实战深入浅出。
深度卷积神经网络(DCNN)
1、卷积神经网络
卷积神经网络(Convolutional Neural Network,CNN,又称为ConvNet)有着它特殊的功能,网络中保留了空间信息,因此可以更好地适用于图像分类问题。原理来源于人类视觉生物学数据的启发,视觉基于多个皮质层,每层识别越来越多的结构性信息。我们看到的是很多单个的像素;然后从这些像素中,我们识别出几何组成;再然后……这样越来越多的复杂的元素,如物体、面部、人类躯干、动物等被识别出来。
很明显,图像识别分类问题就是CNN的用武之地。
深度卷积神经网络,是由很多神经网络层组成。卷积层和池化层这两种不同的网络层,经常交互出现。每个滤波器的深度在网络中由左向右增加。最后一部分通常由一个或多个全连接层组成,如下图。
CNN中最基础的操作是卷积,再精确一点,基础CNN所用的卷积是一种2-D卷积。也就是说,kernel只能在x,y上滑动位移,不能进行深度 (跨通道) 位移。
假设输入图像使用tf(TensorFlow)顺序,它在3个信道上的形状为(256,256),这可以表示成(256, 256, 3)。Keras中,添加一个输出维度为32并且每个滤波器为3×3的卷积层,可以写成:
model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=(256, 256, 3))
这就是说,我们用3个输入信道(或输入滤波器)在一个256×256的图像上进行3×3的卷积运算,得到了一个32个信道(输出滤波器)的输出,卷积结果类似下图。
池化,是一种降采样操作,主要目标是降低feature maps的特征空间,或者可以认为是降低feature maps的分辨率。因为feature map参数太多,而图像细节不利于高层特征的抽取。
常用的有最大池化和平均池化。
最大池化:简单地输出最大激活值作为这个区域的观测结果。在Keras中,定义一个2×2的最大池化层:
model.add(MaxPooling2D(pool_size = (2, 2)))
直观地举例如图:
平均池化:把这个区域观察到的激活值取平均值。如上图用平均池化则会得到:[[1.7,4],[3.75,2,5]]
Keras构建LeNet——CNN族群
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
定义LeNet网络:
# 定义ConvNet
class LeNet:
@staticmethod
def build(input_shape, classes):
model = Sequential()
# CONV => RELU => POOL
model.add(Conv2D(20, kernel_size=5, padding="same",
input_shape=input_shape))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
# CONV => RELU => POOL
model.add(Conv2D(50, kernel_size=5, border_mode="same"))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
# Flatten层到RELU层
model.add(Flatten())
model.add(Dense(500))
model.add(Activation("relu"))
model.add(Dense(classes))
model.add(Activation("softmax"))
return model
1、最先是卷积阶段,我们使用ReLU激活函数,并用最大池化方法。我们的网络将学习20个卷积滤波器,其中每个滤波器的大小都是5×5。输出维度和输入形状相同,因而将是28×28像素。注意,因为二维卷积是我们管道中的第一个阶段,我们必须定义它的input_shape。最大池化操作实现了一个滑窗,它在网络层上滑动,并取水平和垂直各两个像素区域上的最大值。
2、之后的第二个卷积阶段也是用ReLU激活函数,后面再次跟着最大池化方法。把学到的卷积滤波器数量从前面的20增加到50个。在更深的网络层增加滤波器数目是深度学习中一个普遍采用的技术。
3、最后一个全连接网络,它包含500个神经元,其后是具有10个类别的softmax分类器。
深度学习CNN识别MINST图像
训练集和测试集划分:
60000 train samples
10000 test samples
完整代码和详细注释如下:
# 网络和训练
NB_EPOCH = 5
BATCH_SIZE = 128
VERBOSE = 1
OPTIMIZER = Adam()
VALIDATION_SPLIT = 0.2
IMG_ROWS, IMG_COLS = 28, 28
NB_CLASSES = 10
INPUT_SHAPE = (1, IMG_ROWS, IMG_COLS)
# 混合并划分训练集和测试集数据
(X_train, y_train), (X_test, y_test) = mnist.load_data()
K.set_image_dim_ordering("th")
# 把它们看成float类型并归一化
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_test /= 255
# 我们需要使用形状60K×[1×28×28]作为卷积网络的输入
X_train = X_train[:, np.newaxis, :, :]
X_test = X_test[:, np.newaxis, :, :]
print(X_train.shape[0], 'train samples')
print(X_test.shape[0], 'test samples')
# 将类向量转换成二值类别矩阵
y_train = np_utils.to_categorical(y_train, NB_CLASSES)
y_test = np_utils.to_categorical(y_test, NB_CLASSES)
# 初始化优化器和模型
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("Test score:", score[0])
print('Test accuracy:', score[1])
# 列出全部历史数据
print(history.history.keys())
# 汇总准确率历史数据
plt.plot(history.history['acc'])
plt.plot(history.history['val_acc'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.show()
# 汇总损失函数历史数据
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()
经过5个epoch,就获得一个近似99%的准确率,绘制出模型准确率和损失函数的变化图如图。
Test accuracy: 0.9899
总结
这一篇整理了卷积神经网络的详细内容,了解其原理来龙去脉,通过简单入门项目深入浅出。CNN在图像识别分类的应用广泛,在许多深度学习任务中也会用到CNN神经网络。
—版权声明—
仅用于学术分享,版权属于原作者。
若有侵权,请联系微信号:yiyang-sy 删除或修改!