facenet: Error loading a frozen graph ( float incompatible with float_ref )

I froze the 20170131-234652 model using the freeze_graph.py, but I cannot load it in C++.

I first read the binaryproto successfully as:

tensorflow::GraphDef graph_def;
Status load_graph_status =  ReadBinaryProto(tensorflow::Env::Default(), graph_file_name, &graph_def);

But, it gives an error while creating the graph to be used for the session:

std::unique_ptr<tensorflow::Session> session(tensorflow::NewSession(tensorflow::SessionOptions()));
tensorflow::Status sessionCreateStatus = session->Create(graphDef);

The error is:

Invalid argument: Input 0 of node InceptionResnetV1/Block8/Branch_1/Conv2d_0c_3x1/BatchNorm/cond/AssignMovingAvg_1/Switch was passed float from InceptionResnetV1/Block8/Branch_1/Conv2d_0c_3x1/BatchNorm/moving_variance:0 incompatible with expected float_ref.

Any ideas how to solve this problem?

Thanks in advance 😃

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 26 (8 by maintainers)

Commits related to this issue

Most upvoted comments

my code

        saver = tf.train.import_meta_graph(os.path.join(os.path.expanduser(args.model_dir), 
            'model-' + os.path.basename(os.path.normpath(args.model_dir)) + '.meta'), clear_devices=True)
        tf.get_default_session().run(tf.global_variables_initializer())
        tf.get_default_session().run(tf.local_variables_initializer())
        saver.restore(sess, tf.train.latest_checkpoint(os.path.expanduser(args.model_dir)))
        
        output_node_names = 'embeddings'
        
        # for fixing the bug of batch norm
        gd = sess.graph.as_graph_def()
        for node in gd.node:            
            if node.op == 'RefSwitch':
                node.op = 'Switch'
                for index in xrange(len(node.input)):
                    if 'moving_' in node.input[index]:
                        node.input[index] = node.input[index] + '/read'
            elif node.op == 'AssignSub':
                node.op = 'Sub'
                if 'use_locking' in node.attr: del node.attr['use_locking']
            elif node.op == 'AssignAdd':
                node.op = 'Add'
                if 'use_locking' in node.attr: del node.attr['use_locking']
        
        converted_graph_def = graph_util.convert_variables_to_constants(sess, gd, output_node_names.split(","))
        tf.train.write_graph(converted_graph_def, args.output_dir, args.output_filename, as_text=False)

BTW, this error also happens when I load the .pb model in Python:

ValueError: graph_def is invalid at node 'InceptionResnetV1/Conv2d_1a_3x3/BatchNorm/cond/AssignMovingAvg/Switch': Input tensor 'InceptionResnetV1/Conv2d_1a_3x3/BatchNorm/moving_mean:0' Cannot convert a tensor of type float32 to an input of type float32_ref.

@tengshaofeng: I just submitted a pull request with the updated freeze_graph.py. This is how I call the function:

python freeze_graph.py ~/models/facenet/20170131-234652 ~/models/facenet/20170131-234652/facenet.pb

For loading the protobuf graph in Python, you can use:

def load_graph(frozen_graph_filename):
    with tf.gfile.GFile(frozen_graph_filename, "rb") as f:
        graph_def = tf.GraphDef()
        graph_def.ParseFromString(f.read())

    with tf.Graph().as_default() as graph:
        tf.import_graph_def(
            graph_def, 
            input_map=None, 
            return_elements=None, 
            op_dict=None, 
            producer_op_list=None
        )
        
    return graph


graph = load_graph('./facenet/facenet.pb')

For loading it in C++, you can use:

tensorflow::GraphDef graphDef;
tensorflow::ReadBinaryProto(tensorflow::Env::Default(), "facenet.pb", &graphDef);

std::unique_ptr<tensorflow::Session> session = tensorflow::NewSession(tensorflow::SessionOptions());
tensorflow::Status sessionCreateStatus = session->Create(graphDef);

@tengshaofeng A great tutorial is here.