Trying to build a new model based on part of pre-trained model,
Here's some cleaned out code.
Let's imagine we got model1 trained, and want to add some layers defined in model2:
import tensorflow.keras as keras
import tensorflow as tf
from tensorflow.keras.layers import Input, Conv2D, Activation
from tensorflow.keras.models import Model, Sequential
model1 = Sequential([
Conv2D(2, (3,3), padding='same', input_shape=(6,6,1)),
Activation('relu')
])
model2 = Sequential([
Conv2D(3, (3,3), padding='same', input_shape=(6,6,2)),
Activation('softmax')
])
model_merge = Model(inputs=model1.input,
outputs=Activation('softmax')(model2(model1.get_layer('conv2d').output)))
It looks a bit messy, but I want to demonstrate it's not disconnected by adding a softmax activation here.
summary of model1:
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 6, 6, 2) 20
_________________________________________________________________
activation (Activation) (None, 6, 6, 2) 0
=================================================================
Total params: 20
Trainable params: 20
Non-trainable params: 0
_________________________________________________________________
summary of model2:
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d_4 (Conv2D) (None, 6, 6, 3) 57
_________________________________________________________________
activation_4 (Activation) (None, 6, 6, 3) 0
=================================================================
Total params: 57
Trainable params: 57
Non-trainable params: 0
_________________________
And summary of model_merge:
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d_input (InputLayer) (None, 6, 6, 1) 0
_________________________________________________________________
conv2d (Conv2D) (None, 6, 6, 2) 20
_________________________________________________________________
sequential_2 (Sequential) (None, 6, 6, 3) 57
_________________________________________________________________
activation_4 (Activation) (None, 6, 6, 3) 0
=================================================================
Total params: 77
Trainable params: 77
Non-trainable params: 0
_________________________________________________________________
Let's prove this merged model is not disconnected:
layers = [layer.output for layer in model_merge.layers]
test1 = Model(inputs=model_merge.input, outputs=layers[-1])
Everything works just fine.
test1's summary:
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d_input (InputLayer) (None, 6, 6, 1) 0
_________________________________________________________________
conv2d (Conv2D) (None, 6, 6, 2) 20
_________________________________________________________________
sequential_2 (Sequential) (None, 6, 6, 3) 57
_________________________________________________________________
activation_4 (Activation) (None, 6, 6, 3) 0
=================================================================
Total params: 77
Trainable params: 77
Non-trainable params: 0
_________________________________________________________________
Here's the tragedy:
test2 = Model(inputs=model_merge.input, outputs=layers[-2])
The most important feed back:
ValueError: Graph disconnected: cannot obtain value for tensor Tensor("conv2d_2_input:0", shape=(?, 6, 6, 2), dtype=float32) at layer "conv2d_2_input". The following previous layers were accessed without issue: []
full feedback:
ValueErrorTraceback (most recent call last)
<ipython-input-18-946b325081c1> in <module>
----> 1 test = Model(inputs=model_merge.input, outputs=layers[-2])
/usr/local/lib/python3.5/dist-packages/tensorflow/python/keras/engine/training.py in __init__(self, *args, **kwargs)
119
120 def __init__(self, *args, **kwargs):
--> 121 super(Model, self).__init__(*args, **kwargs)
122 # Create a cache for iterator get_next op.
123 self._iterator_get_next = weakref.WeakKeyDictionary()
/usr/local/lib/python3.5/dist-packages/tensorflow/python/keras/engine/network.py in __init__(self, *args, **kwargs)
79 'inputs' in kwargs and 'outputs' in kwargs):
80 # Graph network
---> 81 self._init_graph_network(*args, **kwargs)
82 else:
83 # Subclassed network
/usr/local/lib/python3.5/dist-packages/tensorflow/python/training/checkpointable/base.py in _method_wrapper(self, *args, **kwargs)
440 self._setattr_tracking = False # pylint: disable=protected-access
441 try:
--> 442 method(self, *args, **kwargs)
443 finally:
444 self._setattr_tracking = previous_value # pylint: disable=protected-access
/usr/local/lib/python3.5/dist-packages/tensorflow/python/keras/engine/network.py in _init_graph_network(self, inputs, outputs, name)
219 # Keep track of the network's nodes and layers.
220 nodes, nodes_by_depth, layers, layers_by_depth = _map_graph_network(
--> 221 self.inputs, self.outputs)
222 self._network_nodes = nodes
223 self._nodes_by_depth = nodes_by_depth
/usr/local/lib/python3.5/dist-packages/tensorflow/python/keras/engine/network.py in _map_graph_network(inputs, outputs)
1850 'The following previous layers '
1851 'were accessed without issue: ' +
-> 1852 str(layers_with_complete_input))
1853 for x in node.output_tensors:
1854 computable_tensors.append(x)
ValueError: Graph disconnected: cannot obtain value for tensor Tensor("conv2d_2_input:0", shape=(?, 6, 6, 2), dtype=float32) at layer "conv2d_2_input". The following previous layers were accessed without issue: []
It's really driving me crazy,
Any ideas?
The layer you are trying to use as output has two output nodes. The first connects the input of model2
to the output of the model2
. The second output node connects the output of the model1
and the first layer of model2
. By default, the layer output returns only the first output node. So what is happening is you are tying to connect the input of the model_merge
(input of model1
) with the first output node.
To following code shows this. Individual output nodes of the layer can be accessed using the get_output_at()
method of the layer.
layer_output = model_merge.layers[-2].output # The first output node
layer_output_1 = model_merge.layers[-2].get_output_at(0) # The first output node
layer_output_2 = model_merge.layers[-2].get_output_at(1) # The second output node
Now the following two codes throws error because the graph is disconnected.
test2 = Model(inputs=model_merge.input, outputs=layer_output)
and
test2 = Model(inputs=model_merge.input, outputs=layer_output_1)
But the code below doesnot throw error, because the graph is connected.
test2 = Model(inputs=model_merge.input, outputs=layer_output_2)