keras-vis: Multiple inbound nodes error when visualising dense softmax

Im using the Keras VGG16 net with a custom top layer (4 class softmax)

Loaded model with layers: 
[u'input_2', u'block1_conv1', u'block1_conv2', u'block1_pool', u'block2_conv1', u'block2_conv2', u'block2_pool', u'block3_conv1', u'block3_conv2', u'block3_conv3', u'block3_pool', u'block4_conv1', u'block4_conv2', u'block4_conv3', u'block4_pool', u'block5_conv1', u'block5_conv2', u'block5_conv3', u'block5_pool', u'flatten_2', u'dense_2', u'dropout_2', u'predictions']

However, trying to visualise the filters for the top level (Dense) softmax layer (‘predictions’) is throwing an error on:

tot_filters = get_num_filters(layer)

File "/usr/local/lib/python2.7/site-packages/keras_vis-0.3-py2.7.egg/vis/visualization.py", line 30, in get_num_filters
   isDense = K.ndim(layer.output) == 2
 File "/Users/dgorissen/Library/Python/2.7/lib/python/site-packages/keras/engine/topology.py", line 933, in output
   ' has multiple inbound nodes, '
AttributeError: Layer predictions has multiple inbound nodes, hence the notion of "layer output" is ill-defined. Use `get_output_at(node_index)` instead.

Hardcoding the value to 4 results in the same error later on:

   img = visualize_activation(model, layer_idx, filter_indices=[idx])
  File "/usr/local/lib/python2.7/site-packages/keras_vis-0.3-py2.7.egg/vis/visualization.py", line 108, in visualize_activation
    opt = Optimizer(model.input, losses)
  File "/usr/local/lib/python2.7/site-packages/keras_vis-0.3-py2.7.egg/vis/optimizer.py", line 35, in __init__
    loss_fn = weight * loss.build_loss()
  File "/usr/local/lib/python2.7/site-packages/keras_vis-0.3-py2.7.egg/vis/losses.py", line 76, in build_loss
    layer_output = self.layer.output
  File "/Users/dgorissen/Library/Python/2.7/lib/python/site-packages/keras/engine/topology.py", line 933, in output
    ' has multiple inbound nodes, '
AttributeError: Layer predictions has multiple inbound nodes, hence the notion of "layer output" is ill-defined. Use `get_output_at(node_index)` instead.

Looking at the docs and googling around it would seem that this should just work. What am I missing?

Edit: My overall model is a Sequential() model stuck on top of the base VGG model. The above output is after flattening the overall model into a single Sequential() model with a flat list of layers. However that seems to break things for after flattening, trying to visualise block5_conv1 gives the same error. Without flattening it works fine.

So I guess my question is, how best to deal with nested models, or get the overall model into a shape I can visualise the last dense layer.

About this issue

  • Original URL
  • State: open
  • Created 7 years ago
  • Reactions: 4
  • Comments: 29 (2 by maintainers)

Most upvoted comments

Try building your model without using a sequential model. E.g. for VGG-16 do this;

# get base model
base_model = applications.VGG16(weights='imagenet', include_top=False,input_shape = (img_width, img_height, 3))

# build top model
x = Flatten(name='flatten')(base_model.output)
x = Dense(4096, activation='relu', name='fc1')(x)
x = Dense(4096, activation='relu', name='fc2')(x)
x = Dense(3, activation='softmax', name='predictions')(x)

# stitch together
model = Model(inputs= base_model.input, outputs=x)

# inspect
model.summary()

This builds the model as one unified network rather than two cascading ones.

@yuval-harpaz 's hack seems to work for me. I’m using a cascaded model with a Sequential model on top of base MobileNetV2 (alpha=0.25).

I had a similar error for a network with two nodes of output, dense_1_1/Relu:0 and sequential_2/dense_1/Relu:0 . The solution for me was to go to losses.py and change layer_output = self.layer.output to layer_output = self.layer.get_output_at(-1).

For those of you who want to try out this method, I’ll reformat the code:

Line 76 of losses.py

    #layer_output = self.layer.output
    layer_output = self.layer.get_output_at(-1)

Resnet5 same problem…

I had a similar error for a network with two nodes of output, dense_1_1/Relu:0 and sequential_2/dense_1/Relu:0 . The solution for me was to go to losses.py and change layer_output = self.layer.output to layer_output = self.layer.get_output_at(-1).

Any updates on this? I don’t understand the answer from @8enmann - how do I implement that? I am trying to do the same with visualize_cam and visualize_saliency but get the multiple inbound nodes error. Hope you can help.