数据挖掘入门系列教程(十二)之使用keras构建CNN网络识别CIFAR10

简介

在上一篇博客:数据挖掘入门系列教程(十一点五)之CNN网络介绍中,介绍了CNN的工做原理和工做流程,在这一篇博客,将具体的使用代码来讲明如何使用keras构建一个CNN网络来对CIFAR-10数据集进行训练。html

若是对keras不是很熟悉的话,能够去看一看官方文档。或者看一看我前面的博客:数据挖掘入门系列教程(十一)之keras入门使用以及构建DNN网络识别MNIST,在数据挖掘入门系列教程(十一)这篇博客中使用了keras构建一个DNN网络,并对keras的作了一个入门使用介绍。python

CIFAR-10数据集

CIFAR-10数据集是图像的集合,一般用于训练机器学习和计算机视觉算法。它是机器学习研究中使用比较广的数据集之一。CIFAR-10数据集包含10 种不一样类别的共6w张32x32彩色图像。10个不一样的类别分别表明飞机,汽车,鸟类,猫,鹿,狗,青蛙,马,轮船 和卡车。每一个类别有6,000张图像git

在keras刚好提供了这些数据集。加载数据集的代码以下所示:github

from keras.datasets import cifar10

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

print(x_train.shape, 'x_train samples')
print(x_test.shape, 'x_test samples')
print(y_train.shape, 'y_trian samples')
print(y_test.shape, 'Y_test samples')

输出结果以下:算法

image-20200501103647417

训练集有5w张图片,测试集有1w张图片。在\(x\)数据集中,图片是\((32,32,3)\),表明图片的大小是\(32 \times 32\),为3通道(R,G,B)的图片。网络

展现图片内容

咱们能够稍微的展现一下图片的内容,python代码以下所示:机器学习

import matplotlib.pyplot as plt
%matplotlib inline

plt.figure(figsize=(12,10))
x, y = 8, 6

for i in range(x*y):  
    plt.subplot(y, x, i+1)
    plt.imshow(x_train[i],interpolation='nearest')
plt.show()

下面就是数据集中的部分图片:ide

数据集变换

一样,咱们须要将类标签进行one-hot编码:学习

import keras
# 将类向量转换为二进制类矩阵。
y_train = keras.utils.to_categorical(y_train, 10)
y_test = keras.utils.to_categorical(y_test, 10)

实际上这一步还有不少牛逼(骚)操做,好比说对数据集进行加强,变换等等,这样均可以在必定程度上提升模型的鲁棒性,防止过拟合。这里咱们就怎么简单怎么来,就只对数据集标签进行one-hot编码就好了。测试

构建CNN网络

构建的网络模型代码以下所示:

from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten,Conv2D, MaxPooling2D

# 构建CNN网络
model = Sequential()

# 添加卷积层
model.add(Conv2D(32, (3, 3), padding='same',input_shape=x_train.shape[1:]))
# 添加激活层
model.add(Activation('relu'))
model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))

# 添加最大池化层
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Conv2D(64, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

# 将上一层输出的数据变成一维
model.add(Flatten())
# 添加全链接层
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(10))
model.add(Activation('softmax'))

# 网络模型的介绍
print(model.summary())

这里解释一下代码:

Conv2D

Conv2D表明2D的卷积层,可能这里会有人问,个人图片不是3通道(RGB)的吗?为何使用的是Conv2D而不是Conv3D。首先先说明,在Conv2D中的这个“2”表明的是卷积层能够在两个维度(也就是width,length)进行移动。那么同理Conv3D中的“3”表明这个卷积层能够在3个维度进行移动(好比说视频中的width ,length,time)。那么针对RGB这种3通道(channels),卷积过程当中输入有多少个通道,则滤波器(卷积核)就有多少个通道。

简单点来讲就是:

输入

单色图片的input,是2D, \(w \times h\)
彩色图片的input,是3D,\(w \times h \times channels\)

卷积核filter

单色图片的filter,是2D, \(w \times h\)
彩色图片的filter,是3D, \(w \times h \times channels\)

值得注意的是,卷积以后的结果是二维的。(由于会将3维卷积获得的结果进行相加)

接着继续解释Conv2D的参数:

Conv2D(32, (3, 3), padding='same',input_shape=x_train.shape[1:])

  • 32表示的是输出空间的维度(也就是filter滤波器的输出数量)
  • (3,3)表明的是卷积核的大小
  • strides(这里没有用到):这个表明是滑动的步长。
  • input_shape:输入的维度,这里是(28,28,3)

padding在上一篇博客介绍过,在keras中有两个取值:"valid""same" (大小写敏感)。

  • valid padding:不进行任何处理,只使用原始图像,不容许卷积核超出原始图像边界
  • same padding:进行填充,容许卷积核超出原始图像边界,并使得卷积后结果的大小与原来的一致

Flatten

Flatten这一层就是为了将多维数据变成一维数据:

构建网络

from keras.optimizers import RMSprop
# 利用 RMSprop 来训练模型。
model.compile(loss='categorical_crossentropy',
              optimizer=RMSprop(),
              metrics=['accuracy']
             )

其余的参数在上两篇博客中已经讲了,就再也不赘述。

进行训练评估

这里你们能够根据本身的电脑配置适当调整一下batch_size的大小。

history = model.fit(x_train, y_train,
                    batch_size=32,
                    epochs=64,
                    verbose=1,
                    validation_data=(x_test, y_test)
                   )

在i5-10代u,mx250的状况下,训练一轮大概须要27s左右。

训练完成以后,进行评估:

score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

结果以下所示:

这个结果能够说的上是一言难尽,😔。

查看历史训练状况

import matplotlib.pyplot as plt

# 绘制训练过程当中训练集和测试集合的准确率值
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()

# 绘制训练过程当中训练集和测试集合的损失值
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()

最终在batch_size=1024的状况下(为何不用代码中batch_size=32的那张图呢?由于那张图没有保存,而我实在是不想再训练等那么久了。)

总结

总的来讲效果不是很好,由于我就是用最基本的网络结构,用的图片也没有进行其余处理。不过原本这篇博客就是为了简单的介绍如何使用keras搭建一个cnn网络,效果差一点就差一点吧。若是想获得更好的效果,kaggle欢迎你们。

项目地址:Github

参考

相关文章
相关标签/搜索