1

I'm (unsuccessfully) trying to compile a model with the Aiy Vision Kit Compiler so that I can use it on a Google Vision Kit, but I always get an error regarding the frozen graph. I'm using Keras with Tensorflow 1.15.

I froze and saved my graph in a .pb file as requested for the compiler. At first I was using Tensorflow 2 (as reported in this other question I asked Tensorflow 2.1/Keras - "output_node is not in graph" error when trying to freeze graph , where there's also the code I use for freezing), but the compiler kept giving me a "output_node/Softmax is not in the graph" error, so I switched to TensorFlow 1.15, and now the error is the following:

2020-01-30 07:48:20.826925: F convert_tensorflow_graph.cc:83] Check failed: graph_def.ParseFromString(frozen_graph_contents) Could not parse GraphDef in "./frozen_graph.pb"

after I run the following commands:

    --frozen_graph_path=./frozen_graph.pb \
    --output_graph_path=./frozen_graph.binaryproto \
    --input_tensor_name=input_node \
    --output_tensor_names=output_node/Softmax\
    --input_tensor_size=256 \
    --debug

From what I can see of the frozen graph in the .pbtxt file, it looks like the model I created with Keras and the input and output names are right, so I'm not sure what's the mistake I'm making.

I'm running the compiler on a Linux virtual machine as recommended. Pre-trained models downloded from the Aiy Vision Kit site are successfully compiled, so I'm guessing the issue is with my .pb file and not with the environment.

This is the code I used to create and train the model:

    input_layer=layers.Input(shape = (16,16,1), name = "input_node")
    conv1=layers.Conv2D(64, kernel_size=(3, 3), activation='relu')(input_layer) 
    pool1=layers.MaxPooling2D((2, 2))(conv1) 
    conv2=(layers.Conv2D(128, kernel_size=(3, 3), activation='relu'))(pool1) 
    pool2=(layers.MaxPooling2D((2, 2), strides=1))(conv2)
    conv3=(layers.Conv2D(256, kernel_size=(3, 3), activation='relu'))(pool2) 
    pool3=(layers.MaxPooling2D((2, 2), strides=1))(conv3) 
    flat=(layers.Flatten())(pool3) 
    dense1=(layers.Dense(128, activation='relu'))(flat) 
    dense2=(layers.Dense(units=num_classes))(dense1)
    output=(layers.Softmax(name="output_node"))(dense2)
    model = models.Model(input_layer, output)
    model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])
    return model

model=create_model()
model.summary()
history = model.fit(X_train, Y_train, epochs=25, 
                    validation_data=(X_test, Y_test))

I checked if Tensorflow could parse the graph_def with this code, and it seems to work and I get the nodes with the right names and all.

f = gfile.FastGFile("./frozen_graph.pb", 'rb')
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
f.close()

I also tried creating the model using Sequential with the following code.

model=models.Sequential() 
model.add(layers.Input(shape = (16,16,1), name = "input_node"))
model.add(layers.Conv2D(64, kernel_size=(3, 3), activation='relu')) 
model.add(layers.MaxPooling2D((2, 2))) 
model.add(layers.Conv2D(128, kernel_size=(3, 3), activation='relu')) 
model.add(layers.MaxPooling2D((2, 2), strides=1))
model.add(layers.Conv2D(256, kernel_size=(3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2), strides=1)) 
model.add(layers.Flatten()) 
model.add(layers.Dense(128, activation='relu')) 
model.add(layers.Dense(units=num_classes)) 
model.add(layers.Softmax(name="output_node"))
model.compile(loss=krs.losses.categorical_crossentropy,
              optimizer=krs.optimizers.Adadelta(),
              metrics=['accuracy'])
model.summary()
history = model.fit(X_train, Y_train, epochs=25, 
                    validation_data=(X_test, Y_test))

And I get the same number of parameters and same accuracy/loss for both while training, so I was thinking they were pretty much equivalent. Instead, after saving it as a .h5 file, if I load the model and print the input node name it gives me conv2d_input as if it merged the input layer and the first convolutional layer. In this case I get this other error with the Vision Kit compiler:

./bonnet_model_compiler.par \
    --frozen_graph_path=./frozen_graph2.pb \
    --output_graph_path=./frozen_graph2.binaryproto \
    --input_tensor_name=conv2d_input \
    --output_tensor_names=output_node/Softmax\
    --input_tensor_size=256 \
    --debug

Errorr = 2020-01-31 01:30:27.240900: I external/org_tensorflow/tensorflow/contrib/lite/toco/graph_transformations/graph_transformations.cc:39] Before Removing unused ops: 35 operators, 50 arrays (0 quantized)
2020-01-31 01:30:27.241337: I external/org_tensorflow/tensorflow/contrib/lite/toco/graph_transformations/graph_transformations.cc:39] Before general graph transformations: 35 operators, 50 arrays (0 quantized)
2020-01-31 01:30:27.241414: F external/org_tensorflow/tensorflow/contrib/lite/toco/graph_transformations/propagate_fixed_sizes.cc:347] Check failed: output_depth == input_depth * op->depth_multiplier (64 vs. 192)input/output depths and depth_multiplier don't match

Both models have been created using Keras classes in TF 1.15 and both have been frozen using freeze_session (as done here https://www.dlology.com/blog/how-to-convert-trained-keras-model-to-tensorflow-and-make-prediction/). The node names should be right after checking the pbtxt file and parsing the graph_def.

Any help on how to solve this issue would be much appreciated.

  • were you able to solve it? I have a similar case https://stackoverflow.com/questions/53078505/google-aiy-vision-kit-compiler-get-output-node-from-tensorboard – Luis Leal Jul 24 '20 at 07:00

0 Answers0