Was ich versuche:
ich alle Schichten aus verschiedenen Modellen verbinden möge ein neues keras Modell zu erstellen.Keras: Verbinden von zwei Schichten aus verschiedenen Modellen zu schaffen neues Modell
Was ich bisher gefunden:
https://github.com/keras-team/keras/issues/4205: mit Hilfe des Modells Ruf Klasse, um die Eingabe eines anderen Modells zu ändern. Meine Probleme mit diesem Ansatz:
- Kann nur den Eingang des Modells ändern, keine anderen Schichten. Also, wenn ich einige Schichten am Anfang des Encoders abschneiden möchte, ist das nicht möglich
- Kein Fan der verschachtelten Array-Struktur beim Abrufen der Konfigurationsdatei. Möchte ein 1D-Array haben
Bei Verwendung von model.summary() oder plot_model() wird der Encoder nur als "Modell" angezeigt. Wenn überhaupt, würde ich sagen, beide Modelle sollten verpackt werden. So sollte die config [model_base, model_encoder] zeigt und nicht [base_input, base_conv2D, ..., encoder_model]
Um fair zu sein, mit diesem Ansatz: https://github.com/keras-team/keras/issues/3021, oberhalb der Punkt ist tatsächlich möglich, aber auch hier ist es sehr unflexibel. Sobald ich einige Schichten auf der Ober- oder Unterseite des Bodens oder Encoder Netzwerk abgeschnitten werden, scheitert dieser Ansatz
https://github.com/keras-team/keras/issues/3465: neue Schichten auf ein Basismodell Hinzufügen von beliebigen Ausgang des Basismodells. Probleme hier:
Was habe ich versucht:
Mein Ansatz alle Schichten aus verschiedenen Modellen zu verbinden:
- löschen Inbound-Knoten Eingangsschicht
- den Anruf() -Methode der Ausgangsschicht mit dem Tensor der Ausgabeschicht
- Bereinigen Sie die Ausgangsknoten des Ausgangstensors, indem Sie den neu angelegten Tensor mit dem vorherigen Ausgangstensor ausschaltet
Ich war zuerst wirklich optimistisch, als die summary()
und die plot_model()
mich genau bekommen haben, was ich wollte, also sollte das Node-Diagramm in Ordnung sein, oder? Aber ich habe beim Training Fehler bekommen. Während der Ansatz in dem Abschnitt "Was ich bisher gefunden habe" gut trainiert war, stieß ich bei meinem Ansatz auf einen Fehler. Dies ist die Fehlermeldung:
Könnte eine wichtige Information sein, dass ich Tensorflow als Backend verwende. Ich konnte die Wurzel dieses Fehlers zurückverfolgen. Es scheint, als ob ein Fehler vorliegt, wenn die Gradienten berechnet werden. Normalerweise gibt es für jeden Knoten eine Gradientenberechnung, aber alle Knoten des Basisnetzwerks haben "None", wenn Sie meinen Ansatz verwenden. Also grundsätzlich in keras/optimizers.py, get_updates()
, wenn die Gradienten berechnet werden (grad = self.get_gradients(loss, params)
).Hier
ist der Code (ohne Ausbildung), mit allen drei Ansätzen umgesetzt:
def create_base():
in_layer = Input(shape=(32, 32, 3), name="base_input")
x = Conv2D(32, (3, 3), padding='same', activation="relu", name="base_conv2d_1")(in_layer)
x = Conv2D(32, (3, 3), padding='same', activation="relu", name="base_conv2d_2")(x)
x = MaxPooling2D(pool_size=(2, 2), name="base_maxpooling_2d_1")(x)
x = Dropout(0.25, name="base_dropout")(x)
x = Conv2D(64, (3, 3), padding='same', activation="relu", name="base_conv2d_3")(x)
x = Conv2D(64, (3, 3), padding='same', activation="relu", name="base_conv2d_4")(x)
x = MaxPooling2D(pool_size=(2, 2), name="base_maxpooling2d_2")(x)
x = Dropout(0.25, name="base_dropout_2")(x)
return Model(inputs=in_layer, outputs=x, name="base_model")
def create_encoder():
in_layer = Input(shape=(8, 8, 64))
x = Flatten(name="encoder_flatten")(in_layer)
x = Dense(512, activation="relu", name="encoder_dense_1")(x)
x = Dropout(0.5, name="encoder_dropout_2")(x)
x = Dense(10, activation="softmax", name="encoder_dense_2")(x)
return Model(inputs=in_layer, outputs=x, name="encoder_model")
def extend_base(input_model):
x = Flatten(name="custom_flatten")(input_model.output)
x = Dense(512, activation="relu", name="custom_dense_1")(x)
x = Dropout(0.5, name="custom_dropout_2")(x)
x = Dense(10, activation="softmax", name="custom_dense_2")(x)
return Model(inputs=input_model.input, outputs=x, name="custom_edit")
def connect_layers(from_tensor, to_layer, clear_inbound_nodes=True):
try:
tmp_output = to_layer.output
except AttributeError:
raise ValueError("Connecting to shared layers is not supported!")
if clear_inbound_nodes:
to_layer.inbound_nodes = []
else:
tensor_list = to_layer.inbound_nodes[0].input_tensors
tensor_list.append(from_tensor)
from_tensor = tensor_list
to_layer.inbound_nodes = []
new_output = to_layer(from_tensor)
for out_node in to_layer.outbound_nodes:
for i, in_tensor in enumerate(out_node.input_tensors):
if in_tensor == tmp_output:
out_node.input_tensors[i] = new_output
if __name__ == "__main__":
base = create_base()
encoder = create_encoder()
#new_model_1 = Model(inputs=base.input, outputs=encoder(base.output))
#plot_model(new_model_1, to_file="plots/new_model_1.png")
new_model_2 = extend_base(base)
plot_model(new_model_2, to_file="plots/new_model_2.png")
print(new_model_2.summary())
base_layer = base.get_layer("base_dropout_2")
top_layer = encoder.get_layer("encoder_flatten")
connect_layers(base_layer.output, top_layer)
new_model_3 = Model(inputs=base.input, outputs=encoder.output)
plot_model(new_model_3, to_file="plots/new_model_3.png")
print(new_model_3.summary())
Ich weiß, das viel Text ist und eine Menge Code. Aber ich glaube, dass es notwendig ist, das Problem hier zu erklären.
EDIT: Ich habe gerade versucht thenao und ich denke, der Fehler mehr Informationen verschenkt:
theano.gradient.DisconnectedInputError:
Backtrace when that variable is created:
Es scheint wie jede Schicht aus dem Encoder Modell über TensorVariables eine Verbindung mit der Encoder-Eingang Schicht aufweist.