【问题标题】:How to determine needed memory of Keras model?如何确定 Keras 模型所需的内存?
【发布时间】:2017-08-25 12:36:17
【问题描述】:

我正在使用 Keras 2.0.0,我想在 GPU 上训练一个具有大量参数的深度模型。 使用太大的图像,我的内存不足 (OOM)。 使用太低的图像,模型的准确性会比可能的差。 因此,我想找到适合我的 GPU 的图像的最大可能输入大小。 在给定模型和输入数据的情况下,是否有任何计算内存的功能(例如,与 model.summary() 相当)?

感谢您的帮助。

【问题讨论】:

  • 您可以查看他们如何计算内存使用量 [这里] (cs231n.github.io/convolutional-networks/#case),您也可以尝试减少批量大小而不是分辨率。
  • 感谢您的回答。实际上,在发布我的问题之前,我正在阅读给定的链接。但我想避免手动计算:D 另外我不想减少批量大小,因为我想在统计意义上很好地表示我的整个数据集。
  • try-fail 将是最快回答您问题的方法。 Keras 不是计算库,它只是您选择的后端的包装器。对于不同的后端,内存管理的处理方式不同。内存消耗不仅取决于参数的数量,即使参数数量很少,LSTM 也会使用大量内存...您应该尝试查看实际的内存消耗:)
  • 我害怕那个。但我会这样做......谢谢! (纳西姆,你喜欢回答我的问题,不是吗?:D)
  • 爱它 :-) 玩得开心

标签: memory keras


【解决方案1】:

我根据 Fabrício Pereira 的回答创建了一个完整的函数。

def get_model_memory_usage(batch_size, model):
    import numpy as np
    try:
        from keras import backend as K
    except:
        from tensorflow.keras import backend as K

    shapes_mem_count = 0
    internal_model_mem_count = 0
    for l in model.layers:
        layer_type = l.__class__.__name__
        if layer_type == 'Model':
            internal_model_mem_count += get_model_memory_usage(batch_size, l)
        single_layer_mem = 1
        out_shape = l.output_shape
        if type(out_shape) is list:
            out_shape = out_shape[0]
        for s in out_shape:
            if s is None:
                continue
            single_layer_mem *= s
        shapes_mem_count += single_layer_mem

    trainable_count = np.sum([K.count_params(p) for p in model.trainable_weights])
    non_trainable_count = np.sum([K.count_params(p) for p in model.non_trainable_weights])

    number_size = 4.0
    if K.floatx() == 'float16':
        number_size = 2.0
    if K.floatx() == 'float64':
        number_size = 8.0

    total_memory = number_size * (batch_size * shapes_mem_count + trainable_count + non_trainable_count)
    gbytes = np.round(total_memory / (1024.0 ** 3), 3) + internal_model_mem_count
    return gbytes

更新 2019.10.06:增加了对包含其他模型作为层的模型的支持。

UPDATE 2020.07.17:函数现在可以在 TensorFlow v2 中正常工作。

【讨论】:

  • 计算是有道理的,但由于某种原因,它输出的内存使用量似乎远远超出了我的 GPU 的使用量,而 Keras 正在愉快地对其进行训练。例如:get_model_memory_usage(batch_size, model) => 28GB,而我的 GTX 1060 有 6GB :)
  • 我想知道它是否与损失函数有关?这可能需要一些内存...
  • 可能 Theano 或 TensorFlow 不会将所有中间形状存储在内存中,除了涉及当前层计算的 2 个形状。因此,要找到形状所需的内存,我们需要获得 2 个最大连续形状体积。
  • 每一层的结果和梯度也需要内存。所以这是不正确的。
  • 不应该是:total_memory = 4.0*( batch_size*shapes_mem_count + trainable_count + non_trainable_count ) 权重在所有批次之间共享。无论批次大小如何,权重都将占用相同数量的内存。不需要将权重乘以批量大小。
【解决方案2】:

希望对你有帮助...

  • 这里是如何确定 Keras 模型的形状数量(var model),每个形状单元在内存中占用 4 个字节:

    shapes_count = int(numpy.sum([numpy.prod(numpy.array([s if isinstance(s, int) else 1 for s in l.output_shape])) for l in model.layers]))

    memory = shapes_count * 4

  • 下面是如何确定您的 Keras 模型 (var model) 的参数数量:

    from keras import backend as K

    trainable_count = int(numpy.sum([K.count_params(p) for p in set(model.trainable_weights)]))

    non_trainable_count = int(numpy.sum([K.count_params(p) for p in set(model.non_trainable_weights)]))

【讨论】:

  • 请添加更多关于您的答案的描述。
  • 如果您使用批量训练,要计算 GPU 所需的内存,您还必须将计算出的内存乘以批量大小。
【解决方案3】:

这是我的@ZFTurbo 答案的变体。它为嵌套的 Keras 模型、不同的 TensorFlow dtype 提供了更好的处理,并消除了对 NumPy 的依赖。我已经在 TensorFlow 2.3.0 上编写并测试了它,它可能不适用于早期版本。

def keras_model_memory_usage_in_bytes(model, *, batch_size: int):
    """
    Return the estimated memory usage of a given Keras model in bytes.
    This includes the model weights and layers, but excludes the dataset.

    The model shapes are multipled by the batch size, but the weights are not.

    Args:
        model: A Keras model.
        batch_size: The batch size you intend to run the model with. If you
            have already specified the batch size in the model itself, then
            pass `1` as the argument here.
    Returns:
        An estimate of the Keras model's memory usage in bytes.

    """
    default_dtype = tf.keras.backend.floatx()
    shapes_mem_count = 0
    internal_model_mem_count = 0
    for layer in model.layers:
        if isinstance(layer, tf.keras.Model):
            internal_model_mem_count += keras_model_memory_usage_in_bytes(
                layer, batch_size=batch_size
            )
        single_layer_mem = tf.as_dtype(layer.dtype or default_dtype).size
        out_shape = layer.output_shape
        if isinstance(out_shape, list):
            out_shape = out_shape[0]
        for s in out_shape:
            if s is None:
                continue
            single_layer_mem *= s
        shapes_mem_count += single_layer_mem

    trainable_count = sum(
        [tf.keras.backend.count_params(p) for p in model.trainable_weights]
    )
    non_trainable_count = sum(
        [tf.keras.backend.count_params(p) for p in model.non_trainable_weights]
    )

    total_memory = (
        batch_size * shapes_mem_count
        + internal_model_mem_count
        + trainable_count
        + non_trainable_count
    )
    return total_memory

【讨论】:

  • 我有一个关于internal_model_mem_count的问题,它似乎总是0?但是,这是什么意思?为什么要计算这个?谢谢
  • @Jing,可以将 Keras 模型用作更大模型中的单独层。为了解决这个问题,keras_model_memory_usage_in_bytes() 递归调用自身来测量内存使用情况,并在 internal_model_mem_count 变量中跟踪嵌套模型的内存使用情况。
【解决方案4】:

我相信,如果您使用自定义编写的数据生成器或利用 keras 中的一些现有生成器,它将解决您的问题。 内存错误通常发生在所有加载的数据对系统造成过度负荷时,而不是使用生成器将数据集分解为段,这样您就不会耗尽内存并且可以在任何系统上进行训练。

【讨论】:

  • 这种态度是不正确的。虽然数据生成器或小批量可以帮助减少内存使用量,但研究级模型消耗的内存比消费级 GPU 所能提供的更多的内存已经很常见。
猜你喜欢
  • 2015-04-21
  • 2020-06-20
  • 2019-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-15
  • 2021-05-05
  • 2020-09-26
相关资源
最近更新 更多