web-dev-qa-db-ja.com

KerasでMobilenetFLOPを計算する方法

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

これは、このペーパーで説明されているフロップとは異なります。

mobilenet: https://arxiv.org/pdf/1704.04861.pdf

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

論文に記載されている正確なフロップを計算する方法は?

5
Y. Han

tl; drあなたは実際に正しい答えを持っています!フロップと積和(紙から)を比較しているだけなので、2で割る必要があります。

Kerasを使用している場合、リストしたコードは少し複雑すぎます...

modelをコンパイルされたKerasモデルとします。次のコードでモデルのフロップに到達できます。

import tensorflow as tf
import keras.backend as K


def get_flops(model):
    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 ....
print(get_flops(model))

しかし、私が自分のコンピューターで行った自分の例(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の例を振り返り、ペーパーを簡単に見てみると、パラメーターの数に基づいたデフォルトのKeras実装であるMobileNetの実装が見つかりました。

image

表の最初のモデルは、得られた結果(4,253,864)と一致し、Mult-Addsは、得られたflops結果の約半分です。したがって、正しい答えがあります。フロップをMult-Adds(積和またはMAC)と間違えただけです。

MACの数を計算する場合は、上記のコードの結果を2で割るだけです。

11
Malcolm

これは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
1
driedler

上記のソリューションは2回実行できません。そうしないと、フロップは累積! (つまり、2回目に実行すると、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():
            with U.TimingManager('model load'):
                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から変更、ありがとう!

0
ch271828n