Dieser Beitrag scheint darauf hinzudeuten, dass das, was ich erreichen möchte, nicht möglich ist. Davon bin ich jedoch nicht überzeugt - angesichts dessen, was ich bereits getan habe, verstehe ich nicht, warum das, was ich tun möchte, nicht erreicht werden kann ...
Ich habe zwei Bilddatensätze, von denen einer Bilder mit Form (480, 720, 3) und der andere Bilder mit Form (540, 960, 3) enthält.
Ich habe ein Modell mit dem folgenden Code initialisiert:
input = Input(shape=(480, 720, 3), name='image_input')
initial_model = VGG16(weights='imagenet', include_top=False)
for layer in initial_model.layers:
layer.trainable = False
x = Flatten()(initial_model(input))
x = Dense(1000, activation='relu')(x)
x = BatchNormalization()(x)
x = Dropout(0.5)(x)
x = Dense(1000, activation='relu')(x)
x = BatchNormalization()(x)
x = Dropout(0.5)(x)
x = Dense(14, activation='linear')(x)
model = Model(inputs=input, outputs=x)
model.compile(loss='mse', optimizer='adam', metrics=['mae'])
Nachdem ich dieses Modell für das vorherige Dataset trainiert habe, möchte ich die Eingabe-Tensor-Ebene entfernen und dem Modell einen neuen Eingabe-Tensor voranstellen, dessen Form mit den Bildabmessungen des letzten Datasets übereinstimmt.
model = load_model('path/to/my/trained/model.h5')
old_input = model.pop(0)
new_input = Input(shape=(540, 960, 3), name='image_input')
x = model(new_input)
m = Model(inputs=new_input, outputs=x)
m.save('transfer_model.h5')
was diesen Fehler ergibt:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/aicg2/.local/lib/python2.7/site-packages/keras/engine/topology.py", line 2506, in save
save_model(self, filepath, overwrite, include_optimizer)
File "/home/aicg2/.local/lib/python2.7/site-packages/keras/models.py", line 106, in save_model
'config': model.get_config()
File "/home/aicg2/.local/lib/python2.7/site-packages/keras/engine/topology.py", line 2322, in get_config
layer_config = layer.get_config()
File "/home/aicg2/.local/lib/python2.7/site-packages/keras/engine/topology.py", line 2370, in get_config
new_node_index = node_conversion_map[node_key]
KeyError: u'image_input_ib-0'
In dem von mir verknüpften Beitrag gibt maz an, dass es eine Dimensionsinkongruenz gibt, die verhindert, dass die Eingabeebene eines Modells geändert wird. Wenn dies der Fall ist, wie setze ich dann eine Eingabeebene (480, 720, 3) voran des VGG16-Modells, das (224, 224, 3) Bilder erwartet?
Ich denke, ein wahrscheinlicheres Problem ist, dass die Ausgabe meines früheren Modells etwas anderes erwartet als das, was ich basierend auf dem, was fchollet in diesem Beitrag sagt, gebe . Ich bin syntaktisch verwirrt, aber ich glaube, das gesamte x = Layer()(x)
Segment baut die Ebene Stück für Stück aus Eingabe-> Ausgabe auf, und wenn Sie einfach eine andere Eingabe voranstellen, wird sie unterbrochen.
Ich habe aber wirklich keine Ahnung ...
Kann mir jemand bitte erklären, wie ich das erreichen kann, was ich versuche, oder, wenn es nicht möglich ist, mir erklären, warum nicht?
Antworten:
Sie können dies tun, indem Sie eine neue VGG16-Modellinstanz mit der neuen Eingabeform erstellen
new_shape
und alle Ebenengewichte kopieren. Der Code ist ungefährquelle
Traceback (most recent call last): File "predict_video11.py", line 67, in <module> new_layer.set_weights(layer.get_weights()) File "/usr/local/lib/python2.7/dist-packages/keras/engine/base_layer.py", line 1057, in set_weights 'provided weight shape ' + str(w.shape)) ValueError: Layer weight shape (3, 3, 33, 64) not compatible with provided weight shape (3, 3, 9, 64)
und das ist die Eingabeebene, die so verwendet wird[2:]
?Die Ausgabebreite und -höhe der Ausgabedimensionen von VGGnet ist ein fester Teil der Eingabebreite und -höhe, da die einzigen Ebenen, die diese Dimensionen ändern, die Poolebenen sind. Die Anzahl der Kanäle in der Ausgabe ist auf die Anzahl der Filter in der letzten Faltungsschicht festgelegt. Die Abflachungsebene wird dies umformen, um eine Dimension mit der Form zu erhalten:
((input_width * x) * (input_height * x) * channels)
Dabei ist x eine Dezimalzahl <1.
Der Hauptpunkt ist, dass die Form der Eingabe für die dichten Ebenen von der Breite und Höhe der Eingabe für das gesamte Modell abhängt. Die in die dichte Schicht eingegebene Form kann sich nicht ändern, da dies das Hinzufügen oder Entfernen von Knoten zum neuronalen Netzwerk bedeuten würde.
Eine Möglichkeit, dies zu vermeiden, besteht darin, eine globale Poolebene anstelle einer flachen Ebene (normalerweise GlobalAveragePooling2D) zu verwenden. Auf diese Weise wird der Durchschnitt pro Kanal ermittelt, wodurch die Form der Eingabe in die dichten Ebenen nur so
(channels,)
ist, dass sie nicht von der Eingabeform abhängt das ganze Modell.Sobald dies erledigt ist, hängt keine der Ebenen im Netzwerk von der Breite und Höhe der Eingabe ab, sodass die Eingabeebene mit so etwas wie geändert werden kann
quelle
Hier ist eine andere Lösung, die nicht spezifisch für das VGG-Modell ist.
Beachten Sie, dass die Gewichte der dichten Ebene nicht kopiert werden können (und daher neu initialisiert werden). Dies ist sinnvoll, da die Form der Gewichte beim alten und beim neuen Modell unterschiedlich ist.
quelle
Dies sollte mit ziemlich einfach sein
kerassurgeon
. Zuerst müssen Sie die Bibliothek installieren. Je nachdem, ob Sie Keras über TensorFlow (mit tf 2.0 und höher) oder Keras als separate Bibliothek verwenden, muss Keras auf unterschiedliche Weise installiert werden.Für Keras in TF:
pip install tfkerassurgeon
( https://github.com/Raukk/tf-keras-surgeon ). Für eigenständige Keras:pip install kerassurgeon
( https://github.com/BenWhetton/keras-surgeon )So ersetzen Sie die Eingabe (Beispiel mit TF 2.0; derzeit nicht getesteter Code):
quelle
@gebbissimo answer hat bei mir in TF2 mit nur kleinen Anpassungen funktioniert, die ich unten in einer einzigen Funktion teile:
quelle
So ändere ich die Eingabegröße im Keras-Modell. Ich habe zwei CNN-Modelle, eines mit der Eingabegröße [None, None, 3], während das andere die Eingabegröße [512,512,3] hat. Beide Modelle haben das gleiche Gewicht. Mit set_weights (model.get_weights ()) können Gewichte von Modell 1 auf Modell 2 übertragen werden
quelle