Keras: Cannot stack models in Model Class API

Created on 2 Dec 2016  路  15Comments  路  Source: keras-team/keras

I cannot stack a classifier model on top of a (partly) pre-trained VGG16 model in Model Class API. There are several threads with people having the same problem Google Groups and StackoverFlow. I have tried all variants, but I keep getting a Graph disconnect error:

Exception: Graph disconnected: cannot obtain value for tensor input_2 at layer "

My last attempt:

from keras.applications.vgg16 import VGG16
from keras.models import Model
from keras.layers import Convolution2D, MaxPooling2D, ZeroPadding2D, GlobalAveragePooling2D
from keras.layers import Dropout, Flatten, Dense, Input

img_width, img_height = 150, 150

input_1 = Input(shape=(3, img_width, img_height))

vgg16_model = VGG16(include_top=False, weights='imagenet', input_tensor=input_1)

input_2 = Input(shape=vgg16_model.output_shape[1:])
x = GlobalAveragePooling2D()(input_2)
x = Dense(256, activation='relu')(x)
x = Dropout(0.5)(x)
predict = Dense(1, activation='sigmoid')(x)
top_model = Model(input=input_2, output=predict)

# load the best saved weights
#top_model.load_weights(os.path.join(data_path, 'VGG16Classifier.hdf5'))  
# add the model on top of the convolutional base

model = Model(input=input_1, output=top_model.output)

For info I am trying to re-create this Keras Blog , but with the Model Class API in order to later modify the VGG16 model.
Is there a bug that is preventing this from working? Thanks, Jan

Oh, and I am totally thrilled about Keras!!! Really impressive!

Most helpful comment

Everyone, please be professional.

All 15 comments

@farizrahman4u I also reported this same issue along with a few others. How can we help get this fixed?

The issue is exactly what the error message says. There is no path from input_1 to top_model.output. So nothing to fix on keras side.

@farizrahman4u This is rude comment. This is actually an error that @fchollet fixed, #4477.

@farizrahman4u You've made me irritated with your comment so I will carefully show you the path from input_t to top_model.output.

input_1 feeds into vgg16_model, vgg_model.output feeds into input_2. Input_2 goes to x via the functional API. x goes into predict and then predict goes into top_model = Model(input=input_2, output=predict).

You've made me irritated with your comment

You irritate me with your existence.

vgg_model.output feeds into input_2

No it doesn't. If it does, kindly comment the particular line, Sir.

Here is the original code by OP. You will still get the error, with latest version of Keras; because it is supposed to.

from keras.applications.vgg16 import VGG16
from keras.models import Model
from keras.layers import Convolution2D, MaxPooling2D, ZeroPadding2D, GlobalAveragePooling2D
from keras.layers import Dropout, Flatten, Dense, Input

img_width, img_height = 150, 150

input_1 = Input(shape=(3, img_width, img_height))

vgg16_model = VGG16(include_top=False, weights='imagenet', input_tensor=input_1)

input_2 = Input(shape=vgg16_model.output_shape[1:])
x = GlobalAveragePooling2D()(input_2)
x = Dense(256, activation='relu')(x)
x = Dropout(0.5)(x)
predict = Dense(1, activation='sigmoid')(x)
top_model = Model(input=input_2, output=predict)

# load the best saved weights
#top_model.load_weights(os.path.join(data_path, 'VGG16Classifier.hdf5'))  
# add the model on top of the convolutional base

model = Model(input=input_1, output=top_model.output)

Maybe next time ask someone less rude?

Hi Farirz and Isaac, thank you both for trying to help me get unstuck! Fariz, as you can see I do not see how I can make this work. The code above is just one of many configs I've tried. So may I ask you politely to show me how you think this would work? Isaac and I have given it our best, but so far we have not been able to crack it. Thank you very much! Jan

@jdelange Its pretty straight forward:

img_width, img_height = 150, 150
input = Input(shape=(3, img_width, img_height))
vgg16_model = VGG16(include_top=False, weights='imagenet')
x = vgg16_model(input)
x = GlobalAveragePooling2D()(x)
x = Dense(256, activation='relu')(x)
x = Dropout(0.5)(x)
predict = Dense(1, activation='sigmoid')(x)
model = Model(input=input, output=predict)

P.S Not tested.

Just split the model:

img_width, img_height = 150, 150
vgg16_model = VGG16(include_top=False, weights='imagenet')

input = Input(batch_shape=vgg16_model.output_shape)
x = GlobalAveragePooling2D()(input)
x = Dense(256, activation='relu')(x)
x = Dropout(0.5)(x)
predict = Dense(1, activation='sigmoid')(x)
top_model = Model(input, predict)

top_model.load_weights(os.path.join(data_path, 'VGG16Classifier.hdf5'))  

input = Input(shape=(3, img_width, img_height))
x = vgg16_model(input)
predict = top_model(x)
model = Model(input, predict)

Looks good. I will try to compile and run this. If it works I will share and close the issue.

The good news: the above code compiles and runs. To replicate the Keras tutorial however, I need a Flatten() as first layer in the top_model. GlobalAveragePooling2D does not converge. Replacing the GlobalAveragePooling2D() layer with a Flatten() layer generates the following error:

File "C:\Program Files\Anaconda2lib\site-packages\keras\layers\core.py", lin 433, in get_output_shape_for '(got ' + str(input_shape[1:]) + '. '
Exception: The shape of the input to "Flatten" is not fully defined (got (512,
None, None). Make sure to pass a complete "input_shape" or "batch_input_shape" argument to the first layer in your model.

Addinginput_shape=(3, img_width, img_height) to the VVG16 model raised the 3-channel error I mentioned here #4477. I fixed this by creating a stripped version of the VGG16 model taking out all Tensorflow stuff. It then runs and converges. I realize I would do better by figuring out what causes the issue, but I am not experienced enough.

Perhaps there is a better / more logical way to fully define the input shape?

Since I am now able to proceed, I will close this issue and thank you very much for helping me out. I will copy these findings to the Keras Google group for the benefit of others.

You irritate me with your existence.

@farizrahman4u Boo hoo buddy, get over it

isaacreg

Babies are the ones who delete their comments.

@isaacgerg
You are the one who called me for help, and I did help you with the issue. You called me rude and irritating for pointing out a mistake in your code? (assuming @jdelange is in your team), What did you expect? Also, you do realize that I don't get paid for any of this right? Hope you don't find all the free work we do here for you rude or irritating. "Get over it"? Get over what? You are just an internet troll, who can't even get a trivial VGG to compile. And ping "(@)fchollet" ? You gonna tell on me? Who is the baby now?

trolls_should_go_back_to_youtube_comments

Everyone, please be professional.

@farizrahman4u @fchollet

This is it for me. I am moving to tensorflow.

Was this page helpful?
0 / 5 - 0 ratings