1. 程式人生 > 程式設計 >使用Keras中的ImageDataGenerator進行批次讀圖方式

使用Keras中的ImageDataGenerator進行批次讀圖方式

ImageDataGenerator位於keras.preprocessing.image模組當中,可用於做資料增強,或者僅僅用於一個批次一個批次的讀進圖片資料.一開始以為ImageDataGenerator是用來做資料增強的,但我的目的只是想一個batch一個batch的讀進圖片而已,所以一開始沒用它,後來發現它是有這個功能的,而且使用起來很方便.

ImageDataGenerator類包含了如下引數:(keras中文教程)

ImageDataGenerator(featurewise_center=False,#布林值。將輸入資料的均值設定為 0,逐特徵進行
 samplewise_center=False,#布林值。將每個樣本的均值設定為 0
 featurewise_std_normalization=False,#布林值。將輸入除以資料標準差,逐特徵進行
 samplewise_std_normalization=False,#布林值。將每個輸入除以其標準差
 zca_whitening=False,#是否進行ZAC白化
 zca_epsilon=1e-06,#ZCA 白化的 epsilon 值
 rotation_range=0,#整數。隨機旋轉的度數範圍
 width_shift_range=0.0,height_shift_range=0.0,brightness_range=None,shear_range=0.0,#浮點數。剪下強度(以弧度逆時針方向剪下角度)
 zoom_range=0.0,#浮點數 或 [lower,upper]。隨機縮放範圍。如果是浮點數,[lower,upper] = [1-zoom_range,1+zoom_range]。
 channel_shift_range=0.0,#浮點數。隨機通道轉換的範圍
 fill_mode='nearest',#輸入邊界以外的點的模式填充
 cval=0.0,#當 fill_mode = "constant",邊界點的填充值
 horizontal_flip=False,#隨機水平翻轉
 vertical_flip=False,#隨機垂直翻
 rescale=None,#預設為 None。如果是 None 或 0,不進行縮放,否則將資料乘以所提供的值(在應用任何其他轉換之前)
 preprocessing_function=None,#應用於每個輸入的函式。這個函式會在任何其他改變之前執行。這個函式需要一個引數:一張影象(秩為 3 的 Numpy 張量),並且應該輸出一個同尺寸的 Numpy 張量。
 data_format=None,#影象資料格式,{"channels_first","channels_last"} 之一
 validation_split=0.0,dtype=None) #生成陣列使用的資料型別

雖然包含了很多引數,但實際應用時用到的並不會很多,假設我的目的只是一個batch一個batch的讀進圖片,那麼,我在例項化物件的時候什麼引數都不需要設定,然後再呼叫ImageDataGenerator類的成員函式flow_from_directory()就可以從目錄中讀圖.

我放圖片的目錄如下圖,在train資料夾中包含了兩個子資料夾,然後在兩個子資料夾裡面分別包含了貓和狗的圖片.

使用Keras中的ImageDataGenerator進行批次讀圖方式

先看看flow_from_directory()的引數.需要注意的是,第一個引數directory不是圖片的路徑,而是子資料夾的路徑,還有就是第四個引數classes,它填寫是子資料夾的名稱,比如此處的為['cat','dog'],然後該函式就會自動把兩個子資料夾看成是2個類別,cat資料夾裡面所有圖片的標籤都為0,dog資料夾裡面所有圖片的標籤都為1.而且可以通過設定第5個引數class_mode把標籤設定為ont-hot形式(預設的categorical就是one-hot 形式).可以看出,這個函式有多方便,直接把標籤和原圖對應起來了.

def flow_from_directory(self,directory,#子資料夾所在的目錄
 target_size=(256,256),#輸出的圖片的尺寸
 color_mode='rgb',#單通道還是三通道
 classes=None,#類別,有多少個子資料夾就有多少個類別,填寫的是子資料夾的名稱
 class_mode='categorical',#通常預設,表示標籤採用one-hot形式,batch_size=32,shuffle=True,#是否隨機打亂順序
 seed=None,save_to_dir=None,#把圖片儲存,輸入的是路徑
 save_prefix='',#影象字首名,save_format='png',#影象字尾名
 follow_links=False,subset=None,interpolation='nearest')

接下來看一個例子,部分程式碼.

