Re, après moultes recherches, j'ai trouvé comment résoudre le problème sans trouver une explication à ce qui allait pas. Donc pour rappel, le but était de modifier la structure de VGG19, virer la partie classifieur tout en gardant les poids initiaux du réseau entraîné sur la base imagenet. Puis d'avoir accès aux activations des différentes couches.
Voilà comment j'ai fait du coup pour implémenter :
def VGG19_bis(M, WIDTH = 1280, HEIGHT=720, CHANNELS=3):
input = keras.layers.Input(shape=(HEIGHT,WIDTH,CHANNELS),name="input_1")
x = keras.layers.Conv2D(64,(3,3),strides=(1,1),activation='relu',name="conv1_1",weights=[M.layers[1].get_weights()[0],M.layers[1].get_weights()[1]])(input)
x = keras.layers.Conv2D(64,(3,3),strides=(1,1),activation='relu',name="conv1_2",weights=[M.layers[2].get_weights()[0],M.layers[2].get_weights()[1]])(x)
x = keras.layers.AveragePooling2D(pool_size=(2,2),strides=(2,2),name="avgpool1")(x)
x = keras.layers.Conv2D(128,(3,3),strides=(1,1),activation='relu',name="conv2_1",weights=[M.layers[4].get_weights()[0],M.layers[4].get_weights()[1]])(x)
x = keras.layers.Conv2D(128,(3,3),strides=(1,1),activation='relu',name="conv2_2",weights=[M.layers[5].get_weights()[0],M.layers[5].get_weights()[1]])(x)
x = keras.layers.AveragePooling2D(pool_size=(2,2),strides=(2,2),name="avgpool2")(x)
x = keras.layers.Conv2D(256,(3,3),strides=(1,1),activation='relu',name="conv3_1",weights=[M.layers[7].get_weights()[0],M.layers[7].get_weights()[1]])(x)
x = keras.layers.Conv2D(256,(3,3),strides=(1,1),activation='relu',name="conv3_2",weights=[M.layers[8].get_weights()[0],M.layers[8].get_weights()[1]])(x)
x = keras.layers.Conv2D(256,(3,3),strides=(1,1),activation='relu',name="conv3_3",weights=[M.layers[9].get_weights()[0],M.layers[9].get_weights()[1]])(x)
x = keras.layers.Conv2D(256,(3,3),strides=(1,1),activation='relu',name="conv3_4",weights=[M.layers[10].get_weights()[0],M.layers[10].get_weights()[1]])(x)
x = keras.layers.AveragePooling2D(pool_size=(2,2),strides=(2,2),name="avgpool3")(x)
x = keras.layers.Conv2D(512,(3,3),strides=(1,1),activation='relu',name="conv4_1",weights=[M.layers[12].get_weights()[0],M.layers[12].get_weights()[1]])(x)
x = keras.layers.Conv2D(512,(3,3),strides=(1,1),activation='relu',name="conv4_2",weights=[M.layers[13].get_weights()[0],M.layers[13].get_weights()[1]])(x)
x = keras.layers.Conv2D(512,(3,3),strides=(1,1),activation='relu',name="conv4_3",weights=[M.layers[14].get_weights()[0],M.layers[14].get_weights()[1]])(x)
x = keras.layers.Conv2D(512,(3,3),strides=(1,1),activation='relu',name="conv4_4",weights=[M.layers[15].get_weights()[0],M.layers[15].get_weights()[1]])(x)
x = keras.layers.AveragePooling2D(pool_size=(2,2),strides=(2,2),name="avgpool4")(x)
x = keras.layers.Conv2D(512,(3,3),strides=(1,1),activation='relu',name="conv5_1",weights=[M.layers[17].get_weights()[0],M.layers[17].get_weights()[1]])(x)
x = keras.layers.Conv2D(512,(3,3),strides=(1,1),activation='relu',name="conv5_2",weights=[M.layers[18].get_weights()[0],M.layers[18].get_weights()[1]])(x)
x = keras.layers.Conv2D(512,(3,3),strides=(1,1),activation='relu',name="conv5_3",weights=[M.layers[19].get_weights()[0],M.layers[19].get_weights()[1]])(x)
x = keras.layers.Conv2D(512,(3,3),strides=(1,1),activation='relu',name="conv5_4",weights=[M.layers[20].get_weights()[0],M.layers[20].get_weights()[1]])(x)
M = keras.Model(inputs=input,outputs=x)
M.trainable = False
return M
En gros c'est littéralement VGG19 en remplaçant maxpool par avgpool et en ajoutant les poids + biais via weights qui prend une liste de deux élements : [poids, biais]
Pour avoir accès à l'output de n'importe quelle couche du réseau, en gros ce qu'essayais de faire via la session et les graphs :
loaded_model = VGG19_bis(tf.keras.applications.vgg19.VGG19())
extractor = keras.Model(inputs=loaded_model.input,outputs=loaded_model.get_layer("conv4_2").output)
récupérer les features :
features = extractor(data)