Keras VGG16 fine tuning

前端 未结 3 804
时光说笑
时光说笑 2021-01-18 01:19

There is an example of VGG16 fine-tuning on keras blog, but I can\'t reproduce it.

More precisely, here is code used to init VGG16 without top layer and to freeze a

相关标签:
3条回答
  • 2021-01-18 02:04

    I think you can concatenate both by doing something like this:

    #load vgg model
    vgg_model = applications.VGG16(weights='imagenet', include_top=False, input_shape=(150, 150, 3))
    print('Model loaded.')
    
    #initialise top model
    top_model = Sequential()
    top_model.add(Flatten(input_shape=vgg_model.output_shape[1:]))
    top_model.add(Dense(256, activation='relu'))
    top_model.add(Dropout(0.5))
    top_model.add(Dense(1, activation='sigmoid'))
    
    
    top_model.load_weights(top_model_weights_path)
    
    # add the model on top of the convolutional base
    
    model = Model(input= vgg_model.input, output= top_model(vgg_model.output))
    

    This solution refers to the example Fine-tuning the top layers of a a pre-trained network. Full code can be found here.

    0 讨论(0)
  • 2021-01-18 02:13

    I think that the weights described by the vgg net do not fit your model and the error stems from this. Anyways there is a way better way to do this using the network itself as described in (https://keras.io/applications/#vgg16).

    You can just use:

    base_model = keras.applications.vgg16.VGG16(include_top=False, weights='imagenet', input_tensor=None, input_shape=None)
    

    to instantiate a vgg net that is pre-trained. Then you can freeze the layers and use the model class to instantiate your own model like this:

    x = base_model.output
    x = Flatten()(x)
    x = Dense(your_classes, activation='softmax')(x) #minor edit
    new_model = Model(input=base_model.input, output=x)
    

    To combine the bottom and the top network you can use the following code snippet. The following functions are used (Input Layer (https://keras.io/getting-started/functional-api-guide/) / load_model (https://keras.io/getting-started/faq/#how-can-i-save-a-keras-model) and the functional API of keras):

    final_input = Input(shape=(3, 224, 224))
    base_model = vgg...
    top_model = load_model(weights_file)
    
    x = base_model(final_input)
    result = top_model(x)
    final_model = Model(input=final_input, output=result)
    
    0 讨论(0)
  • 2021-01-18 02:15

    Ok, I guess Thomas and Gowtham posted correct (and more concise answers), but I wanted to share the code, which I was able to run successfully:

    def train_finetuned_model(lr=1e-5, verbose=True):
        file_path = get_file('vgg16.h5', VGG16_WEIGHTS_PATH, cache_subdir='models')
        if verbose:
            print('Building VGG16 (no-top) model to generate bottleneck features.')
    
        vgg16_notop = build_vgg_16()
        vgg16_notop.load_weights(file_path)
        for _ in range(6):
            vgg16_notop.pop()
        vgg16_notop.compile(optimizer=RMSprop(lr=lr), loss='categorical_crossentropy', metrics=['accuracy'])    
    
        if verbose:
            print('Bottleneck features generation.')
    
        train_batches = get_batches('train', shuffle=False, class_mode=None, batch_size=BATCH_SIZE)
        train_labels = np.array([0]*1000 + [1]*1000)
        train_bottleneck = vgg16_notop.predict_generator(train_batches, steps=2000 // BATCH_SIZE)
        valid_batches = get_batches('valid', shuffle=False, class_mode=None, batch_size=BATCH_SIZE)
        valid_labels = np.array([0]*400 + [1]*400)
        valid_bottleneck = vgg16_notop.predict_generator(valid_batches, steps=800 // BATCH_SIZE)
    
        if verbose:
            print('Training top model on bottleneck features.')
    
        top_model = Sequential()
        top_model.add(Flatten(input_shape=train_bottleneck.shape[1:]))
        top_model.add(Dense(4096, activation='relu'))
        top_model.add(Dropout(0.5))
        top_model.add(Dense(4096, activation='relu'))
        top_model.add(Dropout(0.5))
        top_model.add(Dense(2, activation='softmax'))
        top_model.compile(optimizer=RMSprop(lr=lr), loss='categorical_crossentropy', metrics=['accuracy'])
        top_model.fit(train_bottleneck, to_categorical(train_labels),
                      batch_size=32, epochs=10,
                      validation_data=(valid_bottleneck, to_categorical(valid_labels)))
    
        if verbose:
            print('Concatenate new VGG16 (without top layer) with pretrained top model.')
    
        vgg16_fine = build_vgg_16()
        vgg16_fine.load_weights(file_path)
        for _ in range(6):
            vgg16_fine.pop()
        vgg16_fine.add(Flatten(name='top_flatten'))    
        vgg16_fine.add(Dense(4096, activation='relu'))
        vgg16_fine.add(Dropout(0.5))
        vgg16_fine.add(Dense(4096, activation='relu'))
        vgg16_fine.add(Dropout(0.5))
        vgg16_fine.add(Dense(2, activation='softmax'))
        vgg16_fine.compile(optimizer=RMSprop(lr=lr), loss='categorical_crossentropy', metrics=['accuracy'])
    
        if verbose:
            print('Loading pre-trained weights into concatenated model')
    
        for i, layer in enumerate(reversed(top_model.layers), 1):
            pretrained_weights = layer.get_weights()
            vgg16_fine.layers[-i].set_weights(pretrained_weights)
    
        for layer in vgg16_fine.layers[:26]:
            layer.trainable = False
    
        if verbose:
            print('Layers training status:')
            for layer in vgg16_fine.layers:
                print('[%6s] %s' % ('' if layer.trainable else 'FROZEN', layer.name))        
    
        vgg16_fine.compile(optimizer=RMSprop(lr=1e-6), loss='binary_crossentropy', metrics=['accuracy'])
    
        if verbose:
            print('Train concatenated model on dogs/cats dataset sample.')
    
        train_datagen = ImageDataGenerator(rescale=1./255,
                                           shear_range=0.2,
                                           zoom_range=0.2,
                                           horizontal_flip=True)
        test_datagen = ImageDataGenerator(rescale=1./255)
        train_batches = get_batches('train', gen=train_datagen, class_mode='categorical', batch_size=BATCH_SIZE)
        valid_batches = get_batches('valid', gen=test_datagen, class_mode='categorical', batch_size=BATCH_SIZE)
        vgg16_fine.fit_generator(train_batches, epochs=100,
                                 steps_per_epoch=2000 // BATCH_SIZE,
                                 validation_data=valid_batches,
                                 validation_steps=800 // BATCH_SIZE)
        return vgg16_fine 
    

    It is kind of too verbose and makes all things manually (i.e. copies weights from pre-trained layers to concatenated model), but it works, more or less.

    Though this code I've posted has a problem with low accuracy (around 70%), but that is a different story.

    0 讨论(0)
提交回复
热议问题