Keras的数据生成器
为什么需要数据生成器?
在将数据集提供给机器学习模型时,您可能会遇到内存不足的问题。即使是最先进的配置,有时也可能会耗尽内存来处理整个数据。这就是为什么我们需要找到其他方法来有效地完成这项任务的原因。在这篇文章中,我们将向您展示如何在多个核心上实时生成机器学习数据集,并立即将其提供给您的深度学习模型。
你的keras脚本应该是这样的!
Python示例如下:
import numpy as np from keras.models import Sequential # Load entire dataset X, y = np.load('some_training_set_with_labels.npy') # Design model model = Sequential() [...] # Your architecture model.compile() # Train model on your dataset model.fit(x=X, y=y)
为了提供整个数据集或最大(数据集),让我们一步一步来构建一个适合这种情况的数据生成器。
重要提示
在深入研究之前,首先要了解一些可能有用的重要提示。
设ID为用于标识数据集的给定示例的Python字符串。考虑以下框架以跟踪样本及其标签:
1.创建一个名为partition您收集的字典:
- partition['train'],训练ID列表
- partition['validation'],验证ID列表
2.创建一个字典labels,其中为每个ID数据集指定了相关标签labels[ID]
例如,假设我们的训练集包含id1、id2和id3,它们各自的标签分别为0、1和2,验证集包含id4,标签为1。在这种情况下,变量partition 和labels在Python中看起来像这样
>>> partition
{'train': ['id1', 'id2', 'id3'], 'validation': ['id4']}
>>> labels
{'id1': 0, 'id2': 1, 'id3': 2, 'id4': 1}
为了模块化,我们将在单独的文件中编写Keras代码和定制类。
您在这里看到的Python代码比较通用,因此您也可以在您的项目中使用它!
生成数据
def __init__(self, list_IDs, labels, batch_size=32, dim=(32,32,32), n_channels=1, n_classes=10, shuffle=True): 'Initialization' self.dim = dim self.batch_size = batch_size self.labels = labels self.list_IDs = list_IDs self.n_channels = n_channels self.n_classes = n_classes self.shuffle = shuffle self.on_epoch_end()
这里,该方法on_epoch_end在每个epoch的最开始和结束时被触发一次。如果shuffle参数设置为True,我们将在每次传递时获得新的探索顺序。
def on_epoch_end(self): 'Updates indexes after each epoch' self.indexes = np.arange(len(self.list_IDs)) if self.shuffle == True: np.random.shuffle(self.indexes)
调整示例被输入到分类器中的顺序是有帮助的,这样一来,不同时期之间的批看起来就不一样了。这样做最终会使我们的机器学习模型更加健壮。
生成过程的另一个核心方法是完成最关键工作的方法:生成批量数据。负责此任务的私有方法称为__data_generation,并将目标批处理的id列表作为参数。Python代码如下:
def __data_generation(self, list_IDs_temp): 'Generates data containing batch_size samples' # X : (n_samples, *dim, n_channels) # Initialization X = np.empty((self.batch_size, *self.dim, self.n_channels)) y = np.empty((self.batch_size), dtype=int) # Generate data for i, ID in enumerate(list_IDs_temp): # Store sample X[i] = np.load('data/' + ID + '.npy') # Store class y[i] = self.labels[ID] return X, keras.utils.to_categorical(y, num_classes=self.n_classes)
在数据生成期间,这段代码从相应的文件ID.npy中读取每个示例的NumPy数组。由于我们的代码是多内核友好的,请注意,您可以执行更复杂的操作(例如从源文件计算),而不必担心数据生成成为训练过程中的瓶颈。
现在我们要一起构建所有这些组件。每个调用请求0到总批次数量之间的批索引,后者在__len__方法中指定。
def __len__(self): 'Denotes the number of batches per epoch' return int(np.floor(len(self.list_IDs) / self.batch_size))
通常的做法是将此值设置为
[#camples / batch size]
这样模型每个时期最多可以看到一次训练样本。
现在,当调用与给定索引对应的批处理时,生成器执行该__getitem__方法以生成它。
def __getitem__(self, index): 'Generate one batch of data' # Generate indexes of the batch indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size] # Find list of IDs list_IDs_temp = [self.list_IDs[k] for k in indexes] # Generate data X, y = self.__data_generation(list_IDs_temp) return X, y
现在,我们必须相应地修改我们的Keras脚本,以便它接受我们刚才创建的生成器。Python代码如下:
import numpy as np from keras.models import Sequential from my_classes import DataGenerator # Parameters params = {'dim': (32,32,32), 'batch_size': 64, 'n_classes': 6, 'n_channels': 1, 'shuffle': True} # Datasets partition = # IDs labels = # Labels # Generators training_generator = DataGenerator(partition['train'], labels, **params) validation_generator = DataGenerator(partition['validation'], labels, **params) # Design model model = Sequential() [...] # Architecture model.compile() # Train model on dataset model.fit_generator(generator=training_generator, validation_data=validation_generator, use_multiprocessing=True, workers=6)
正如你所看到的,我们从机器学习模型中调用fit_generator方法,而不是fit,我们只需要将我们的训练生成器作为参数之一。Keras负责其余的事情!
您现在可以运行Keras脚本了。然后您将看到,在训练阶段,数据由CPU并行生成,然后直接馈送到GPU。