why does this error happen in Keras,"Graph disconnected" when I want to separate whole network into two models?
I have an autoencoder in keras and I need to define a different model for each part because my network has two outputs and I want to have two separate network for each output during the test, but when I do this it produces the following error.
Traceback (most recent call last):
File "", line 99, in wext=Model(inputs=decoded_noise,outputs=pred_w)
File "D:\software\Anaconda3\envs\py36\lib\site-packages\keras\legacy\interfaces.py", line 91, in wrapper return func(*args, **kwargs)
File "D:\software\Anaconda3\envs\py36\lib\site-packages\keras\engine\network.py", line 93, in init self._init_graph_network(*args, **kwargs)
File "D:\software\Anaconda3\envs\py36\lib\site-packages\keras\engine\network.py", line 231, in _init_graph_network self.inputs, self.outputs)
File "D:\software\Anaconda3\envs\py36\lib\site-packages\keras\engine\network.py", line 1443, in _map_graph_network str(layers_with_complete_input))
ValueError: Graph disconnected: cannot obtain value for tensor Tensor("input_8:0", shape=(?, 28, 28, 1), dtype=float32) at layer "input_8". The following previous layers were accessed without issue: []
I want to have two networks during test one of them from the encoder to end of the decoder and second for w extraction part. what is the problem? Thank you.
#-----------------------encoder------------------------------------------------
wtm=Input((28,28,1))
image = Input((28, 28, 1))
conv1 = Conv2D(64, (5, 5), activation='relu', padding='same', name='convl1e',dilation_rate=(2,2))(image)
conv2 = Conv2D(64, (5, 5), activation='relu', padding='same', name='convl2e',dilation_rate=(2,2))(conv1)
conv3 = Conv2D(64, (5, 5), activation='relu', padding='same', name='convl3e',dilation_rate=(2,2))(conv2)
BN=BatchNormalization()(conv3)
encoded = Conv2D(1, (5, 5), activation='relu', padding='same',name='encoded_I',dilation_rate=(2,2))(BN)
add_const = Kr.layers.Lambda(lambda x: x[0] + x[1])
encoded_merged = add_const([encoded,wtm])
#-----------------------decoder------------------------------------------------
deconv1 = Conv2D(64, (5, 5), activation='relu', padding='same', name='convl1d',dilation_rate=(2,2))(encoded_merged)
deconv2 = Conv2D(64, (5, 5), activation='relu', padding='same', name='convl2d',dilation_rate=(2,2))(deconv1)
deconv3 = Conv2D(64, (5, 5), activation='relu',padding='same', name='convl3d',dilation_rate=(2,2))(deconv2)
deconv4 = Conv2D(64, (5, 5), activation='relu',padding='same', name='convl4d',dilation_rate=(2,2))(deconv3)
BNd=BatchNormalization()(deconv3)
decoded = Conv2D(1, (5, 5), activation='sigmoid', padding='same', name='decoder_output',dilation_rate=(2,2))(BNd)
model1=Model(inputs=[image,wtm],outputs=decoded)
decoded_noise = GaussianNoise(0.5)(decoded)
#----------------------w extraction------------------------------------
convw1 = Conv2D(64, (3,3), activation='relu', padding='same', name='conl1w',dilation_rate=(2,2))(decoded_noise)
convw2 = Conv2D(64, (3, 3), activation='relu', padding='same', name='convl2w',dilation_rate=(2,2))(convw1)
convw3 = Conv2D(64, (3, 3), activation='relu', padding='same', name='conl3w',dilation_rate=(2,2))(convw2)
convw4 = Conv2D(64, (3, 3), activation='relu', padding='same', name='conl4w',dilation_rate=(2,2))(convw3)
convw5 = Conv2D(64, (3, 3), activation='relu', padding='same', name='conl5w',dilation_rate=(2,2))(convw4)
convw6 = Conv2D(64, (3, 3), activation='relu', padding='same', name='conl6w',dilation_rate=(2,2))(convw5)
pred_w = Conv2D(1, (1, 1), activation='sigmoid', padding='same', name='reconstructed_W',dilation_rate=(2,2))(convw6)
wext=Model(inputs=decoded_noise,outputs=pred_w)
final=Model(inputs=[image,wtm],outputs=[decoded,pred_w])
Modified code:
from keras.layers import Input, Concatenate, GaussianNoise,Cropping2D,Activation,Dropout,BatchNormalization,MaxPool2D,AveragePooling2D,ZeroPadding2D
from keras.layers import Conv2D, AtrousConv2D
from keras.models import Model
from keras.datasets import mnist
from keras.callbacks import TensorBoard
from keras import backend as K
from keras import layers
import matplotlib.pyplot as plt
import tensorflow as tf
import keras as Kr
from keras.optimizers import SGD,RMSprop,Adam
from keras.callbacks import ReduceLROnPlateau
from keras.callbacks import EarlyStopping
from keras.callbacks import ModelCheckpoint
import numpy as np
import pylab as pl
import matplotlib.cm as cm
import keract
from matplotlib import pyplot
from keras import optimizers
from keras import regularizers
from tensorflow.python.keras.layers import Lambda;
w_expand=np.zeros((49999,28,28),dtype='float32')
wv_expand=np.zeros((9999,28,28),dtype='float32')
wt_random=np.random.randint(2, size=(49999,4,4))
wt_random=wt_random.astype(np.float32)
wv_random=np.random.randint(2, size=(9999,4,4))
wv_random=wv_random.astype(np.float32)
w_expand[:,:4,:4]=wt_random
wv_expand[:,:4,:4]=wv_random
x,y,z=w_expand.shape
w_expand=w_expand.reshape((x,y,z,1))
x,y,z=wv_expand.shape
wv_expand=wv_expand.reshape((x,y,z,1))
#-----------------building w test---------------------------------------------
w_test = np.random.randint(2,size=(1,4,4))
w_test=w_test.astype(np.float32)
wt_expand=np.zeros((1,28,28),dtype='float32')
wt_expand[:,0:4,0:4]=w_test
wt_expand=wt_expand.reshape((1,28,28,1))
#-----------------------encoder------------------------------------------------
#------------------------------------------------------------------------------
wtm=Input((28,28,1))
image = Input((28, 28, 1))
conv1 = Conv2D(64, (5, 5), activation='relu', padding='same', name='convl1e',dilation_rate=(2,2))(image)
conv2 = Conv2D(64, (5, 5), activation='relu', padding='same', name='convl2e',dilation_rate=(2,2))(conv1)
conv3 = Conv2D(64, (5, 5), activation='relu', padding='same', name='convl3e',dilation_rate=(2,2))(conv2)
BN=BatchNormalization()(conv3)
encoded = Conv2D(1, (5, 5), activation='relu', padding='same',name='encoded_I',dilation_rate=(2,2))(BN)
add_const = Kr.layers.Lambda(lambda x: x[0] + x[1])
encoded_merged = add_const([encoded,wtm])
#-----------------------decoder------------------------------------------------
deconv1 = Conv2D(64, (5, 5), activation='relu', padding='same', name='convl1d',dilation_rate=(2,2))(encoded_merged)
deconv2 = Conv2D(64, (5, 5), activation='relu', padding='same', name='convl2d',dilation_rate=(2,2))(deconv1)
deconv3 = Conv2D(64, (5, 5), activation='relu',padding='same', name='convl3d',dilation_rate=(2,2))(deconv2)
deconv4 = Conv2D(64, (5, 5), activation='relu',padding='same', name='convl4d',dilation_rate=(2,2))(deconv3)
BNd=BatchNormalization()(deconv3)
decoded = Conv2D(1, (5, 5), activation='sigmoid', padding='same', name='decoder_output',dilation_rate=(2,2))(BNd)
model1=Model(inputs=[image,wtm],outputs=decoded)
decoded_input=Input((28,28,1))
#----------------------w extraction------------------------------------
convw1 = Conv2D(64, (3,3), activation='relu', padding='same', name='conl1w',dilation_rate=(2,2))(decoded_input)
convw2 = Conv2D(64, (3, 3), activation='relu', padding='same', name='convl2w',dilation_rate=(2,2))(convw1)
convw3 = Conv2D(64, (3, 3), activation='relu', padding='same', name='conl3w',dilation_rate=(2,2))(convw2)
convw4 = Conv2D(64, (3, 3), activation='relu', padding='same', name='conl4w',dilation_rate=(2,2))(convw3)
convw5 = Conv2D(64, (3, 3), activation='relu', padding='same', name='conl5w',dilation_rate=(2,2))(convw4)
convw6 = Conv2D(64, (3, 3), activation='relu', padding='same', name='conl6w',dilation_rate=(2,2))(convw5)
pred_w = Conv2D(1, (1, 1), activation='sigmoid', padding='same', name='reconstructed_W',dilation_rate=(2,2))(convw6)
decoded_noise = GaussianNoise(0.5)(decoded)
wext=Model(inputs=decoded_input, outputs=pred_w)
pred_w = wext(decoded_noise)
w_extraction=Model(inputs=[image,wtm],outputs=[decoded,pred_w])
#----------------------training the model-----------------------------------
(x_train, _), (x_test, _) = mnist.load_data()
x_validation=x_train[1:10000,:,:]
x_train=x_train[10001:60000,:,:]
#
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
x_validation = x_validation.astype('float32') / 255.
x_train = np.reshape(x_train, (len(x_train), 28, 28, 1)) # adapt this if using `channels_first` image data format
x_test = np.reshape(x_test, (len(x_test), 28, 28, 1)) # adapt this if using `channels_first` image data format
x_validation = np.reshape(x_validation, (len(x_validation), 28, 28, 1))
#---------------------compile and train the model------------------------------
opt=SGD(momentum=0.99,lr=0.0001)
w_extraction.compile(optimizer='adam', loss={'imageprim':'mse','wprimmain':'binary_crossentropy'}, loss_weights={'imageprim': 1.0, 'wprimmain': 1.0},metrics=['mae'])
es = EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=40)
#rlrp = ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=20, min_delta=1E-4, verbose=1)
mc = ModelCheckpoint('los4x4_con_tile_convolw_FBN_SigAct_SandPAttack.h5', monitor='val_loss', mode='min', verbose=1, save_best_only=True)
history=w_extraction.fit([x_train,w_expand], [x_train,w_expand],
epochs=1,
batch_size=32,
validation_data=([x_validation,wv_expand], [x_validation,wv_expand]),
callbacks=[TensorBoard(log_dir='/home/jamalm8/tensorboardGNWLoss/', histogram_freq=0, write_graph=False),es,mc])
w_extraction.summary()
the produced error:
Traceback (most recent call last):
File "", line 113, in w_extraction.compile(optimizer='adam', loss={'imageprim':'mse','wprimmain':'binary_crossentropy'}, loss_weights={'imageprim': 1.0, 'wprimmain': 1.0},metrics=['mae'])
File "D:\software\Anaconda3\envs\py36\lib\site-packages\keras\engine\training.py", line 119, in compile str(self.output_names))
ValueError: Unknown entry in loss dictionary: "imageprim". Only expected the following keys: ['decoder_output', 'model_29']
Answer
The error you're encountering happens because Keras is expecting the loss to be specified with respect to the model's output layer names, but it seems you are using custom names in your loss dictionary that do not match the actual output names of your model.
Let's break down the issue:
Key Points:
-
Output Layer Names: When you define a model in Keras, the layers, including the output layers, are given default names based on their layer types (e.g.,
decoder_output
,model_29
). If you do not explicitly name them, Keras will auto-generate these names. -
Loss Dictionary: When using
model.compile()
, you need to specify the losses according to the names of the output layers. The error message suggests that"imageprim"
and"wprimmain"
are not recognized because these names do not match the actual output names of the model.
Fix:
You need to modify the loss dictionary to use the correct output layer names. In your code, it looks like your outputs are named decoder_output
(for the decoder) and model_29
(for the wext
model's output).
Here is how you can fix it:
1. Check the Output Layer Names:
If you have not explicitly named your layers, Keras will assign default names like decoder_output
for the first output and model_29
for the second one. If you're unsure about the output names, you can check them by printing the model summary:
w_extraction.summary()
This will list all layers and their names, which will help you determine the exact names of the outputs.
2. Update the Loss Dictionary:
You should change the loss
dictionary to match the correct output layer names. Based on your model structure and the summary, here's how you can modify the compile
method:
w_extraction.compile(
optimizer='adam',
loss={'decoder_output': 'mse', 'reconstructed_W': 'binary_crossentropy'},
loss_weights={'decoder_output': 1.0, 'reconstructed_W': 1.0},
metrics=['mae']
)
Here:
decoder_output
corresponds to the decoded image output.reconstructed_W
corresponds to the output from thewext
model.
3. Ensure Consistent Naming:
If you explicitly named your layers (e.g., imageprim
, wprimmain
), you need to ensure that the Model
outputs in the final
model are correctly referenced in the loss
dictionary. If decoder_output
and reconstructed_W
are the outputs, use those in the loss function.
Full Code Snippet:
w_extraction.compile(
optimizer='adam',
loss={'decoder_output': 'mse', 'reconstructed_W': 'binary_crossentropy'},
loss_weights={'decoder_output': 1.0, 'reconstructed_W': 1.0},
metrics=['mae']
)
This should resolve the ValueError
since the model will now correctly map the loss functions to the corresponding output layers.
Let me know if this clears up the issue or if you need further clarification!