【问题标题】:How to manually compute the number of FLOPS in backward pass for a CNN like ResNet?如何手动计算像 ResNet 这样的 CNN 的后向传递中的 FLOPS 数?
【发布时间】:2020-05-05 06:24:24
【问题描述】:

我一直在试图弄清楚如何计算 ResNet 反向传递中的 Flops 数。对于前向传递,这似乎很简单:将卷积过滤器应用于每一层的输入。但是,在反向传递过程中,Flops 如何计算梯度计算和所有权重的更新?

具体来说,

  • 如何在每一层的梯度计算中计算 Flops?

  • 需要计算哪些梯度才能计算每个梯度的 Flops?

  • Pool、BatchNorm 和 Relu 层的梯度计算中有多少次 Flops?

我了解梯度计算的链式规则,但很难确定它如何应用于 ResNet 的卷积层中的权重过滤器以及每个需要多少次 Flops。获取任何有关计算向后传递的总触发器的方法的 cmets 将非常有用。谢谢

【问题讨论】:

标签: deep-learning neural-network conv-neural-network backpropagation deep-residual-networks


【解决方案1】:

您绝对可以手动计算反向传递的乘法和加法的次数,但我想这对于复杂模型来说是一个详尽的过程。

通常,对于 CNN 和其他模型,大多数模型都以 flop 为基准进行前向传递,而不是反向 flop 计数。我想原因与 inference 在应用程序中的不同 CNN 变体和其他深度学习模型方面更为重要有关。

backward pass 只在训练时很重要,对于大多数简单模型,backward 和 forward flop 应该是接近的,有一些常数因素。

因此,我尝试了一种 hacky 方法来计算图中整个 resnet 模型的梯度,以获得前向传递和梯度计算的 flop 计数,然后减去前向 flop。这不是一个精确的测量,可能会错过复杂图形/模型的许多操作。

但这可能会给出大多数模型的失败估计值。

[以下代码 sn-p 适用于 tensorflow 2.0]

import tensorflow as tf

def get_flops():

    for_flop = 0
    total_flop = 0
    session = tf.compat.v1.Session()
    graph = tf.compat.v1.get_default_graph()

    # forward
    with graph.as_default():
        with session.as_default():

            model = tf.keras.applications.ResNet50() # change your model here

            run_meta = tf.compat.v1.RunMetadata()
            opts = tf.compat.v1.profiler.ProfileOptionBuilder.float_operation()

            # We use the Keras session graph in the call to the profiler.
            flops = tf.compat.v1.profiler.profile(graph=graph,
                                                  run_meta=run_meta, cmd='op', options=opts)

            for_flop = flops.total_float_ops
            # print(for_flop)

    # forward + backward
    with graph.as_default():
        with session.as_default():

            model = tf.keras.applications.ResNet50() # change your model here


            outputTensor = model.output 
            listOfVariableTensors = model.trainable_weights
            gradients = tf.gradients(outputTensor, listOfVariableTensors)

            run_meta = tf.compat.v1.RunMetadata()
            opts = tf.compat.v1.profiler.ProfileOptionBuilder.float_operation()

            # We use the Keras session graph in the call to the profiler.
            flops = tf.compat.v1.profiler.profile(graph=graph,
                                                  run_meta=run_meta, cmd='op', options=opts)

            total_flop = flops.total_float_ops
            # print(total_flop)

    return for_flop, total_flop


for_flops, total_flops = get_flops()
print(f'forward: {for_flops}')
print(f'backward: {total_flops - for_flops}')

输出:

51112224
102224449
forward: 51112224
backward: 51112225

【讨论】:

  • 我的问题更多是关于如何手动完成,也就是说,查看层,查看它的过滤器大小并计算它需要反向传播的操​​作数,无需编码。例如。你会如何处理 Resnet-50 的第一个瓶颈块(只有 3 层)?
  • 不认为这适合这个频道。
猜你喜欢
  • 2017-09-15
  • 1970-01-01
  • 2021-07-21
  • 2017-12-30
  • 2017-08-27
  • 1970-01-01
  • 2013-09-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多