google-research / receptive_field

Compute receptive fields of your favorite convnets
Apache License 2.0
432 stars 54 forks source link

TensorFlow 2+Keras support #5

Closed aizvorski closed 3 years ago

aizvorski commented 4 years ago

I'm trying to use this code with TensorFlow 2.2.0 (latest) and Keras 2.3.0 (built into tf) and I'm running into some errors.

import tensorflow as tf
import receptive_field as rf

g = tf.Graph()
with g.as_default():
    model = tf.keras.applications.InceptionV3()
    output_name = "inception_v3/conv2d_85/Conv2D"

    images = tf.Variable(tf.ones(shape=(1, 299, 299, 3)), name="input_image")
    model(images)

    rf_x, rf_y, eff_stride_x, eff_stride_y, eff_pad_x, eff_pad_y = \
      rf.compute_receptive_field_from_graph_def( \
      g.as_graph_def(), "input_image", output_name)

(tf.placeholder from the sample code replaced with tf.Variable)

Output:

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-48-2edcc65a3292> in <module>
      9     rf_x, rf_y, eff_stride_x, eff_stride_y, eff_pad_x, eff_pad_y = \
     10       rf.compute_receptive_field_from_graph_def( \
---> 11       g.as_graph_def(), "input_image", output_name)

~/anaconda3/envs/tensorflow2_latest_p37/lib/python3.7/site-packages/receptive_field/python/util/receptive_field_computation.py in compute_receptive_field_from_graph_def(graph_def, input_node, output_node, stop_propagation, input_resolution)
    272       (kernel_size_x, kernel_size_y, stride_x, stride_y, padding_x, padding_y,
    273        _, _) = parse_layer_parameters.get_layer_params(
--> 274            node, name_to_node, node_info[node.name].input_size)
    275       logging.vlog(
    276           3, "kernel_size_x = %s, kernel_size_y = %s, "

~/anaconda3/envs/tensorflow2_latest_p37/lib/python3.7/site-packages/receptive_field/python/util/parse_layer_parameters.py in get_layer_params(node, name_to_node, input_resolution, force)
    292   if node.op == "Conv2D" or node.op == "DepthwiseConv2dNative":
    293     stride_x, stride_y = _stride_size(node, name_to_node)
--> 294     kernel_size_x, kernel_size_y = _conv_kernel_size(node, name_to_node)
    295     # Compute the padding for this node separately for each direction.
    296     total_padding_x, padding_x = _padding_size_conv_pool(

~/anaconda3/envs/tensorflow2_latest_p37/lib/python3.7/site-packages/receptive_field/python/util/parse_layer_parameters.py in _conv_kernel_size(node, name_to_node)
     95         "Weight layer's name input to conv layer does not end with '/read' or "
     96         "'/Conv2D/ReadVariableOp': %s" % weights_layer_read_name)
---> 97   weights_node = name_to_node[weights_layer_param_name]
     98   if weights_node.op == "VariableV2" or weights_node.op == "VarHandleOp":
     99     shape_dim = weights_node.attr["shape"].shape.dim

KeyError: 'inception_v3/conv2d_85/kernel'

Similarly for VGG:

g = tf.Graph()
with g.as_default():
    model = tf.keras.applications.VGG19()
    output_name = "vgg19/block5_conv4/Conv2D"

    images = tf.Variable(tf.ones(shape=(1, 224, 224, 3)), name="input_image")
    model(images)

    rf_x, rf_y, eff_stride_x, eff_stride_y, eff_pad_x, eff_pad_y = \
      rf.compute_receptive_field_from_graph_def( \
      g.as_graph_def(), "input_image", output_name)
~/anaconda3/envs/tensorflow2_latest_p37/lib/python3.7/site-packages/receptive_field/python/util/parse_layer_parameters.py in _conv_kernel_size(node, name_to_node)
     95         "Weight layer's name input to conv layer does not end with '/read' or "
     96         "'/Conv2D/ReadVariableOp': %s" % weights_layer_read_name)
---> 97   weights_node = name_to_node[weights_layer_param_name]
     98   if weights_node.op == "VariableV2" or weights_node.op == "VarHandleOp":
     99     shape_dim = weights_node.attr["shape"].shape.dim

KeyError: 'vgg19/block5_conv4/kernel'

Could you please let me know what's going wrong and how to fix it?

I tried with TF 1.15.2 and Keras 2.2.4-tf and got a different set of errors, so I don't think downgrading is enough to fix this.

It would be really nice if this worked with the latest set of models (eg from tensorflow hub or https://github.com/tensorflow/models/), and Keras is now officially in TF as well so it would be nice if it was supported out of the box.

SorourMo commented 4 years ago

Hi,

If you'd like to get a response from the authors, take a look at here:

andrefaraujo commented 3 years ago

Sorry for the extremely long delay! Indeed I had not been notified of this issue. In any case, here goes the answer -- using this library with tf.keras.applications models works :)

Here's how to compute it for the InceptionV3 example you tried, @aizvorski

import tensorflow.compat.v1 as tf
import receptive_field as rf

g = tf.Graph()
with g.as_default():
  tf.keras.backend.set_learning_phase(0) # Disable BN learning.
  x = tf.keras.Input([None, None, 3], name='input_image')
  model = tf.keras.applications.InceptionV3(input_tensor=x)

graph_def = g.as_graph_def()

input_node = 'input_image'
output_node = 'conv2d_85/Conv2D'
(receptive_field_x, receptive_field_y, effective_stride_x,
 effective_stride_y, effective_padding_x, effective_padding_y) = (
         rf.compute_receptive_field_from_graph_def(graph_def, input_node,
                                                   output_node))

# These will print 1183.
print(receptive_field_x)
print(receptive_field_y)

# These will print 32.
print(effective_stride_x)
print(effective_stride_y)

# These will print 554.
print(effective_padding_x)
print(effective_padding_y)

This gives identical numbers as the Mixed_7b layer from the Slim inception_v3 model (see table).