【问题标题】:Inference using saved model in Tensorflow 2: how to control in/output?在 Tensorflow 2 中使用保存的模型进行推理:如何控制输入/输出?
【发布时间】:2022-01-11 01:04:50
【问题描述】:

将我的代码从 TF1 调整到 TF2.6 我遇到了麻烦。 我正在尝试向 inception resnet 添加一些自定义层,保存模型,然后加载并运行它。

from tensorflow.keras.layers import Dense                                                                                                                       
from tensorflow.keras.models import Model                                                                                                                       
from tensorflow.keras.applications.inception_resnet_v2 import InceptionResNetV2                                                                                 
from tensorflow.keras.layers import Dense, GlobalAveragePooling2D                                                                                               
import tensorflow as tf                                                                                                                                         
import numpy as np                                                                                                                                              
from PIL import Image                                                                                                                                           
                                                                                                                                                                
export_path = "./save_test"                                                                                                                                     
                                                                                                                                                                
# Get model without top and add two layers                                                                                                                      
base_model = InceptionResNetV2(weights='imagenet', input_tensor=None, include_top=False)                                                                        
out = base_model.output                                                                                                                                         
out = GlobalAveragePooling2D()(out)                                                                                                                             
predictions = Dense(7, activation='softmax', name="output")(out)                                                                                                
                                                                                                                                                                
# Make new model using inputs from base model and custom outputs                                                                                                
model = Model(inputs=base_model.input, outputs=[predictions])                                                                                                   
                                                                                                                                                                
# save model                                                                                                                                                    
tf.saved_model.save(model, export_path)                                                                                                                         
                                                                                                                                                                
# load model and run                                                                                                                                            
with tf.compat.v1.Session(graph=tf.Graph()) as sess:                                                                                                            
    tf.compat.v1.saved_model.loader.load(sess, ['serve'], export_path)                                                                                          
    graph = tf.compat.v1.get_default_graph()                                                                                                                    
                                                                                                                                                                
    img = Image.new('RGB', (299, 299))                                                                                                                          
    x = tf.keras.preprocessing.image.img_to_array(img)                                                                                                          
    x = np.expand_dims(x, axis=0)                                                                                                                               
    x = x[..., :3]                                                                                                                                              
    x /= 255.0                                                                                                                                                  
    x = (x - 0.5) * 2.0                                                                                                                                         
                                                                                                                                                                
    y_pred = sess.run('output/Softmax:0', feed_dict={'serving_default_input_1:0': x})                                                                           

错误: KeyError: "The name 'output/Softmax:0' refers to a Tensor which does not exist. The operation, 'output/Softmax', does not exist in the graph."

我不明白的: predictions.name'output/Softmax:0',但是 graph.get_tensor_by_name('output/Softmax:0') 告诉我它不存在!

注意:我知道我可以使用 TF2 的 tf.keras.models.savetf.keras.models.load_model 保存和加载,然后使用 model(x) 运行模型。但是,在我的应用程序中,我在内存中有多个模型,并且我发现推理时间比使用 session 对象的 TF1 代码要长得多。因此,我想在兼容模式下将 TF1 方法与 session 对象一起使用。

保存时如何控制输入/输出的名称?我错过了什么?

