在keras中微调预训练模型

spo*_*234 5 python deep-learning keras

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

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
Run Code Online (Sandbox Code Playgroud)

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

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)
Run Code Online (Sandbox Code Playgroud)

加载基础模型,预处理输入并获取功能

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

x = preprocess_input(aa)
features = base_model.predict(x)
Run Code Online (Sandbox Code Playgroud)

这是有效的,我在预训练的VGG上获得了我的图像功能.

我现在想要微调模型并添加一些卷积层.我阅读了https://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.htmlhttps://keras.io/applications/,但无法将它们整合在一起.

在顶部添加我的模型:

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)
Run Code Online (Sandbox Code Playgroud)

建立完整的模型

model_complete = Model(input=base_model.input, output=feat)
Run Code Online (Sandbox Code Playgroud)

停止学习基础层

for layer in base_model.layers:
layer.trainable = False
Run Code Online (Sandbox Code Playgroud)

新模式

model_complete.compile(optimizer='rmsprop', 
          loss='binary_crossentropy')
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

这是怎么做到的?

如果我只想替换最后一个卷积块(VGG16中的conv block5)而不是添加某些东西,我该怎么办呢?

我怎么只训练瓶颈功能?

功能输出features具有形状(4,512,7,7).有四个图像,但其他维度是什么?我如何将其减少为(1,x)数组?

gin*_*nge 7

拟合模型

生成器代码的问题在于fit_generator方法需要生成器函数生成适合您未提供的数据.您可以在已链接到的教程中定义生成器,也可以自己创建数据和标签,并自己适合您的模型:

model_complete.fit(images, labels, batch_size=100, nb_epoch=2)
Run Code Online (Sandbox Code Playgroud)

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

删除最后一层

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

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

for layer in base_model.layers:
    layer.trainable = False
Run Code Online (Sandbox Code Playgroud)

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

改变尺寸

要将输出更改为1D阵列,可以使用"展平"图层


流行方法

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
Run Code Online (Sandbox Code Playgroud)