最近做Kaggle的圖像分類比賽:RSNA Intracranial Hemorrhage Detection (https://www.kaggle.com/c/rsna-intracranial-hemorrhage-detection/overview)以及閱讀Yolov3
源碼的時候接觸到深度學習訓練時一個有趣的技巧,那就是構造生成器generator 並且用Keras 的fit_generator來批量生成數據,釋放內存,該方法適合於大規模數據集的訓練。一個DataGenerator是keras的Sequence類的繼承類,一般要包含__len__,__getitem__, on_epoch_end等方法,例如下面的批量圖片數據生成器:
class DataGenerator(keras.utils.Sequence): def __init__(self, list_IDs, labels, batch_size=1, img_size=(512, 512), img_dir, *args, **kwargs): """ self.list_IDs:存放所有需要訓練的圖片文件名的列表。 self.labels:記錄圖片標注的分類信息的pandas.DataFrame數據類型,已經預先給定。 self.batch_size:每次批量生成,訓練的樣本大小。 self.img_size:訓練的圖片尺寸。 self.img_dir:圖片在電腦中存放的路徑。 """ self.list_IDs = list_IDs self.labels = labels self.batch_size = batch_size self.img_size = img_size self.img_dir = img_dir self.on_epoch_end() def __len__(self): """ 返回生成器的長度,也就是總共分批生成數據的次數。 """ return int(ceil(len(self.list_IDs) / self.batch_size)) def __getitem__(self, index): """ 該函數返回每次我們需要的經過處理的數據。 """ indices = self.indices[index*self.batch_size:(index+1)*self.batch_size] list_IDs_temp = [self.list_IDs[k] for k in indices] X, Y = self.__data_generation(list_IDs_temp) return X, Y def on_epoch_end(self): """ 該函數將在訓練時每一個epoch結束的時候自動執行,在這里是隨機打亂索引次序以方便下一batch運行。 """ self.indices = np.arange(len(self.list_IDs)) np.random.shuffle(self.indices) def __data_generation(self, list_IDs_temp): """ 給定文件名,生成數據。 """ X = np.empty((self.batch_size, *self.img_size, 1)) Y = np.empty((self.batch_size, 6), dtype=np.float32) for i, ID in enumerate(list_IDs_temp): X[i,] = mpimg.imread(self.img_dir+ID+".png") Y[i,] = self.labels.loc[ID].values return X, Y
有了這個生成器,我們就可以用fit_generator 方法進行訓練,格式套路如下:
model.fit_generator(generator,
steps_per_epoch=...,
epochs=...,
verbose=...,
callbacks=...,
validation_data=...,
validation_steps=...,
validation_freq=...,
class_weight=None=...,
max_queue_size=...
workers=...,
use_multiprocessing=...,
)
除此以外我們還可以搞批量預測:
model.predict_generator()