數據挖掘入門系列教程(十二)之使用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

參考

相關文章
相關標籤/搜索