[英]Extracting last layers of keras model as a submodel
假設我們有一個卷積神經網絡 M。我可以通過使用從圖像中提取特征
extractor = Model(M.inputs, M.get_layer('last_conv').output)
features = extractor.predict(X)
如何獲得將使用features
預測類別的模型?
我不能使用以下幾行,因為它需要模型的輸入作為占位符。
predictor = Model([M.get_layer('next_layer').input], M.outputs)
pred = predictor.predict(features)
我也不能使用K.function
因為稍后我想將它用作另一個模型的一部分,所以我會將預測器應用於 tf.tensor,而不是 np.array。
這不是最好的解決方案,但它有效:
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)
模型中的每一層都有索引。 因此,如果您知道需要哪些層,就可以遍歷它們,將它們復制到新模型中。 此操作也應復制層內的權重。
這是一個模型(來自 Oli Blum 的回答):
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 new_model
這取決於你想做什么。
如果您打算使用提取的特征,但不打算訓練用於生成它們的模型,則可以使用 predict 方法來獲取特征:
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:此示例使用通道優先排序。 如果您使用 tensorflow,則應將形狀更改為 shape=(img_width, img_height,3 )
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.