【问题标题】:Extracting feature vector from Images Tensorflow OOM从图像 Tensorflow OOM 中提取特征向量
【发布时间】:2016-09-05 10:12:09
【问题描述】:

我使用从 Caffe zoo 下载的预训练网络权重在 tensorflow 中构建特征提取器 (VGG-16)。

因此,我使用导入的权重作为常量重新定义了 TF 中的网络架构,并添加了一个额外的带有 tf.Variables 的全连接层,以通过 SGD 在铰链损失成本上训练线性 SVM。

我的初始训练集由 100000 个 32x32x3 图像组成,以 numpy 数组的形式。 因此,我不得不将它们调整为 224x224x3,这是 VGG 的输入大小,但不适合内存。

所以我删除了不必要的示例并将其缩小到 10000x224x224x3 图像,这很糟糕但仍然可以接受,因为只有支持向量很重要,但即便如此我仍然在训练时使用 TF 得到 OOM。

这不应该是这种情况,因为唯一重要的表示是来自倒数第二层的大小为 4096 的表示,它很容易管理,并且反向传播的权重只有大小 (4096+1bias)。

所以我能做的就是首先将我所有的图像转换为只有常数的 TF 网络的特征,形成一个 10000x4096 的数据集,然后训练第二个 tensorflow 模型。 或者在每个批次重新计算批次的所有特征。在 next_batch 方法中。或者使用 TF 提供的大量缓冲区/队列运行器,但这有点吓人,因为我不太熟悉这些。

我不喜欢那些我认为应该有更优雅的方法(如果可能的话不要太多队列)。

处理这个问题的最符合 TensorFlow 的方法是什么?

【问题讨论】:

  • 您的图像非常小,将它们放大这么多没有多大意义,在它们上训练网络可能会更好(甚至是自动编码器)。
  • @Matias Valdenegro 你说得有道理。不幸的是,我试图从头开始训练一个网络(实际上是几个网络),但由于各种原因,它被证明不如我预期的那么有效。这就是我想尝试迁移学习的原因。
  • 您需要从使用类似大小图像的网络进行迁移学习。 32x32 彩色图像应该不难训练到可接受的精度(例如 70-80% 或更高),特别是对于您拥有的数据量。在 CIFAR-10/100 数据集上训练的网络可以工作得更好。
  • 即使调整大小看起来有点牵强,我实际上仍然希望 Imagenet 训练的网络能够更好地工作(也许我会弄错?)但当然你也是对的,我也会尝试使用 CIFAR。但是,这并不能回答我的问题。
  • 你是对的,解决方案只是一次加载一批图像(32个左右),但我不知道具体如何在TensorFlow中做到这一点。

标签: out-of-memory tensorflow deep-learning


【解决方案1】:

我想一种使用一些队列和线程但不会太多的方法是使用tf.python_io.TFRecordWriter 将训练集保存为 tensorflow protobuf 格式(或多种格式)。

然后创建一个从 protobuf 读取和解码单个示例的方法,最后使用tf.train.shuffle_batch 使用前一种方法将 BATCH_SIZE 示例提供给优化器。

这样在内存中同时只有一个最大容量(在 shuffle_batch 中定义)张量。

awesome tutorial from Indico 解释了一切。

【讨论】:

    【解决方案2】:

    如果我正确理解您的问题,100K 图像根本不适合内存,而 10K 图像确实适合内存,但是网络本身 OOM。这听起来很合理,因为仅 10K 图像,假设它们使用每个通道每个像素 4 个字节来表示,占用 5.6GiB 的空间(或者如果您以某种方式每个通道每个像素只花费 1 个字节,则为 1.4GiB),所以即使数据集发生为了适应内存,当您添加模型时,这将占用更多 GiB,您将 OOM。

    现在,有几种方法可以解决它:

    1. 您应该使用小批量进行训练(如果您还没有)。如果使用大小为 512 的小批量,您将显着减少向 GPU 加载的数据。使用小批量,您也不需要在开始时将整个数据集加载到 numpy 数组中。以一次加载 512 个图像、向前和向后运行 (sess.run(train...))、加载下一个 512 个图像等的方式构建您的迭代器。这样,您在任何时候都不需要同时在内存中拥有 10K 或 100K 图像。

    2. 当您的原始图像小得多时,高档图像似乎也非常浪费。您可能会考虑做的是从 VGG 网络中获取卷积层(卷积层的尺寸不依赖于原始图像的尺寸),并从头开始在它们之上训练完全连接的层。为此,只需在展平层之后修剪 VGG 网络,为您拥有的所有图像运行它并为每个图像生成展平层的输出,然后在这些特征上训练一个三层全连接网络(这将相对较快与训练整个 conv 网络相比),并在原始 VGG 网络的 flatten 层之后插入生成的网络。这也可能会产生更好的结果,因为卷积层经过训练可以在原始大小的图像中找到特征,而不是模糊的放大图像。

    【讨论】:

    • 很好的答案谢谢我认为最重要的部分是如果你批量训练你实际上不需要将整个数组加载到内存中,解决方案确实是将一定数量的图像加入队列(远小于整个数据集但大于 batch_size) 并在每一步将它们的 batch_size 出列以训练您的网络。它是迭代器所做的吗?除了将整个数据集加载到内存中并对其进行迭代之外,我做了您在 1 中描述的操作。
    • 我还在考虑你回答的第二部分,我会尽快回复你。然而,这两个答案在某种程度上都不令人满意,因为我想做的与您在 2 中描述的相似。通过将网络的权重设置为 tensorflow 中的常数,您只能训练相对较少的神经元。但这仍然不适合记忆,请尝试使用 1 和 2。
    • 我将研究你提到的迭代器。
    • 根据python迭代器上的FAQ,您确实需要先加载完整的对象吗?
    猜你喜欢
    • 2013-05-11
    • 2018-08-17
    • 2018-12-23
    • 1970-01-01
    • 2020-11-13
    • 2020-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多