Keras的数据生成器

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。

相关推荐