添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

System information

  • 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()
    
    _________________________________________________________________
    Layer (type)                 Output Shape              Param #   
    =================================================================
    input_1 (InputLayer)         (None, 10)                0         
    _________________________________________________________________
    dense (Dense)                (None, 100)               1100      
    _________________________________________________________________
    dense_1 (Dense)              (None, 10)                1010      
    =================================================================
    Total params: 2,110
    Trainable params: 2,110
    Non-trainable params: 0
    
    _________________________________________________________________
    _________________________________________________________________
    Layer (type)                 Output Shape              Param #   
    =================================================================
    input_1 (InputLayer)         (None, 10)                0         
    _________________________________________________________________
    dense (Dense)                (None, 100)               1100      
    _________________________________________________________________
    dense_1 (Dense)              (None, 10)                1010      
    =================================================================
    Total params: 2,110
    Trainable params: 2,110
    Non-trainable params: 0
    
    _________________________________________________________________
    _________________________________________________________________
    Layer (type)                 Output Shape              Param #   
    =================================================================
    input_1 (InputLayer)         (None, 10)                0         
    _________________________________________________________________
    dense (Dense)                (None, 100)               1100      
    _________________________________________________________________
    dense_1 (Dense)              (None, 10)                1010      
    _________________________________________________________________
    dense_2 (Dense)              (None, 120)               1320      
    _________________________________________________________________
    dense_3 (Dense)              (None, 5)                 605       
    =================================================================
    Total params: 4,035
    Trainable params: 4,035
    Non-trainable params: 0
    _________________________________________________________________
              

    @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 emoji TimbusCalin, yansun-12sigma, AFSyoung, webstruck, GiangHLe, grofte, DrCod, and prabhat-123 reacted with heart emoji All 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:

  • https://stackoverflow.com/questions/41668813/how-to-add-and-remove-new-layers-in-keras-after-loading-weights
  • Removing layers from model gives the same output as original model keras-team/keras#8909
  • 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 emoji MartinThoma, cmehrshad, zxydi1992, Piyush142, y-71, locdoan12121997, maraoz, anerirana, and Thanos-DB reacted with thumbs down emoji usman7vt, yansun-12sigma, AttEela, and vennson reacted with hooray emoji All 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 emoji 5hyfilm-zz, locdoan12121997, and Thanos-DB reacted with thumbs down emoji ChristineHallart, ghasemikasra39, and shuangyangwang reacted with hooray emoji ghassen1302, minesh1291, ghasemikasra39, shuangyangwang, amartyadash, tejas2454, GuintherKovalski, and kabyanil reacted with heart emoji GuintherKovalski reacted with rocket emoji All 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.

    Layer (type) Output Shape Param # Connected to

    input_1 (InputLayer) (None, 256, 256, 1) 0

    lambda (Lambda) (None, 256, 256, 1) 0 input_1[0][0]

    lambda_1 (Lambda) (None, 256, 256, 1) 0 input_1[0][0]

    inception_v3 (Model) (None, 11) 21824747 lambda[0][0]
    lambda_1[0][0]

    predictions (Concatenate) (None, 11) 0 inception_v3[1][0]
    inception_v3[2][0]

    Total params: 21,824,747
    Trainable params: 21,790,315
    Non-trainable params: 34,432

    QArtur99, fanlyu, alekseisolovev, joaofbsm, a-arbabian, saptarc, jonathan5p, Woodyet, tomaspiaggio, ismael-elatifi, and 38 more reacted with thumbs up emoji KirylBelasheuski, jamescook106, peachthiefmedia, myaadvishal, Mahmood1968, rsun-bdti, francotheengineer, anerirana, HoseinHashemi, eliandrew, and alkatar21 reacted with thumbs down emoji mightyroy, anubhav1, ufuk23, and PhanThanhTrung reacted with laugh emoji Harirai, bowtiejicode, teopapad92, menmartey, Amitabha101, mightyroy, a-taherkhani, SirNader, and anubhav1 reacted with heart emoji QArtur99, michalheker, joaofbsm, jonathan5p, mahdip72, juroberttyb, menmartey, Iolop, Amitabha101, a-taherkhani, and 4 more reacted with rocket emoji All reactions

    @jamescook106

    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 emoji KMint1819 reacted with hooray emoji All 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:

    https://github.com/keras-team/keras-applications

    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 layer
    new_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 emoji Azmisov, ngonthier, markstrefford, maraoz, and imohammadhossein reacted with thumbs down emoji Mahmood1968 reacted with laugh emoji guillefix and Mahmood1968 reacted with hooray emoji jntdst reacted with rocket emoji All 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 @cmwolverton here.

    pop doesn't help anything here, the correct way to do it is:

    model2 = Model(model.input, model.layers[-2].output)
    

    Tested this only for a non-sequential model.