【问题讨论】:

    标签: python tensorflow machine-learning keras tensorflow2.0


    【解决方案1】:

    在 TF 2.0、2.6 和 2.7 上测试

    如果您还没有,您可以尝试以下方法,因为我相信您在 SignatureDef 中引用了错误的键:

    from tensorflow.keras.layers import Dense                                                                                                                       
    from tensorflow.keras.models import Model                                                                                                                       
    from tensorflow.keras.applications.inception_resnet_v2 import InceptionResNetV2                                                                                 
    from tensorflow.keras.layers import Dense, GlobalAveragePooling2D                                                                                               
    import tensorflow as tf                                                                                                                                         
    import numpy as np                                                                                                                                              
    from PIL import Image                                                                                                                                           
                                                                                                                                                                    
    export_path = "./save_test"                                                                                                                                     
                                                                                                                                                                    
    base_model = InceptionResNetV2(weights='imagenet', input_tensor=None, include_top=False)                                                                        
    out = base_model.output                                                                                                                                         
    out = GlobalAveragePooling2D()(out)                                                                                                                             
    predictions = Dense(7, activation='softmax', name="output")(out)                                                                                                
    model = Model(inputs=base_model.input, outputs=[predictions])                                                                                                   
                                                                                                                                                                  
    tf.saved_model.save(model, export_path)
    
    with tf.compat.v1.Session(graph=tf.Graph()) as sess:                                                                                                            
        meta_graph = tf.compat.v1.saved_model.loader.load(sess, ["serve"], export_path)
        sig_def = meta_graph.signature_def[tf.saved_model.DEFAULT_SERVING_SIGNATURE_DEF_KEY]
        input_key = list(dict(sig_def.inputs).keys())[0]
        input_name = sig_def.inputs[input_key].name
        output_name = sig_def.outputs['output'].name
        img = Image.new('RGB', (299, 299))                                                                                                                          
        x = tf.keras.preprocessing.image.img_to_array(img)                                                                                                          
        x = np.expand_dims(x, axis=0)                                                                                                                               
        x = x[..., :3]                                                                                                                                              
        x /= 255.0                                                                                                                                                  
        x = (x - 0.5) * 2.0   
        y_pred = sess.run(output_name, feed_dict={input_name: x})        
        print(y_pred)  
    
    INFO:tensorflow:Restoring parameters from ./save_test/variables/variables
    [[0.14001141 0.13356228 0.14509581 0.22432518 0.16313255 0.11899492
      0.07487784]]
    

    您还可以查看SignatureDef 以获取输入和输出信息:

    print(meta_graph.signature_def)
    {'serving_default': inputs {
      key: "input_2"
      value {
        name: "serving_default_input_2:0"
        dtype: DT_FLOAT
        tensor_shape {
          dim {
            size: -1
          }
          dim {
            size: -1
          }
          dim {
            size: -1
          }
          dim {
            size: 3
          }
        }
      }
    }
    outputs {
      key: "output"
      value {
        name: "StatefulPartitionedCall:0"
        dtype: DT_FLOAT
        tensor_shape {
          dim {
            size: -1
          }
          dim {
            size: 7
          }
        }
      }
    }
    method_name: "tensorflow/serving/predict"
    , '__saved_model_init_op': outputs {
      key: "__saved_model_init_op"
      value {
        name: "NoOp"
        tensor_shape {
          unknown_rank: true
        }
      }
    }
    }
    

    如果删除base_model 的第一层并添加新的Input 层,则可以使用静态键名sig_def.inputs['input'].namesig_def.outputs['output'].name

    from tensorflow.keras.layers import Dense                                                                                                                       
    from tensorflow.keras.models import Model                                                                                                                       
    from tensorflow.keras.applications.inception_resnet_v2 import InceptionResNetV2                                                                                 
    from tensorflow.keras.layers import Dense, GlobalAveragePooling2D                                                                                               
    import tensorflow as tf                                                                                                                                         
    import numpy as np                                                                                                                                              
    from PIL import Image                                                                                                                                           
                                                                                                                                                                    
    export_path = "./save_test"                                                                                                                                     
                                                                                                                                                                    
    base_model = InceptionResNetV2(weights='imagenet', input_tensor=None, include_top=False)
    base_model.layers.pop(0)
    new_input = tf.keras.layers.Input(shape=(299,299,3), name='input')
    out = base_model(new_input)                                                                                                                                        
    out = GlobalAveragePooling2D()(out)                                                                                                                             
    predictions = Dense(7, activation='softmax', name="output")(out) 
    
    model = Model(inputs=new_input, outputs=[predictions])                                                                                                   
    tf.saved_model.save(model, export_path)
    
    with tf.compat.v1.Session(graph=tf.Graph()) as sess:                                                                                                            
        meta_graph = tf.compat.v1.saved_model.loader.load(sess, ["serve"], export_path)
        sig_def = meta_graph.signature_def[tf.saved_model.DEFAULT_SERVING_SIGNATURE_DEF_KEY]
        input_name = sig_def.inputs['input'].name
        output_name = sig_def.outputs['output'].name
        img = Image.new('RGB', (299, 299))                                                                                                                          
        x = tf.keras.preprocessing.image.img_to_array(img)                                                                                                          
        x = np.expand_dims(x, axis=0)                                                                                                                               
        x = x[..., :3]                                                                                                                                              
        x /= 255.0                                                                                                                                                  
        x = (x - 0.5) * 2.0   
        y_pred = sess.run(output_name, feed_dict={input_name: x})        
        print(y_pred)   
    
    INFO:tensorflow:Restoring parameters from ./save_test/variables/variables
    [[0.21079363 0.10773096 0.07287834 0.06983061 0.10538215 0.09172108
      0.34166315]]
    

    请注意,更改base_model 第一层的名称不适用于语法model.layers[0]._name = 'input',因为模型配置本身不会更新。

    【讨论】:

    • 不错! sig_def 好像是我要找的那个!!
    • 您是否知道我是否可以通过这种方式将多个模型加载到一个会话中?例如,当使用tf.compat.v1.import_graph_def(meta_graph.graph_def, name="model1") 执行此操作然后加载另一个模型时,看起来事情变得混乱了......
    • 从未尝试过,但我想您需要两个会话。 stackoverflow.com/questions/41607144/…
    猜你喜欢
    • 2020-03-04
    • 1970-01-01
    • 2020-10-08
    • 1970-01-01
    • 2018-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    相关资源
    最近更新 更多