You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Have I written custom code (as opposed to using a stock example script provided in TensorFlow)
: Yes
OS Platform and Distribution (e.g., Linux Ubuntu 16.04)
: Colab
Mobile device (e.g. iPhone 8, Pixel 2, Samsung Galaxy) if the issue happens on mobile device
:
TensorFlow installed from (source or binary)
: Colab
TensorFlow version (use command below)
: 1.10.1
Python version
: 3.6
Bazel version (if compiling from source)
: Colab
GCC/Compiler version (if compiling from source)
: Colab
CUDA/cuDNN version
: Colab
GPU model and memory
: Colab
Exact command to reproduce
:
Describe the problem
When we delete a layer with model.layers.pop(), the deleted layer reappears.
Source code / logs
import tensorflow as tf
import tensorflow.keras as keras
import tensorflow.keras.backend as K
from tensorflow.keras.layers import Dense, Input, Layer
from tensorflow.keras.models import Model
input_tensor = Input(shape=(10,))
hidden = Dense(100, activation='relu')(input_tensor)
out = Dense(10, activation='relu')(hidden)
model = Model(input_tensor, out)
model.compile(loss="mse", optimizer=tf.train.AdamOptimizer(learning_rate=0.001))
model.summary()
model.layers.pop()
model.layers.pop()
model.summary()
hidden = Dense(120, activation='relu')(model.layers[-1].output)
out = Dense(5, activation='softmax')(hidden)
model = Model(input_tensor, out)
model.summary()
@ymodak thank you for the response. I have created a second model as suggested in the similar thread.
Unfortunately, it is not working. Please note that in https://github.com/keras-team/keras/issues/8909, the user mentioned that the model.summary() shows that the layer has been removed. For me, it is not the case.
Here is the code. Check it out.
import tensorflow as tf
import tensorflow.keras as keras
import tensorflow.keras.backend as K
import numpy as np
from tensorflow.keras.layers import Dense, Input, Layer
from tensorflow.keras.models import Model
input_tensor = Input(shape=(20,), name="input")
hidden = Dense(100, activation='relu')(input_tensor)
out = Dense(10, activation='relu', name="out")(hidden)
model = Model(inputs=input_tensor, outputs=out)
model.compile(loss="mse", optimizer=tf.train.AdamOptimizer(learning_rate=0.001))
model.summary()
model.layers.pop()
model.summary()
hidden = Dense(120, activation='relu')(model.layers[-1].output)
out = Dense(5, activation='softmax')(hidden)
model2 = Model(input_tensor, out)
model2.summary()
There are two issues in your code:
You can't use model.layers.pop() to remove the last layer in the model. In tf.keras, model.layers will return a shallow copy version of the layers list, so actually you don't remove that layer, just remove the layer in the return value.
If you want to remove the last dense layer and add your own one, you should use hidden = Dense(120, activation='relu')(model.layers[-2].output). model.layers[-1].output means the last layer's output which is the final output, so in your code, you actually didn't remove any layers.
Thanks.
nairouz, ymodak, wqi, cgebbe, chyld, TimbusCalin, yansun-12sigma, AFSyoung, neoantigen, CarsonSlovoka, and 40 more reacted with thumbs up emojiTimbusCalin, yansun-12sigma, AFSyoung, webstruck, GiangHLe, grofte, DrCod, and prabhat-123 reacted with heart emojiAll reactions
@yanboliang
Thank you very much for the response.
So basically, there is no need to use model.layers.pop() in this case if I understood the point.
Actually, I think the pop method implementation has changed since I have found many examples where it is used to remove a layer from a model.
You can check:
Faced the same issue.
Try popping the last layer after loading the model
vgg16_model = keras.applications.vgg16.VGG16()
vgg16_model.layers.pop()
Then, if you want to create a Sequential one just iterrate over it
model = Sequential()
for layer in vgg16_model.layers:
model.add(layer)
and then add the other layer(s) that you want
model.add(Dense(3, activation='softmax'))
That should work
oluwayetty, aktorion, usman7vt, QArtur99, haaguileraa, julydinesh, famunir, victorhcm, ghasemikasra39, vennson, and 9 more reacted with thumbs up emojiMartinThoma, cmehrshad, zxydi1992, Piyush142, y-71, locdoan12121997, maraoz, anerirana, and Thanos-DB reacted with thumbs down emojiusman7vt, yansun-12sigma, AttEela, and vennson reacted with hooray emojiAll reactions
The purpose of model.layers.pop() is to remove the last layer and fine-tune it reserving the already-trained weights. I resolved the problem simply as below.
vgg16_model = keras.applications.vgg16.VGG16()
model = Sequential()
for layer in vgg16_model.layers[:-1]: # just exclude last layer from copying
model.add(layer)
for layer in model.layers:
layer.trainable = False
model.add(Dense(2, activation='softmax'))
With model.summary(), you can confirm that the last layer of the model has been replaced.
simontamayo, mannanrehbari, extra8, vivagg007, GermanInfinity, rahul-dhrub, andresC98, rafibayer, minesh1291, jamesvrt, and 15 more reacted with thumbs up emoji5hyfilm-zz, locdoan12121997, and Thanos-DB reacted with thumbs down emojiChristineHallart, ghasemikasra39, and shuangyangwang reacted with hooray emojighassen1302, minesh1291, ghasemikasra39, shuangyangwang, amartyadash, tejas2454, GuintherKovalski, and kabyanil reacted with heart emojiGuintherKovalski reacted with rocket emojiAll reactions
I am pretty sure that the original poster was talking about tf.keras NOT Keras. Some of the responses apply to Keras NOT tf.keras. (I am just trying to get this clear for myself, don't be offended by the all caps!)
I am trying to solve the same issue. I want to remove the last layer from Inception_V3 in tf.keras. Then I want to add an additional layer for regression. I know how to do it in Keras, but not tf.keras.
If you load Inception_V3 in Keras, it shows about 300 layers. If you load it in tf.keras and print the layer summary you see something completely different.
The best way is to create a new model that ends before the last layer of that model. Using the Keras functional model.
As far as I'm aware there is no method in Keras to delete a specific layer - you need to take apart the entire model and reconstruct it yourself.
Here is an example of how to remove the last layer of a pretrained model in tf.keras (NOT keras!) and add a new output layer. This method could be used to change the number of classes for a classification problem, or to change the model to for a regression problem. The example below changes a 10 class classification model to a 2 output regression model using InceptionV3 in tf.keras.
Create InceptionV3 model, load pre-trained weights, find layer you want add on to
nb_classes = 10; # number must match your pre-trained weights
base_model =InceptionV3(include_top=True, weights=weightFile, input_shape=input_shape, classes=nb_classes)
print(base_model.summary()) # find layer in the summary that you want to add new output to
base_output = base_model.layers[311].output # layer number obtained from model summary above
attach new desired output layer to the base model to create your new model
num_regression_targets = 2 # some point (x, y)
new_output = tf.keras.layers.Dense(activation="sigmoid", units=num_regression_targets)(base_output)
new_model = tf.keras.models.Model(inputs=base_model.inputs, outputs=new_output)
print(new_model.summary())
Now the new_model is ready to use
gluque, KMint1819, kongaskristjan, mayhemsloth, and tsenst reacted with thumbs up emojiKMint1819 reacted with hooray emojiAll reactions
I re-rad my post above, and realize the explanation could be clearer. Basically, the strategy is to create a new model starting from a base model that is a standard model included in tf.keras for which you have pre-trained weights. You can find the standard models are included in tf.keras.keras.applications (tensorflow 1.13) here:
You create an instance of the base model, then look for the layer which feeds into the final fully connected layer (or other desired layer) by looking at the model summary. Then you create a new layer which takes as input the desired layer output from the base model. Finally, you define a new model in tf.keras.model.Models() by defining the inputs and outputs. Tensorflow will now have a graph of the base model with the new output layer.
@cmwolverton How does tf.keras know which layers to process? I see in your solution we are taking the base_output and providing it as input to the new Dense() layer, but the skipped InceptionV3 layers after 311 still exist in the model object, which is where layers 0-310 we are using also exist. So when model.fit() is running, does the unused layers [311:] still be receiving data and consuming CPU cycles?
Only thing which worked in my case (with TF 2.0.0) was :
model=tf.keras.models.load_model(path_model)
model.pop() # to remove last layernew_model=tf.keras.Sequential([
model,
tf.keras.layers.Dense(units=nb_classes, activation="softmax", name="new_layer_name")
new_model.build((None, height, width, 3))
guillefix, youssefelhabouz, Ahmed-Araby, HerbieHSSO, Mahmood1968, Stevens05, binalbariya, jntdst, and H-Pastry reacted with thumbs up emojiAzmisov, ngonthier, markstrefford, maraoz, and imohammadhossein reacted with thumbs down emojiMahmood1968 reacted with laugh emojiguillefix and Mahmood1968 reacted with hooray emojijntdst reacted with rocket emojiAll reactions
for me following code is a nice workaround. It builds another model without the last layer. Thus effectively being .pop()
model_reduced = Sequential()
for layer in old_model.layers[:-1]:
model_reduced.add(layer)
Previous replies mention iterating over base model and adding to a new model, which seems ok for VGG16.
For MobileNetV2 it seems to not be possible
when iterating over its layers it will raise an error when reaching an merge.Add layer
<tensorflow.python.keras.layers.merge.Add object at 0x000002BDB32D0F48>
ValueError: A merge layer should be called on a list of inputs.
I understood from previous conversation that using model.layers will bring a shallow copy from the model and using model._layers would bring the actual layers.
I observed that as @cgebbe mentioned will indeed remove the layers (at least from summary view)
I got a solution by using model._layers.pop(0)
instead of model.layers.pop(0)
I didn't found any cons of using this method, but usually messing around the private vars is not a safe thing to do if you don't know the details of the implementation. Does anybody found any problem with this method ?
Another question would be how I can properly add the mege.Add object layer to my model if I would try the iteration method.
Thanks!
Previous replies mention iterating over base model and adding to a new model, which seems ok for VGG16.
For MobileNetV2 it seems to not be possible
when iterating over its layers it will raise an error when reaching an merge.Add layer
<tensorflow.python.keras.layers.merge.Add object at 0x000002BDB32D0F48>
ValueError: A merge layer should be called on a list of inputs.
I understood from previous conversation that using model.layers will bring a shallow copy from the model and using model._layers would bring the actual layers.
I observed that as @cgebbe mentioned will indeed remove the layers (at least from summary view)
I got a solution by using model._layers.pop(0)
instead of model.layers.pop(0)
I didn't found any cons of using this method, but usually messing around the private vars is not a safe thing to do if you don't know the details of the implementation. Does anybody found any problem with this method ?
Another question would be how I can properly add the mege.Add object layer to my model if I would try the iteration method.
Thanks!
I think that's because the structure of mobilenetV2 isn't "sequential". For the method that you iterate through all the layers, you assume the model structure passes data through layer by layer. This method is available for VGG since VGG is this kind of model. Yet some model structures aren't like this, such as resnet which contains shortcuts for some data. In these kind of cases, including mobilenetV2, you have to use the functional api solution provided by @cmwolvertonhere.
pop doesn't help anything here, the correct way to do it is: