如何将多个 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 变量中,分别称为
filenames
和 classes
。我们将使用这些相同的变量来存储时间序列的位置及其 classes.
- 它有一个名为
_get_batches_of_transformed_samples()
的方法,它接受一个 index_array
,加载其索引对应于数组的图像和 returns 一批这些图像和一个包含它们的图像classes.
我建议你做的是:
- 编写一个脚本来构建您的时间序列数据,就像您在使用 ImageDataGenerator 时应该如何构建图像一样。这涉及为每个 class 创建一个 目录,并将 每个时间序列分开 放置在该目录中。虽然这可能需要比您当前选项更多的存储空间,但在训练模型时数据不会加载到内存中。
- 了解 DirectoryIterator 的工作原理。
- 定义您自己的生成器 class(例如
MyTimeseriesGenerator
)。确保它 继承 来自上面提到的 Iterator class。
- 修改它以便搜索您想要的文件格式(例如 HDF5、npy)而不是图像格式(例如png, jpeg) 就像现在一样。这是在 1733-1763 行中完成的。您不需要让它在多个线程上工作,就像 keras 的 DirectoryIterator 所做的那样,因为这个过程只完成一次。
- 更改
_get_batches_of_transformed_samples()
方法,使其读取所需的文件类型,而不是读取图像(第 1774-1788 行)。 删除 DirectoryIterator 具有的任何其他图像相关功能(转换图像、标准化图像、保存图像等)
- 确保上述方法返回的数组与您希望模型接受的数组匹配。我猜数据应该在
(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=..., ...)
我有大约 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 变量中,分别称为
filenames
和classes
。我们将使用这些相同的变量来存储时间序列的位置及其 classes. - 它有一个名为
_get_batches_of_transformed_samples()
的方法,它接受一个index_array
,加载其索引对应于数组的图像和 returns 一批这些图像和一个包含它们的图像classes.
我建议你做的是:
- 编写一个脚本来构建您的时间序列数据,就像您在使用 ImageDataGenerator 时应该如何构建图像一样。这涉及为每个 class 创建一个 目录,并将 每个时间序列分开 放置在该目录中。虽然这可能需要比您当前选项更多的存储空间,但在训练模型时数据不会加载到内存中。
- 了解 DirectoryIterator 的工作原理。
- 定义您自己的生成器 class(例如
MyTimeseriesGenerator
)。确保它 继承 来自上面提到的 Iterator class。 - 修改它以便搜索您想要的文件格式(例如 HDF5、npy)而不是图像格式(例如png, jpeg) 就像现在一样。这是在 1733-1763 行中完成的。您不需要让它在多个线程上工作,就像 keras 的 DirectoryIterator 所做的那样,因为这个过程只完成一次。
- 更改
_get_batches_of_transformed_samples()
方法,使其读取所需的文件类型,而不是读取图像(第 1774-1788 行)。 删除 DirectoryIterator 具有的任何其他图像相关功能(转换图像、标准化图像、保存图像等) - 确保上述方法返回的数组与您希望模型接受的数组匹配。我猜数据应该在
(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=..., ...)