【问题标题】:Can't import frozen graph with BatchNorm layer无法使用 BatchNorm 层导入冻结图
【发布时间】:2018-08-15 11:53:52
【问题描述】:

我已经根据repo 训练了一个 Keras 模型。

训练结束后,我将模型保存为检查点文件,如下所示:

 sess=tf.keras.backend.get_session() 
 saver = tf.train.Saver()
 saver.save(sess, current_run_path + '/checkpoint_files/model_{}.ckpt'.format(date))

然后我从检查点文件中恢复图形并使用标准 tf freeze_graph 脚本将其冻结。当我想恢复冻结的图形时,出现以下错误:

Input 0 of node Conv_BN_1/cond/ReadVariableOp/Switch was passed float from Conv_BN_1/gamma:0 incompatible with expected resource

我该如何解决这个问题?

编辑:我的问题与this 问题有关。不幸的是,我无法使用解决方法。

编辑 2: 我在 github 上打开了一个问题并创建了一个要点来重现该错误。 https://github.com/keras-team/keras/issues/11032

【问题讨论】:

    标签: tensorflow keras


    【解决方案1】:

    刚刚解决了同样的问题。我连接了这几个答案:123 并意识到问题源于 batchnorm 层工作状态:训练或学习。因此,为了解决该问题,您只需在加载模型之前放置一行:

    keras.backend.set_learning_phase(0)
    

    完整示例,导出模型

    import tensorflow as tf
    from tensorflow.python.framework import graph_io
    from tensorflow.keras.applications.inception_v3 import InceptionV3
    
    
    def freeze_graph(graph, session, output):
        with graph.as_default():
            graphdef_inf = tf.graph_util.remove_training_nodes(graph.as_graph_def())
            graphdef_frozen = tf.graph_util.convert_variables_to_constants(session, graphdef_inf, output)
            graph_io.write_graph(graphdef_frozen, ".", "frozen_model.pb", as_text=False)
    
    tf.keras.backend.set_learning_phase(0) # this line most important
    
    base_model = InceptionV3()
    
    session = tf.keras.backend.get_session()
    
    INPUT_NODE = base_model.inputs[0].op.name
    OUTPUT_NODE = base_model.outputs[0].op.name
    freeze_graph(session.graph, session, [out.op.name for out in base_model.outputs])
    

    加载 *.pb 模型:

    from PIL import Image
    import numpy as np
    import tensorflow as tf
    
    # https://i.imgur.com/tvOB18o.jpg
    im = Image.open("/home/chichivica/Pictures/eagle.jpg").resize((299, 299), Image.BICUBIC)
    im = np.array(im) / 255.0
    im = im[None, ...]
    
    graph_def = tf.GraphDef()
    
    with tf.gfile.GFile("frozen_model.pb", "rb") as f:
        graph_def.ParseFromString(f.read())
    
    graph = tf.Graph()
    
    with graph.as_default():
        net_inp, net_out = tf.import_graph_def(
            graph_def, return_elements=["input_1", "predictions/Softmax"]
        )
        with tf.Session(graph=graph) as sess:
            out = sess.run(net_out.outputs[0], feed_dict={net_inp.outputs[0]: im})
            print(np.argmax(out))
    

    【讨论】:

    • 非常感谢,在阅读了数十篇文章后唯一对我有用的解决方案。
    • set_learning_phase(0) 的问题在于它将批量规范层置于推理模式,因此如果您进行任何训练,它们将不会正常更新。
    • 在将学习阶段设置为 0 之前不要忘记清除会话:keras.backend.clear_session()
    【解决方案2】:

    这是 Tensorflow 1.1x 的错误,正如另一个答案所述,这是因为内部批量规范学习与推理状态。在 TF 1.14.0 中,您在尝试 freeze a batch norm layer 时实际上会遇到一个神秘错误。

    使用set_learning_phase(0) 会将批范数层(可能还有其他类似 dropout)置于推理模式,因此批范数层在训练期间将不起作用,从而导致准确性降低。

    我的解决办法是这样的:

    1. 使用函数创建模型(不要使用K.set_learning_phase(0)):
    def create_model():
        inputs = Input(...)
        ...
        return model
    
    model = create_model()
    
    1. 火车模型
    2. 保存权重: model.save_weights("weights.h5")
    3. 清除会话(重要的是层名称相同)并将学习阶段设置为 0:
    K.clear_session()
    K.set_learning_phase(0)
    
    1. 重新创建模型并加载权重:
    model = create_model()
    model.load_weights("weights.h5")
    
    1. 像以前一样冻结

    【讨论】:

      【解决方案3】:

      感谢您指出主要问题!我发现keras.backend.set_learning_phase(0) 有时不起作用,至少在我的情况下是这样。

      另一种方法可能是:for l in keras_model.layers: l.trainable = False

      【讨论】:

      • 你能详细说明这个答案吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-09
      • 1970-01-01
      • 1970-01-01
      • 2017-05-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多