keras_GPU實現卷積神經網路CNN貓狗影象分類
一、keras環境配置
二、貓狗影象資料集準備
kaggle官網下載,主要註冊賬號,得科學上網才行:
不能科學上網的同學來百度網盤:
連結:
https://
pan。baidu。com/share/ini
t?surl=3hw4LK8ihR6-6-8mpjLKDA
密碼:dmp4
三、資料集預處理
這個資料集包含25000張貓狗影象(每類有12500 張)。由於我們
機器效能限制性原因
,建立一個新資料集(資料夾),其中包含三個子集:每個類別各1000個樣本的訓練集、每個類別各500個樣本的驗證集和每個類別各500個樣本的測試集。資料集結構為:
dataset
|— train
|— dogs
|— cats
|— validation
|— dogs
|— cats
|— test
|— dogs
|— cats
直接手動將貓狗影象複製貼上到新資料夾下即可,程式碼亦可:
import os
import shutil
original_dataset_dir = r“data\train”
train_cats_dir = r“dataset\train\cats”
validation_cats_dir = r“dataset\validation\cats”
test_cats_dir = r“dataset\test\cats”
train_dogs_dir = r“dataset\train\dogs”
validation_dogs_dir = r“dataset\validation\dogs”
test_dogs_dir = r“dataset\test\dogs”
fnames = [‘cat。{}。jpg’。format(i) for i in range(1000)]
for fname in fnames:
src = os。path。join(original_dataset_dir, fname)
dst = os。path。join(train_cats_dir, fname)
shutil。copyfile(src, dst)
fnames = [‘cat。{}。jpg’。format(i) for i in range(1000, 1500)]
for fname in fnames:
src = os。path。join(original_dataset_dir, fname)
dst = os。path。join(validation_cats_dir, fname)
shutil。copyfile(src, dst)
fnames = [‘cat。{}。jpg’。format(i) for i in range(1500, 2000)]
for fname in fnames:
src = os。path。join(original_dataset_dir, fname)
dst = os。path。join(test_cats_dir, fname)
shutil。copyfile(src, dst)
fnames = [‘dog。{}。jpg’。format(i) for i in range(1000)]
for fname in fnames:
src = os。path。join(original_dataset_dir, fname)
dst = os。path。join(train_dogs_dir, fname)
shutil。copyfile(src, dst)
fnames = [‘dog。{}。jpg’。format(i) for i in range(1000, 1500)]
for fname in fnames:
src = os。path。join(original_dataset_dir, fname)
dst = os。path。join(validation_dogs_dir, fname)
shutil。copyfile(src, dst)
fnames = [‘dog。{}。jpg’。format(i) for i in range(1500, 2000)]
for fname in fnames:
src = os。path。join(original_dataset_dir, fname)
dst = os。path。join(test_dogs_dir, fname)
shutil。copyfile(src, dst)
新的資料集準備好之後,將資料輸入神經網路之前,我們應該
將資料格式化為經過歸一化(神經網路喜歡處理較小的輸入值)、統一尺寸預處理的浮點數張量
。Keras有一個影象處理輔助工具的模組,位於keras。preprocessing。image。其中的ImageDataGenerator 類,可以快速建立Python 生成器,能夠將硬碟上的影象檔案自動轉換為預處理好的張量批次。
from keras。preprocessing。image import ImageDataGenerator
# 將所有影象乘以1/255 縮放
train_datagen = ImageDataGenerator(rescale=1。/255)
validation_datagen = ImageDataGenerator(rescale=1。/255)
train_dir = r“dataset\train”
validation_dir = r“dataset\validation”
train_generator = train_datagen。flow_from_directory(train_dir,
# 將所有影象的大小調整為150×150
target_size=(150, 150),
# 批次大小
batch_size=20,
# 需要用二進位制標籤
class_mode=‘binary’)
validation_generator = validation_datagen。flow_from_directory(validation_dir,
target_size=(150, 150),
batch_size=20,
class_mode=‘binary’)
生成器的輸出:它生成了150×150 的RGB影象[形狀為(20,150, 150, 3)]與二進位制標籤[形狀為(20,)]組成的批次。每個批次中包含20 個樣本(批次大小)。生成器會不停地生成這些批次,它會不斷迴圈目標資料夾中的影象。
學習樣本太少容易導致過擬合
,導致無法訓練出能夠泛化到新資料的模型。如果擁有無限的資料,那麼模型能夠觀察到資料分佈的所有內容,這樣就永遠不會過擬合。
資料增強是從現有的訓練樣本中生成更多的訓練資料
,其方法是利用多種能夠生成可信影象的隨機變換來增加樣本。其目標是,模型在訓練時不會兩次檢視完全相同的影象。這讓模型能夠觀察到資料的更多內容,從而具有更好的泛化能力。在Keras 中,這可以透過對ImageDataGenerator 例項讀取的影象執行多次隨機變換來實現。所以上面的程式碼更改為:
from keras。preprocessing。image import ImageDataGenerator
# 訓練資料增強
train_datagen = ImageDataGenerator(rescale=1。/255,
# 表示影象隨機旋轉的角度範圍
rotation_range=40,
# 影象在水平方向上平移的範圍
width_shift_range=0。2,
# 影象在垂直方向上平移的範圍
height_shift_range=0。2,
# 隨機錯切變換的角度
shear_range=0。2,
# 影象隨機縮放的範圍
zoom_range=0。2,
# 隨機將一半影象水平翻轉
horizontal_flip=True)
# 驗證資料不能增強
validation_datagen = ImageDataGenerator(rescale=1。/255)
train_dir = r“dataset\train”
validation_dir = r“dataset\validation”
train_generator = train_datagen。flow_from_directory(train_dir,
# 將所有影象的大小調整為150×150
target_size=(150, 150),
# 批次大小
batch_size=32,
# 需要用二進位制標籤
class_mode=‘binary’)
validation_generator = validation_datagen。flow_from_directory(validation_dir,
target_size=(150, 150),
batch_size=32,
class_mode=‘binary’)
利用生成器,我們讓模型對資料進行擬合
。我們將使用fit_generator方法來擬合,它在資料生成器上的效果和fit方法相同。
四、定義模型以及模型訓練
定義模型結構,我們採用一個簡單的CNN結構:卷積+池化+卷積+池化+卷積+池化+卷積+池化+Dropout+全連線+全連線:
from keras import models
from keras。layers import Conv2D, MaxPooling2D, Dense, Flatten, Dropout
def model():
model = models。Sequential()
model。add(Conv2D(32, (3, 3), activation=‘relu’, input_shape=(150, 150, 3)))
model。add(MaxPooling2D((2, 2)))
model。add(Conv2D(64, (3, 3), activation=‘relu’))
model。add(MaxPooling2D((2, 2)))
model。add(Conv2D(128, (3, 3), activation=‘relu’))
model。add(MaxPooling2D((2, 2)))
model。add(Conv2D(128, (3, 3), activation=‘relu’))
model。add(MaxPooling2D((2, 2)))
model。add(Flatten())
model。add(Dropout(0。5))
model。add(Dense(512, activation=‘relu’))
model。add(Dense(1, activation=‘sigmoid’))
return model
設定一些模型引數,之後進行模型訓練:
# 初始化模型
model = model()
# 用於配置訓練模型(最佳化器、目標函式、模型評估標準)
model。compile(optimizer = ‘adam’, loss = ‘binary_crossentropy’, metrics=[‘accuracy’])
# 檢視各個層的資訊
model。summary()
# 回撥函式,在每個訓練期之後儲存模型
model_checkpoint = ModelCheckpoint(‘model。hdf5’,#儲存模型的路徑
monitor=‘loss’,#被監測的資料
verbose=1,#日誌顯示模式:0=>安靜模式,1=>進度條,2=>每輪一行
save_best_only=True)#若為True,最佳模型就不會被覆蓋
# 用history接收返回值用於畫loss/acc曲線
history = model。fit_generator(train_generator,
steps_per_epoch=100,
epochs=30,
validation_data=validation_generator,
validation_steps=50)
# 繪製loss,acc
import matplotlib。pyplot as plt
acc = history。history[‘acc’]
val_acc = history。history[‘val_acc’]
loss = history。history[‘loss’]
val_loss = history。history[‘val_loss’]
epochs = range(1, len(acc) + 1)
plt。plot(epochs, acc, ‘r’, label=‘Training acc’)
plt。plot(epochs, val_acc, ‘b’, label=‘Validation acc’)
plt。title(‘Training and validation accuracy’)
plt。legend()
plt。savefig(‘accuracy。png’,dpi=300)
plt。figure()
plt。plot(epochs, loss, ‘r’, label=‘Training loss’)
plt。plot(epochs, val_loss, ‘b’, label=‘Validation loss’)
plt。title(‘Training and validation loss’)
plt。legend()
plt。savefig(‘loss。png’,dpi=300)
plt。show()
10輪過後,訓練集精度acc達到0。8969;驗證集acc: 0。8471。
訓練和驗證資料的loss走向圖
訓練和驗證資料的acc走向圖
五、檢視測試集訓練精度
test_dir = r“dataset\test”
test_datagen = ImageDataGenerator(rescale=1。/255)
test_generator = test_datagen。flow_from_directory(
test_dir,
target_size=(150, 150),
batch_size=20,
class_mode=‘binary’)
test_loss, test_acc = model。evaluate_generator(test_generator, steps=50)
print(‘test acc:’, test_acc)
測試集精度為:0。8370
jupyder檔案:
dogs_and_cats。ipynb
89K
·
百度網盤
參考