将keras模型的最后一层提取为子模型

时间:2017-10-04 19:49:42

标签: python keras

假设我们有一个卷积神经网络M.我可以使用

从图像中提取特征
ECONNREFUSED 127.0.0.1:3306

如何使用this.state.cards && this.state.cards.(your stuff) 获取预测类的模型?

我无法使用以下行,因为它需要输入模型作为占位符。

extractor = Model(M.inputs, M.get_layer('last_conv').output)
features = extractor.predict(X)

我也不能使用features因为后来我想将它作为另一个模型的一部分使用,所以我将适用于tf.tensor的预测器,而不是np.array。

3 个答案:

答案 0 :(得分:2)

这不是最好的解决方案,但它有效:

from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Dense, Dropout, Flatten

def cnn():
    model = Sequential()
    model.add(Conv2D(32, kernel_size=(3, 3),
                     activation='relu',
                     input_shape=(28, 28, 1), name='l_01'))
    model.add(Conv2D(64, (3, 3), activation='relu', name='l_02'))
    model.add(MaxPooling2D(pool_size=(2, 2), name='l_03'))
    model.add(Dropout(0.25, name='l_04'))
    model.add(Flatten(name='l_05'))
    model.add(Dense(128, activation='relu', name='l_06'))
    model.add(Dropout(0.5, name='l_07'))
    model.add(Dense(10, activation='softmax', name='l_08'))
    return model

def predictor(input_shape):
    model = Sequential()
    model.add(Flatten(name='l_05', input_shape=(12, 12, 64)))
    model.add(Dense(128, activation='relu', name='l_06'))
    model.add(Dropout(0.5, name='l_07'))
    model.add(Dense(10, activation='softmax', name='l_08'))
    return model

cnn_model = cnn()
cnn_model.save('/tmp/cnn_model.h5')

predictor_model = predictor(cnn_model.output.shape)
predictor_model.load_weights('/tmp/cnn_model.h5', by_name=True)

答案 1 :(得分:0)

这取决于你想做什么。

  • 如果您之后要丢弃特征提取器
  • 如果您打算稍后培训功能提取器

如果您打算使用提取的功能但不打算训练用于生成它们的模型,您可以使用预测方法来获取功能:

features = extractor.predict(X)

然后将其输出保存到文件(np.save或cPickle或其他)。 之后,您可以使用新数据集作为新模型的输入。

如果您计划稍后训练特征提取器,则需要将这两个网络堆叠起来,如此处所示,将vgg作为特征提取器https://github.com/fchollet/keras/issues/4576

img_width, img_height = 150, 150
vgg16_model = VGG16(include_top=False, weights='imagenet')

input = Input(batch_shape=vgg16_model.output_shape)
x = GlobalAveragePooling2D()(input)
x = Dense(256, activation='relu')(x)
x = Dropout(0.5)(x)
predict = Dense(1, activation='sigmoid')(x)
top_model = Model(input, predict)

top_model.load_weights(os.path.join(data_path, 'VGG16Classifier.hdf5'))  

input = Input(shape=(3, img_width, img_height))
x = vgg16_model(input)
predict = top_model(x)
model = Model(input, predict)

PS:此示例使用首先排序的频道。如果你使用张量流,你应该将形状更改为shape =(img_width,img_height,3)

答案 2 :(得分:0)

对模型中的每一层进行索引。因此,如果您知道需要哪些层,则可以遍历它们,然后将它们复制到新模型中。此操作也应在图层内部复制权重。

这是一个模型(根据奥利·布鲁姆的回答):

  model = Sequential()
  # add some layers
  model.add(Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=(28, 28, 1), name='l_01'))
  model.add(Conv2D(64, (3, 3), activation='relu', name='l_02'))
  model.add(MaxPooling2D(pool_size=(2, 2), name='l_03'))
  model.add(Dropout(0.25, name='l_04'))
  model.add(Flatten(name='l_05'))
  model.add(Dense(128, activation='relu', name='l_06'))
  model.add(Dropout(0.5, name='l_07'))
  model.add(Dense(10, activation='softmax', name='l_08'))

说您需要最后三层:

def extract_layers(main_model, starting_layer_ix, ending_layer_ix):
  # create an empty model
  new_model = Sequential()
  for ix in range(starting_layer_ix, ending_layer_ix + 1):
    curr_layer = main_model.get_layer(index=ix)
    # copy this layer over to the new model
    new_model.add(curr_layer)
  return extracted_layers