【问题标题】:how to calculate a Mobilenet FLOPs in Keras如何在 Keras 中计算 Mobilenet FLOPs
【发布时间】:2018-03-28 03:48:18
【问题描述】:

run_meta = tf.RunMetadata()
enter codwith tf.Session(graph=tf.Graph()) as sess:
K.set_session(sess)


with tf.device('/cpu:0'):
    base_model = MobileNet(alpha=1, weights=None, input_tensor=tf.placeholder('float32', shape=(1,224,224,3)))




opts = tf.profiler.ProfileOptionBuilder.float_operation()    
flops = tf.profiler.profile(sess.graph, run_meta=run_meta, cmd='op', options=opts)

opts = tf.profiler.ProfileOptionBuilder.trainable_variables_parameter()    
params = tf.profiler.profile(sess.graph, run_meta=run_meta, cmd='op', options=opts)

print("{:,} --- {:,}".format(flops.total_float_ops, params.total_parameters))

当我运行上面的代码时,我得到了以下结果

1,137,481,704 --- 4,253,864

这与论文中描述的失败不同。

手机网:https://arxiv.org/pdf/1704.04861.pdf

ShuffleNet:https://arxiv.org/pdf/1707.01083.pdf

如何计算论文中描述的精确翻牌?

【问题讨论】:

标签: deep-learning keras flops


【解决方案1】:

tl;dr 实际上你得到了正确的答案!您只是将触发器与乘法累加(来自论文)进行比较,因此需要除以 2。

如果您使用的是 Keras,那么您列出的代码有点过于复杂...

model 成为任何已编译的 Keras 模型。我们可以通过以下代码得出模型的失败。

import tensorflow as tf
import keras.backend as K


def get_flops():
    run_meta = tf.RunMetadata()
    opts = tf.profiler.ProfileOptionBuilder.float_operation()

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

    return flops.total_float_ops  # Prints the "flops" of the model.


# .... Define your model here ....
# You need to have compiled your model before calling this.
print(get_flops())

但是,当我查看自己在计算机上执行的示例(不是 Mobilenet) 时,打印出的 total_float_ops 为 2115,当我得到以下结果时我只是打印了flops 变量:

[...]
Mul                      1.06k float_ops (100.00%, 49.98%)
Add                      1.06k float_ops (50.02%, 49.93%)
Sub                          2 float_ops (0.09%, 0.09%)

很明显,total_float_ops 属性考虑了乘法、加法和减法。

然后我又回顾了 MobileNets 的例子,简单地翻阅了一下论文,我发现 MobileNet 的实现是基于参数数量的默认 Keras 实现:

表中的第一个模型与您拥有的结果 (4,253,864) 匹配,并且多加数大约是您拥有的 flops 结果的一半。因此,您有正确的答案,只是您将翻牌误认为是 Mult-Adds(也就是乘法累加或 MAC)。

如果您想计算 MAC 的数量,只需将上述代码的结果除以 2。


重要提示

如果您尝试运行代码示例,请记住以下几点:

  1. 代码示例是在 2018 年编写的,不适用于 tensorflow 版本 2。有关 tensorflow 版本 2 兼容性的完整示例,请参阅 @driedler 的回答。
  2. 代码示例最初是为了在已编译的模型上运行一次...作为一个更好的示例,以没有副作用的方式使用它(因此可以多次运行)同一型号上的时间),请参阅@ch271828n 的答案。

【讨论】:

  • 为什么需要model 作为get_flops 的参数?
  • 在 Tensorflow 2.1.0 上出现错误:AttributeError: module 'tensorflow' has no attribute 'RunMetadata'
  • MAC 数不等于parameters/2 。在论文中,你可以看到parameters 是 420 万,Mult-Adds 是 5.69 亿。所以这种方法计算 MAC 的数量是错误的。我也不确定是否合适。
  • @gizzmole ...idk,哈哈。也许我最初的推理是调用函数时它必须是编译模型? @QinHeyang 他们完全有可能弃用或删除了该模块。实际上只是浏览文档,它在tf.compat.v1.RunMetadata2.1.0 中。也许在 v2 文档中有更好的选择......如果你找到一些东西我可以编辑我的答案,或者你可以单独回答。 @AwaisHussain 不是 parameters / 2,如果您重新阅读我的回复,您会发现我没有这么说。
【解决方案2】:

这在 TF-2.1 中对我有用:

def get_flops(model_h5_path):
    session = tf.compat.v1.Session()
    graph = tf.compat.v1.get_default_graph()


    with graph.as_default():
        with session.as_default():
            model = tf.keras.models.load_model(model_h5_path)

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

            # Optional: save printed results to file
            # flops_log_path = os.path.join(tempfile.gettempdir(), 'tf_flops_log.txt')
            # opts['output'] = 'file:outfile={}'.format(flops_log_path)

            # 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)

            return flops.total_float_ops

【讨论】:

  • 感谢您的修改,当我在具有大约 18 个卷积层的模型上运行它时,我得到以下 =================Model分析报告====================== 简介:_TFProfRoot 0 float_ops (0.00%, 0.00%) ============== ========报告结束=========================== 好像有些不对劲。我的模型摘要打印总参数:176,240 可训练参数:176,240 不可训练参数:0
  • 我不确定。也许是 TF 1.x 分析器的问题?请注意,据说他们正在开发 TF 2.x 分析器:github.com/tensorflow/tensorflow/issues/32809
  • 我得到了它的工作,问题是我试图在生成和编译后即时传递模型。但是,此代码仅在模型保存到文件然后重新加载时才有效。
  • 您好,看来这个不能运行两次,否则会累积失败...我提供了一点改进,看我的回答:)
【解决方案3】:

上述解决方案不能运行两次,否则失败会累积! (也就是说,第二次运行,你会得到 output = flops_of_1st_call + flops_of_2nd_call。)下面的代码调用reset_default_graph 来避免这种情况。

def get_flops():
    session = tf.compat.v1.Session()
    graph = tf.compat.v1.get_default_graph()

    with graph.as_default():
        with session.as_default():
            model = keras.applications.mobilenet.MobileNet(
                    alpha=1, weights=None, input_tensor=tf.compat.v1.placeholder('float32', shape=(1, 224, 224, 3)))

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

            # Optional: save printed results to file
            # flops_log_path = os.path.join(tempfile.gettempdir(), 'tf_flops_log.txt')
            # opts['output'] = 'file:outfile={}'.format(flops_log_path)

            # 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)

    tf.compat.v1.reset_default_graph()

    return flops.total_float_ops

根据@driedler 修改,谢谢!

【讨论】:

  • 你能添加你得到U.TimingManager的部分吗?
  • @JashShah 这只是计时线路执行的时间。所以我(安全地)删除它。
  • 感谢分享。输入形状和总翻牌数之间是否存在关系?当我改变输入形状时,我得到了同样的结果。
  • @asendjasni 我想应该有。也许问一个单独的问题供您观察?
  • 顺便说一句,你能解释一下这个输出6.95m float_ops (100.00%, 98.81%)的含义吗?谢谢。
【解决方案4】:

您可以在所有 Keras 模型上使用model.summary() 来获取 FLOPS 数。

【讨论】:

  • 这里只列出参数个数
猜你喜欢
  • 2021-07-21
  • 1970-01-01
  • 2017-09-15
  • 2013-09-19
  • 2012-09-21
  • 2014-07-18
  • 2017-09-18
  • 2018-10-07
  • 2019-09-14
相关资源
最近更新 更多