對于keras加載訓練數據,,官方上沒有詳說,。然而網上查各種資料,寫法太多,,通過自己跑代碼測試總結以下幾條,,方便自己以后使用。
總的來說keras模型加載數據主要有三種方式:.fit(), .fit_generator()和.train_on_batch(),。
1.fit():
上函數,,各個參數的意義就不解釋了
fit(x=None, y=None, batch_size=None, epochs=1, verbose=1, callbacks=None, validation_split=0.0, validation_data=None, shuffle=True, class_weight=None, sample_weight=None, initial_epoch=0, steps_per_epoch=None, validation_steps=None)
Copy
從官方文檔中可以看出,fit()是需要先把整個數據集加載進來,,然后喂入網絡,,因為minist數據集比較小,這么做是可行的,,但對于實際開發(fā)而言,,這么做是不可行的,需要大量的內存資源,,同時不能對數據進行在線提升,。
一次性加載整個數據集的示例代碼:
任務為貓和狗的二分類,train_data下包含cat和dog兩個文件夾,代碼將兩個文件夾下圖片和標簽存入numpy數組,,返回為訓練數據和訓練標簽,。
seq_names = ['cat','dog'] for seq_name in seq_names: frames = sorted(os.listdir(os.path.join(root_path,'data','train_data', seq_name))) imgs = [os.path.join(root_path, 'data', 'train_data', seq_name, frame)] imgs = np.array(Image.open(imgs[0])) return np.array(tran_imags), np.array(labels) train_data,train_labs = load_data() model.fit(train_data,keras.utils.to_categorical(train_labs),batch_size=32,epochs=50,verbose=1)
Copy
2.fit_generator()
fit_generator()需要將數據集和標簽寫成生成器格式
fit_generator(generator, steps_per_epoch=None, epochs=1, verbose=1, callbacks=None, validation_data=None, validation_steps=None, class_weight=None, max_queue_size=10, workers=1, use_multiprocessing=False, shuffle=True, initial_epoch=0)
Copy
1).從txt文件讀取圖片路徑的生成器,不進行數據增強
以下代碼從給定路徑的txt文本中循環(huán)讀取圖片路徑,,每次讀取一個batch_size的圖片,,并存入numpy數組返回。其中,,當讀到文本末尾時,,將指針指向文件第一行。
def generate_array_from_txt(path, batch_size,num_class): labs = np.zeros(shape=(batch_size,num_class)) while len(imgs) < batch_size: img_path = line.split(' ')[0] img = np.array(Image.open(os.path.join('./',img_path))) lab = keras.utils.to_categorical(int(lab)-1,num_classes=num_class) yield (np.array(imgs),labs) gen = generate_arrays_from_txt(txt_path,batch_size,num_class) model.fit_generator(gen,steps_per_epoch=N, epochs=EPOCN) ## 因為生成器是無限生成數據,,所以它不知道一輪要訓練多少圖片,,所以steps_per_epoch為數據集的總數除以batch_size。
Copy
我的txt文本格式如下:前面是圖片路徑,,后面是類別標簽,,因為從1開始的,所以to_categorical 里面減了1.
2).使用.flow_from_directory(directory)
使用ImageDataGenerator類,,ImageDataGenerator類有.flow()與.flow_from_directory(directory)兩個加載數據的方法,,個人認為第一個偏向于先將數據全部加載(看過的示例代碼都是這樣的),第二個從圖片目錄利用生成器返回數據,。
2.1 用于分類網絡,,返回圖像以及標簽
## 聲明一個ImageDataGenerator類對象,并給出你需要進行的數據增強選項 train_datagen = ImageDataGenerator( ##調用.flow_from_director()方法,,第一個為數據集路徑,。生成數據集及標簽 train_generator = train_datagen.flow_from_directory( class_mode='categorical') model.fit_generator(train_generator,steps_per_epoch=N, epochs=EPOCH)
Copy
我的數據集目錄結構如下:
2.2 用于pix2pix
當用于圖像分割、超分辨率重建等需要像素對應像素的任務時,,標簽也為圖片(單通道或多通道),。 示例:加載用于圖像分割的圖像與mask,mask為單通道灰度圖像,目標為白色,,其余背景為黑色,。
# 分別定義兩個ImageDataGenerator對象 image_datagen = ImageDataGenerator(featurewise_center=True, featurewise_std_normalization=True, mask_datagen = ImageDataGenerator(rescale= 1./255)
image_generator = image_datagen.flow_from_directory( 'data/data_seg/davis_train', mask_generator = mask_datagen.flow_from_directory( 'data/data_seg/davis_label', train_generator = zip(image_generator, mask_generator) steps_per_epoch=STEPS_NUM,
Copy
對于標簽為圖像的數據,當用這種方式加載的時候,,需將class_mode指定為None,表示不返回標簽,。對于訓練圖片和標簽要保證順序不變,一一對應,,名字可不同
需要將兩個生成器的seed指定為相同的數字,,此時兩個生成器返回的圖片對就一一對應
3) 使用flow(x, y=None)
使用.flow()時,需要將訓練數據加載到內存中,,每次填充一個Batch_size的數據進網絡
train_data, train_labs = load_data() dataGenerator = ImageDataGenerator( preprocessing_function=normalize) gen = dataGenerator.flow(train_data, train_labs, batch_size=8)
Copy
4) 使用.flow_from_dataframe()
dataframe中保存的是圖片名字和label
df=pd.read_csv(r".\train.csv") datagen=ImageDataGenerator(rescale=1./255) train_generator=datagen.flow_from_dataframe(dataframe=df, directory=".\train_imgs", x_col="id", y_col="label", class_mode="categorical", target_size=(32,32), batch_size=32)
Copy
3.train_on_batch()
類似于TensorFlow的數據填充了,,一次喂一個batch_size的數據,。
train_on_batch(x, y, sample_weight=None, class_weight=None)
Copy
采用2.2中的生成器例子
train_generator = zip(image_generator, mask_generator) steps = len(train_generator)/ batch_size * EPOCH for train_batch, label_batch in train_generator: train_on_batch(train_batch, label_batch, sample_weight=None, class_weight=None)
Copy
4.對生成器返回數據進行處理
使用生成器時,如果需要對圖片進行一定的處理,,可以在ImageDataGenerator中定義預處理函數,,但是要求返回的shape不能改變。 如果要對圖片的shape進行改變,,可將生成器返回結果再次包裝為生成器,,如下例:
# 實例化ImageDataGenerator,同時指定預處理函數 datagen = ImageDataGenerator( preprocessing_function=normalize)
# 定義生成器,,每次從datagen中取出一個Batch,,然后對數據進行自己的操作 def image_a_b_gen(data_path): for batch in datagen.flow_from_directory(data_path, lab_batch = rgb2lab(batch) X_batch = lab_batch[:, :, :, 0] Y_batch = lab_batch[:, :, :, 1:] / 128 yield (np.expand_dims(X_batch, axis=3), Y_batch)
原帖:http:///post/keras_dataload/
|