如何将多个 NumPy 数组提供给 Keras 中的深度学习网络?

How to feed multiple NumPy arrays to a deep learning network in Keras?

我有大约 13 个 NumPy 数组存储为文件,在磁盘上占用大约 24 GB 的空间。每个文件都针对一个主题,由两个数组组成:一个包含输入数据(二维矩阵列表,行表示连续时间),另一个包含数据标签。

我的最终目标是将所有数据提供给我用 Keras 编写的深度学习网络以对新数据进行分类。但我不知道如何在内存不足的情况下 运行。

我读过 Keras 的数据生成器,但找不到适合我的情况的方法。

我也查阅了 HDF5 和 h5py,但我不知道如何将所有数据添加到单个数组(HDF5 中的数据集)而不 运行 内存不足。

你需要做的是实现一个生成器,将数据一点一点地提供给你的模型。 Keras,确实有一个 TimeseriesGenerator, but I don't think you can use it as it requires you to first load the whole dataset in memory. Thankfully, keras has a generator for images (called ImageDataGenerator),我们将使用它来作为我们自定义生成器的基础。

先说两句关于它是如何工作的。你有两个主要的 classes ImageDataGenerator class (主要处理您要对每张图像执行的任何预处理)和 DirectoryIterator class,它实际上完成了所有工作。后者是我们将修改以获得我们想要的东西。它本质上做的是:

  • 继承自 keras.preprocessing.image.Iterator,它实现了许多方法,这些方法初始化并生成一个名为 index_array 的数组,其中包含每个批次中使用的图像的索引。这个数组在每次迭代中都会改变,而它从中提取的数据在每个时期都会被打乱。我们将在此基础上构建生成器,以保持其功能。
  • 搜索目录下的所有图片;标签是从目录结构中推导出来的。它将每个图像的路径及其标签存储在两个 class 变量中,分别称为 filenamesclasses。我们将使用这些相同的变量来存储时间序列的位置及其 classes.
  • 它有一个名为 _get_batches_of_transformed_samples() 的方法,它接受一个 index_array,加载其索引对应于数组的图像和 returns 一批这些图像和一个包含它们的图像classes.

我建议你做的是:

  1. 编写一个脚本来构建您的时间序列数据,就像您在使用 ImageDataGenerator 时应该如何构建图像一样。这涉及为每个 class 创建一个 目录,并将 每个时间序列分开 放置在该目录中。虽然这可能需要比您当前选项更多的存储空间,但在训练模型时数据不会加载到内存中。
  2. 了解 DirectoryIterator 的工作原理。
  3. 定义您自己的生成器 class(例如 MyTimeseriesGenerator)。确保它 继承 来自上面提到的 Iterator class。
  4. 修改它以便搜索您想要的文件格式(例如 HDF5npy)而不是图像格式(例如png, jpeg) 就像现在一样。这是在 1733-1763 行中完成的。您不需要让它在多个线程上工作,就像 keras 的 DirectoryIterator 所做的那样,因为这个过程只完成一次
  5. 更改 _get_batches_of_transformed_samples() 方法,使其读取所需的文件类型,而不是读取图像(第 1774-1788 行)。 删除 DirectoryIterator 具有的任何其他图像相关功能(转换图像、标准化图像、保存图像等)
  6. 确保上述方法返回的数组与您希望模型接受的数组匹配。我猜数据应该在 (batch_size, n_timesteps)(batch_size, n_timesteps, n_feature) 行,标签应该在 (batch_size, n_classes) 行。

这就是全部!听起来比实际更难。一旦您熟悉了 DirectoryIterator class,其他一切都是微不足道的。

预期用途(修改代码后):

from custom_generator import MyTimeseriesGenerator  # assuming you named your class 
                                                    # MyTimeseriesGenerator and you
                                                    # wrote it in a python file 
                                                    # named custom_generator

train_dir = 'path/to/your/properly/structured/train/directory'
valid_dir = 'path/to/your/properly/structured/validation/directory'

train_gen = MyTimeseriesGenerator(train_dir, batch_size=..., ...)
valid_gen = MyTimeseriesGenerator(valid_dir, batch_size=..., ...)

# instantiate and compile model, define hyper-parameters, callbacks, etc.

model.fit_generator(train_gen, validation_data=valid_gen, epochs=..., ...)