Nach dem Upgrade auf Keras 2.0.9 habe ich das Dienstprogramm multi_gpu_model
verwendet, aber ich kann meine Modelle oder die besten Gewichte nicht mit speichern
model.save('path')
Den Fehler bekomme ich
TypeError: Modulobjekte können nicht ausgewählt werden
Ich vermute, dass es Probleme gibt, Zugriff auf das Modellobjekt zu erhalten. Gibt es eine Arbeit um dieses Problem herum?
Um ehrlich zu sein, besteht der einfachste Ansatz darin, das parallele Multi-gpu-Modell mithilfe von zu untersuchen
parallel_model.summary()
(Das Parallelmodell ist einfach das Modell, nachdem die multi_gpu-Funktion angewendet wurde). Dies zeigt deutlich das tatsächliche Modell (in der vorletzten Schicht - ich bin momentan nicht an meinem Computer). Dann können Sie den Namen dieser Ebene verwenden, um das Modell zu speichern.
model = parallel_model.get_layer('sequential_1)
Häufig heißt es sequential_1, aber wenn Sie eine veröffentlichte Architektur verwenden, kann es sich um "googlenet" oder "alexnet" handeln. Der Name der Ebene wird in der Zusammenfassung angezeigt.
Dann ist es einfach zu speichern
model.save()
Maxims Ansatz funktioniert, aber ich denke der Overkill.
Rem: Sie müssen sowohl das Modell als auch das parallele Modell kompilieren.
Hier ist eine gepatchte Version, die beim Speichern nicht fehlschlägt:
from keras.layers import Lambda, concatenate
from keras import Model
import tensorflow as tf
def multi_gpu_model(model, gpus):
if isinstance(gpus, (list, Tuple)):
num_gpus = len(gpus)
target_gpu_ids = gpus
else:
num_gpus = gpus
target_gpu_ids = range(num_gpus)
def get_slice(data, i, parts):
shape = tf.shape(data)
batch_size = shape[:1]
input_shape = shape[1:]
step = batch_size // parts
if i == num_gpus - 1:
size = batch_size - step * i
else:
size = step
size = tf.concat([size, input_shape], axis=0)
stride = tf.concat([step, input_shape * 0], axis=0)
start = stride * i
return tf.slice(data, start, size)
all_outputs = []
for i in range(len(model.outputs)):
all_outputs.append([])
# Place a copy of the model on each GPU,
# each getting a slice of the inputs.
for i, gpu_id in enumerate(target_gpu_ids):
with tf.device('/gpu:%d' % gpu_id):
with tf.name_scope('replica_%d' % gpu_id):
inputs = []
# Retrieve a slice of the input.
for x in model.inputs:
input_shape = Tuple(x.get_shape().as_list())[1:]
slice_i = Lambda(get_slice,
output_shape=input_shape,
arguments={'i': i,
'parts': num_gpus})(x)
inputs.append(slice_i)
# Apply model on slice
# (creating a model replica on the target device).
outputs = model(inputs)
if not isinstance(outputs, list):
outputs = [outputs]
# Save the outputs for merging back together later.
for o in range(len(outputs)):
all_outputs[o].append(outputs[o])
# Merge outputs on CPU.
with tf.device('/cpu:0'):
merged = []
for name, outputs in Zip(model.output_names, all_outputs):
merged.append(concatenate(outputs,
axis=0, name=name))
return Model(model.inputs, merged)
Sie können diese multi_gpu_model
-Funktion verwenden, bis der Fehler in Keras behoben ist. Beim Laden des Modells ist es außerdem wichtig, das Tensorflow-Modulobjekt bereitzustellen:
model = load_model('multi_gpu_model.h5', {'tf': tf})
Das Problem liegt in der import tensorflow
-Zeile in der Mitte von multi_gpu_model
:
def multi_gpu_model(model, gpus):
...
import tensorflow as tf
...
Dadurch wird eine Schließung für die get_slice
-Lambda-Funktion erstellt, die die Anzahl der gpus (das ist in Ordnung) und das Tensorflow-Modul (nicht in Ordnung) enthält. Beim Speichern von Modellen wird versucht, alle Layer zu serialisieren, einschließlich derjenigen, die get_slice
aufrufen, und schlägt fehl, da tf
in der Schließung ist.
Die Lösung besteht darin, den Import aus multi_gpu_model
zu verschieben, sodass tf
ein globales Objekt wird, obwohl get_slice
noch benötigt wird. Dies behebt das Problem des Speicherns, aber beim Laden muss tf
explizit angegeben werden.
Es ist etwas, das etwas umgangen werden muss, indem das multi_gpu_model-Gewicht auf das reguläre Modellgewicht geladen wird. Z.
#1, instantiate your base model on a cpu
with tf.device("/cpu:0"):
model = create_model()
#2, put your model to multiple gpus, say 2
multi_model = multi_gpu_model(model, 2)
#3, compile both models
model.compile(loss=your_loss, optimizer=your_optimizer(lr))
multi_model.compile(loss=your_loss, optimizer=your_optimizer(lr))
#4, train the multi gpu model
# multi_model.fit() or multi_model.fit_generator()
#5, save weights
model.set_weights(multi_model.get_weights())
model.save(filepath=filepath)
`
auffrischung: https://github.com/fchollet/keras/issues/8123