from tensorflow.keras.preprocessing.image import ImageDataGenerator #我是直接裝tensorflow,然後使用裡面的keras的,#例項化物件datagen
datagen=ImageDataGenerator() 
 
#讀訓練集圖片
train_generator = datagen.flow_from_directory(
 '/home/hky/folder/kaggle/DataGenerator/train',classes=['cat',target_size=(227,227),class_mode='categorical',batch_size=batch_size)
 
#讀驗證集圖片
validation_generator = datagen.flow_from_directory(
 '/home/hky/folder/kaggle/DataGenerator/validation',batch_size=batch_size)
 
'''開始訓練'''
#steps_per_epoch是為了判斷是否完成了一個epoch,這裡我訓練集有20000張圖片,然後batch_size=16,所以是10000/16
#同樣,validation_steps=2496/16是因為我的驗證集有2496張圖片
model.fit_generator(generator=train_generator,steps_per_epoch=20000/16,epochs=10,validation_data=validation_generator,validation_steps=2496/16)

下面是完整程式碼,實現了一個AlexNet模型.

import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.preprocessing import image
from tensorflow.keras.callbacks import EarlyStopping
from tensorflow.keras import optimizers
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import numpy as np
import cv2
import yaml
from tensorflow.keras.models import model_from_yaml
 
batch_size = 16
 
''' 搭建模型'''
l=tf.keras.layers
model=Sequential()
 
#第一層卷積和池化
model.add(l.Conv2D(filters=96,kernel_size=(11,11),strides=(4,4),padding='valid',input_shape=(227,227,3),activation='relu'))
model.add(l.BatchNormalization())
model.add(l.MaxPooling2D(pool_size=(3,strides=(2,2),padding='valid'))
 
#第二層卷積和池化
model.add(l.Conv2D(256,(5,5),(1,1),padding='same',activation='relu'))
model.add(l.BatchNormalization())
model.add(l.MaxPooling2D((3,(2,padding='valid'))
 
#第三層卷積
model.add(l.Conv2D(384,(3,'same',activation='relu'))
 
#第四層卷積
model.add(l.Conv2D(384,activation='relu'))
 
#第五層卷積和池化
model.add(l.Conv2D(256,activation='relu'))
model.add(l.MaxPooling2D((3,'valid'))
 
#全連線層
model.add(l.Flatten())
model.add(l.Dense(4096,activation='relu'))
model.add(l.Dropout(0.5))
 
model.add(l.Dense(4096,activation='relu'))
model.add(l.Dropout(0.5))
 
model.add(l.Dense(1000,activation='relu'))
model.add(l.Dropout(0.5))
 
#輸出層
model.add(l.Dense(2,activation='softmax'))
model.compile(optimizer='sgd',loss='categorical_crossentropy',metrics=['accuracy'])
 
'''匯入圖片資料'''
#利用ImageDataGenerator生成一個batch一個batch的資料
 
datagen=ImageDataGenerator(samplewise_center=True,rescale=1.0/255) #samplewise_center:使輸入資料的每個樣本均值為0,rescale:歸一化
train_generator = datagen.flow_from_directory(
 '/home/hky/folder/kaggle/DataGenerator/train',batch_size=batch_size)
 
validation_generator = datagen.flow_from_directory(
 '/home/hky/folder/kaggle/DataGenerator/validation',batch_size=batch_size)
 
'''開始訓練'''
model.fit_generator(generator=train_generator,validation_steps=2496/16)
 
yaml_string = model.to_yaml() # 儲存模型結構到yaml檔案
open('./model_architecture.yaml','w').write(yaml_string)
model.save_weights('./AlexNet_model.h5') #儲存模型引數
 
'''匯入模型'''
#model = model_from_yaml(open('./model_architecture.yaml').read())
#model.load_weights('./AlexNet_model.h5')
 
'''隨便輸入一張圖片測試一下'''
imgs=[]
img=cv2.imread('/home/hky/folder/kaggle/test/120.jpg')
img=cv2.resize(img,(227,227))
imgs.append(img)
a=np.array(imgs)
 
result=model.predict(a)
idx=np.argmax(result)
 
if idx==0:
 print('the image is cat\n')
else:
 print('the image is dog\n')
 
cv2.imshow("image",img)
cv2.waitKey(0)

以上這篇使用Keras中的ImageDataGenerator進行批次讀圖方式就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。