在keras中微调预训练模型 [英] Fine tuning pretrained model in keras

查看:89
本文介绍了在keras中微调预训练模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在keras中使用预训练的imagenet VGG16模型,并在顶部添加我自己的小型convnet.我只对功能感兴趣,对预测不感兴趣

I want to use a pretrained imagenet VGG16 model in keras and add my own small convnet on top. I am only interested in the features, not the predictions

from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img
from keras.applications.vgg16 import VGG16
from keras.preprocessing import image
from keras.applications.vgg16 import preprocess_input
import numpy as np
import os
from keras.models import Model
from keras.models import Sequential
from keras.layers import Convolution2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense

从目录加载图像(该目录包含4张图像)

load images from directory (the dir contains 4 images)

IF = '/home/ubu/files/png/'
files = os.listdir(IF)

imgs = [img_to_array(load_img(IF + p, target_size=[224,224])) for p in files]
im = np.array(imgs)

加载基本模型,预处理输入并获取特征

load the base model, preprocess input and get the features

base_model = VGG16(weights='imagenet', include_top=False)

x = preprocess_input(aa)
features = base_model.predict(x)

这行得通,我在预先训练的VGG上获得了图像的功能.

this works, and I get the features for my images on the pretrained VGG.

我现在想微调模型并添加一些卷积层. 我阅读了 https://blog.keras .io/building-powerful-image-classification-models-using-very-little-data.html > ://keras.io/applications/,但不能完全将它们组合在一起.

I now want to finetune the model and add some convolutional layers. I read https://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html and https://keras.io/applications/ but cannot quite bring them together.

在顶部添加我的模型:

x = base_model.output
x = Convolution2D(32, 3, 3)(x)
x = Activation('relu')(x)
x = MaxPooling2D(pool_size=(2, 2))(x)
x = Convolution2D(32, 3, 3)(x)
x = Activation('relu')(x)
feat = MaxPooling2D(pool_size=(2, 2))(x)

建立完整的模型

model_complete = Model(input=base_model.input, output=feat)

阻止基础层的学习

for layer in base_model.layers:
layer.trainable = False

新型号

model_complete.compile(optimizer='rmsprop', 
          loss='binary_crossentropy')

现在适合新模型,该模型是4张图像,[1,0,1,0]是类别标签. 但这显然是错误的:

now fit the new model, the model is 4 images and [1,0,1,0] are the class labels. But this is obviously wrong:

model_complete.fit_generator((x, [1,0,1,0]), samples_per_epoch=100, nb_epoch=2)

ValueError: output of generator should be a tuple (x, y, sample_weight) or (x, y). Found: None

这是怎么做的?

如果我只想替换最后的卷积块(VGG16中的conv block5)而不添加内容,该怎么办?

How would I do it if I only wanted to replace the last convolutional block (conv block5 in VGG16) instead of adding something?

我将只训练瓶颈功能吗?

How would I only train the bottleneck features?

特征输出features具有形状(4、512、7、7).有四个图像,但其他维度是什么?如何将其简化为(1,x)数组?

The features output features has shape (4, 512, 7, 7). There are four images, but what is in the other dimensions? How would I reduce that to a (1,x) array?

推荐答案

拟合模型

生成器代码的问题是fit_generator方法期望生成器函数生成您不提供的适合拟合的数据. 您可以按照已链接的教程中的定义定义一个生成器,也可以自己创建数据和标签并自己适合模型:

The problem with your generator code is that the fit_generator method expects a generator function to generate the data for fitting which you don't provide. You can either define a generator as done in the tutorial that you have linked to or create the data and labels yourself and fit your model yourself:

model_complete.fit(images, labels, batch_size=100, nb_epoch=2)

其中图像是您生成的训练图像,标签是相应的标签.

where images are your generated training images and labels are the corresponding labels.

删除最后一层

假设您有一个模型变量和下面介绍的"pop"方法,则可以执行model = pop(model)删除最后一层.

Assuming you have a model variable and the "pop" method described below, you can do model = pop(model) to remove the last layer.

仅训练特定图层 正如您在代码中所做的一样,您可以执行以下操作:

Training only specific layers As you have done in your code, you can do:

for layer in base_model.layers:
    layer.trainable = False

然后,您可以通过将其trainable属性更改为True来解冻"所需的图层.

Then you can "unfreeze" and layer that you want by changing their trainable property to True.

更改尺寸

要将输出更改为一维数组,可以使用 Flatten layer

To change the output to a 1D array you can use the Flatten layer

弹出方法

The pop method

def pop(model):
    '''Removes a layer instance on top of the layer stack.
    This code is thanks to @joelthchao https://github.com/fchollet/keras/issues/2371#issuecomment-211734276
    '''
    if not model.outputs:
        raise Exception('Sequential model cannot be popped: model is empty.')
    else:
        model.layers.pop()
        if not model.layers:
            model.outputs = []
            model.inbound_nodes = []
            model.outbound_nodes = []
        else:
            model.layers[-1].outbound_nodes = []
            model.outputs = [model.layers[-1].output]
        model.built = False

    return model

这篇关于在keras中微调预训练模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