-
-
Notifications
You must be signed in to change notification settings - Fork 55.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[dnn] Unknown layer type Square in op netvlad/l2_normalize/Square #11223
Comments
Update The problem is that some layer like L2normalize isn t supported but I have seen that in tf_importer.cpp there is a L2Normalize layer defined. |
@DavideCatto, Could you please test your model with the changes from a pull request #11236? |
@dkurt I have tested your pull request #11236 and the conversion of the layer l2_normalize seem worker; the problems occurs when it try to recognize the l2_normalization type. In particular the model does the l2.nn.l2_normalize using axis=1 and the error is "Cannot determine normalization axis". I have check that axis is equal 1 before the if, but using tensorflow Data_layout is Channel last so I think doesn't enter into the if section.
Thanks for your support, I think that for the moment the l2_normalization along other axis isn' supported yet. I hope it will be implemented soon on in other version of opencv. |
@DavideCatto, please provide TensorFlow code. Do you mean something like this? input = tf.placeholder(tf.float32, [1, 2, 3, 4]) # NHWC data layout
norm = tf.nn.l2_normalize(input, axis=1) |
@dkurt exactly like your code, a simple: -- another unsupported layer -- |
@DavideCatto, just to clarify the operation, for the following input of size
TensorFlow code inp = tf.placeholder(tf.float32, [1, 2, 3, 4], 'input')
l2norm = tf.nn.l2_normalize(inp, axis=1)
save(inp, l2norm, 'l2_normalize') produces the following output:
So it normalizes an every column.
However inp = tf.placeholder(tf.float32, [1, 2, 3, 4], 'input')
l2norm = tf.nn.l2_normalize(inp, axis=[1, 2])
save(inp, l2norm, 'l2_normalize') normalizes spatial slices:
To normalize a whole batch, you need to pass all the dimensions: l2norm = tf.nn.l2_normalize(inp, axis=[1, 2, 3])
Here a sum of squares of all the values is equal to 1. Could you please specify what kind of transformation do you want to implement? |
@dkurt Every example into the batch [1, 2, 3, 4] is used like a [6, 4] descriptors, where 6 represent the number of the local descriptors for that example and every local descriptors's size is 4. My problem maybe is that the l2_normalization is working consider NHWC or a NCHW input tensors, and it isn't generic for all type tensors. example [1, 2, 3] Problem 2 Update
|
@DavideCatto, May I ask you to test your model with an updated PR #11236? |
@dkurt Thank you for your work! I have tried and it's seem working, have you already tested with simple model like this one? I'm trying right now these examples, because my model can define now the l2_normalize layer but it has some trouble with another unsupported layer: ExpandDims layer that isn't implemented yet. If you want, here there is my test model. The input layer is named "input" with a size of (224, 224, 3) and an output named "netvlad/l2_normalization_2" with an output of (8192). |
@DavideCatto, You may look at opencv/opencv_extra#454 for added tests. Have you tried to replace tf.expand_dims to tf.reshape? The first one is useful only if input's sizes are unknown. |
@dkurt, OK, for the test! my mistake, sorry. Fot the second question my problem is that the tf.expand_dims is necessary for obtain, after a convolution of the input [BxNxDx1] (my local descriptors associated to an example) with the kernel [1, D, 1, K] (D is the dimension of the local descriptor and K is the centers of the clusters) an output of [B x N x 1 x K] (for every Descriptors obtain the "distance"/"similarity" with all K centers). So is for obtain from [BxNxDx1] conv2d [1,D,1,K] an output of [BxNx1xK], I can't use reshape, it's for matrix coherence dimensionality. |
@DavideCatto, please add a code example. |
@dkurt Of course.. input = tf.placeholder(tf.float32, [1, 14, 14, 128], name="input")
conv_reshape = tf.reshape(input, shape = [-1, (14*14), 128], name='reshape') # conv_reshape is BxNxD
conv_norm = tf.nn.l2_normalize(conv_reshape, axis=1)
descriptor = tf.expand_dims(conv_norm, axis=-1, name='expanddim') # descriptor is B x N x D x 1
conv_vlad = tf.nn.convolution(descriptor, filt, padding='VALID') # conv_vlad is B x N x 1 x K
bias = tf.nn.bias_add(conv_vlad, conv_biases)
a_k = tf.nn.softmax(tf.squeeze(bias, axis=2), axis=-1, name="vlad_softmax") # a_k is B x N x K
V1 = tf.matmul(conv_reshape, a_k, transpose_a=True) # V_1 is B x D x K
V2 = tf.multiply(tf.reduce_sum(a_k, axis=1, keepdims=True), centers) # V_1 is B x D x K
V = tf.subtract(V1, V2)
norm = tf.nn.l2_normalize(tf.reshape(tf.nn.l2_normalize(V, axis=1), shape=[-1, 128 * 64]), axis=1) # norm is B x (D x K) where: |
@dkurt any update? |
@DavideCatto, the problem is that we try to focus on image processing and it's hard to support general cases like that. I'll try to make this particular example work again. |
@DavideCatto, This is a simplified part of your sample which can work with changes from a PR #11826: import tensorflow as tf
import cv2 as cv
import numpy as np
np.random.seed(324)
D = 128
K = 64
filt = tf.Variable(tf.random_normal([1, D, 1, K]), name='filt')
conv_biases = tf.Variable(tf.random_normal([K]), name='conv_biases')
input = tf.placeholder(tf.float32, [1, 14*14, D, 1], name="input")
conv_norm = tf.nn.l2_normalize(input, axis=1)
conv_vlad = tf.nn.convolution(conv_norm, filt, padding='VALID', name='output') # conv_vlad is B x N x 1 x K
bias = tf.nn.bias_add(conv_vlad, conv_biases)
a_k = tf.nn.softmax(tf.squeeze(bias, axis=2), axis=-1) # a_k is B x N x K
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
inputData = np.random.standard_normal([1, 14*14, D, 1]).astype(np.float32)
tfOut = sess.run(sess.graph.get_tensor_by_name('output:0'),
feed_dict={'input:0': inputData})
graph_def = sess.graph.as_graph_def()
graph_def = tf.graph_util.convert_variables_to_constants(sess, graph_def, ['output'])
with tf.gfile.FastGFile('graph.pb', 'wb') as f:
f.write(graph_def.SerializeToString())
net = cv.dnn.readNet('graph.pb')
net.setInput(inputData.transpose(0, 3, 1, 2))
cvOut = net.forward()
print np.max(np.abs(cvOut - tfOut.transpose(0, 3, 1, 2))) Output difference is about 1e-6. As you may see it receives already reshaped data. The following untrainable matmul is not supported for now. You may perform it outside the network multiplying it's input to it's output. |
@dkurt OK, thank you for this solution; It's a bit different from the original but I think that it works for my purpose. Thank you again! |
System information (version)
Error description
During the loading of tf model
cv::dnn::Net net = cv::dnn::readNetFromTensorflow(modelFile);
I get this error, related to the l2_normalize layer:
How can solve it? Can I merge or define a layer like "FusedBatchNorm" for obtain the "L2Normalize" layer? I'm asking for this solution because I have seen that during the populateNet function in tf_importer.cpp there is a layer defined "L2Normalize" but it doesn t enter into the L2normalize's if because it searching for the "Square" layer that isn t defined.
The text was updated successfully, but these errors were encountered: