将具有许多二进制数据特征的大量观察结果提供给 TensorFlow

Feeding lots of observations with many binary data features to TensorFlow

我有大约 170 万个观察值。他们每个人都有大约 4000 个布尔特征和 4 个浮点数 labels/targets。这些特征是稀疏的并且近似均匀分布(4000 个布尔值中的大约 150 个被设置为每次观察 True)。

如果我将整个 (1700000, 4000) 矩阵存储为原始 numpy 文件(npz 格式),它需要大约 100 MB 的磁盘 space。如果我通过 np.load() 加载它,需要几分钟时间,我的 RAM 使用量会增加大约 7 GB,这本身就没问题。

问题是,我必须将 feed_dict 中的布尔值转换为 tf.placeholder,以便 tf.data.Dataset 能够使用它。此过程需要另外 7 GB 的 RAM。我的计划是在未来收集更多的数据(在某个时候可能会超过 1000 万个观察值)。

问题:那么如何将数据馈送到我的 DNN(前馈,密集, 卷积和 循环)而不产生瓶颈并且以 TensorFlow 固有的方式?我原以为这是一个非常标准的设置,很多人应该有这个问题——为什么不呢? wrong/different 与没有问题的人相比,我该怎么做?


我听说 tfrecord format is well integrated 使用 TensorFlow 并且能够延迟加载,但我认为将这种格式用于我的特征结构是个坏主意,因为它会为每次观察创建一个 Message 并保存特征为 map,所有特征的键为字符串 per observation.

我找到了一个解决方案,名为 tf.data.Dataset.from_generator

这基本上可以解决问题:

def generate_train_data(self, batch_size: int) -> typing.Iterable[typing.Tuple[np.ndarray, np.ndarray]]:
    row_id = 0
    features = self.get_features()
    targets = self.get_targets()
    test_amount = self.get_test_data_amount()
    while row_id < features.shape[0]:
        limit = min(features.shape[0] - test_amount, row_id + batch_size)
        feature_batch = features[row_id:limit, :]
        target_batch = targets[row_id:limit, :]
        yield (feature_batch, target_batch)
        del feature_batch, target_batch
        row_id += batch_size

并创建 tf.data.Dataset 类似于:

train_data = tf.data.Dataset.from_generator(
    data.generate_train_data,
    output_types=(tf.bool, tf.bool),
    output_shapes=(
        (None, data.get_feature_amount()),
        (None, data.get_target_amount()),
    ),
    args=(batch_size,),
).repeat()

这当然不会打乱数据,但改造起来非常容易……