2017-10-04 249 views
1

說我們有一個卷積神經網絡M.我可以用提取keras模型的最後一層爲子模型

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因爲後來我想用它作爲另一個模型的一部分,所以我會appliyng預測到tf.tensor,不np.array。

+0

什麼是使用一個佔位符的問題或一個輸入層?這是正確的方法。 –

+1

@MatiasValdenegro如何在新的輸入層之上堆疊**訓練好的**預測器圖層? – eclique

+0

使用功能性API,您只需使用您的模型,因爲它是一個圖層:in = Input(...)inter = yourModel(in)final = Dense(10)(inter) –

回答

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) 
+0

是....到目前爲止,這是我發現的唯一解決方案,重新創建模型的相關部分。 –

+0

是的,我也採取了重建預測器和加載重量。'by_name'是有用的,但我認爲這應該是一個更清潔解決方案,如果我們不盡快提出更好的答案,我會接受答案。 – eclique

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:此示例使用渠道第一順序。如果你正在使用tensorflow你應該改變形狀塑造=(img_width,IMG_HEIGHT,3)

+0

我想我可以在你提供的代碼中看到解決方案。我將可以在稍後測試它。 但主要問題是在預測器,而不是提取器。你的意思是預測嗎? 我會扔掉提取器,只會在預測器中使用固定的權重(未經過培訓)。 – eclique

+0

如果您要扔掉提取器,這很簡單,只需從模型中獲取輸出數據即可。當我說「預測」時,我的意思是使用extractor.predict來獲得它的輸出。在這個輸出結束後,您基本上會使用新的數據集。使用keras/tensorflow構建符號模型,並以模型的擬合方法傳遞數據,就好像它是具有映射向量的任何其他數據集一樣 - >標籤 – maz

+1

我將extractor.predict(X)的要素與任何其他數據一起加載。問題是獲得預測器**部分的**符號模型與訓練後的權重。不幸的是,你的回答並不能解決這個問題。 :( – eclique