15

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

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

4

4 回答 4

17

tl;博士您实际上得到了正确的答案!您只是将翻牌与乘法累加(来自论文)进行比较,因此需要除以 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),而 Mult-Adds 大约flops是您的结果的一半。因此,您有正确的答案,只是您将翻牌误认为是 Mult-Adds(也就是乘法累加或 MAC)。

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


重要笔记

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

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

这在 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
于 2020-01-22T15:17:50.230 回答
5

以上解决方案不能运行两次,否则会累积失败!(换句话说,你第二次运行它,你会得到 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

由@dryedler 修改,谢谢!

于 2020-04-06T13:02:21.543 回答
-11

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

于 2018-06-11T10:38:21.687 回答