J'ai un modèle Keras qui a été formé sur 8 unités centrales. Cela signifie que le modèle a des blocs comme: with tf.device('gpu:0')
. Maintenant, je veux appliquer l'apprentissage de transfert avec un autre pc qui a 4 GPU. Cependant, cela entraîne une erreur, très probablement parce que le modèle a été formé sur plus de GPU (error: could not set cudnn tensor descriptor: CUDNN_STATUS_BAD_PARAM
). Dans le journal des erreurs, je peux également voir un avertissement que tensorflow essaie de colocaliser les dégradés sur le périphérique GPU 0-7. Y a-t-il un moyen d'adapter ou d'effacer les appareils dans un modèle formé qui est configuré avec Keras?Modifier les attributions de périphériques dans un modèle Keras formé et rechargé
Pour votre information: Je n'ai pas un fichier méta graphique, car le modèle a également été enregistré avec Keras et non avec la fonction d'économie d'tensorflow
Les tentatives actuelles
J'ai essayé pour changer les propriétés de la couche, mais cela ne l'a pas fait fonctionner:
track = 0
for i in range(len(model.layers)):
if model.layers[i].name[:6] == 'lambda':
model.layers[i].arguments['n_gpus'] = n_gpus
if model.layers[i].arguments['part'] > n_gpus-1:
model.layers[i].arguments['part'] = np.arange(n_gpus)[track]
track += 1
if track > n_gpus-1:
track = 0
En outre, j'ai essayé de définir le nombre de périphériques visibles, qui a également ne fonctionnait pas:
import os
os.environ['CUDA_VISIBLE_DEVICES'] = "0,1,2,3"
script pour créer une scission modèle sur 8 GPUs
"""
to_multi_gpu & slice_batch by: https://github.com/fchollet/keras/issues/2436
baseline_model by: http://machinelearningmastery.com/
"""
from keras import backend as K
from keras.models import Sequential, Model
from keras.layers import Dense, Input, Lambda, merge
import tensorflow as tf
def slice_batch(x, n_gpus, part):
"""
Divide the input batch into [n_gpus] slices, and obtain slice no. [part]
i.e. if len(x)=10, then slice_batch(x, 2, 1) will return x[5:].
x: input batch (input shape of model)
n_gpus: number of gpus
part: id of current gpu
return: sliced model per gpu
"""
sh = K.shape(x)
L = sh[0] // n_gpus
if part == n_gpus - 1:
return x[part*L:]
return x[part*L:(part+1)*L]
def to_multi_gpu(model, n_gpus):
"""
Given a keras [model], return an equivalent model which parallelizes
the computation over [n_gpus] GPUs.
Each GPU gets a slice of the input batch, applies the model on that slice
and later the outputs of the models are concatenated to a single
tensor, hence the user sees a model that behaves the same as the original.
model: sequential model created with the Keras library
n_gpus: number of gpus
return: model divided over n_gpus
"""
# Only divide model over multiple gpus if there is more than one
if n_gpus > 1:
with tf.device('/cpu:0'):
x = Input(model.input_shape[1:])#, name=model.input_names[0]
towers = []
# Divide model over gpus
for g in range(n_gpus):
# Work on GPU number g.
with tf.device('/gpu:' + str(g)):
# Obtain the g-th slice of the batch.
slice_g = Lambda(slice_batch, lambda shape: shape,
arguments={'n_gpus':n_gpus, 'part':g})(x)
# Apply model on the batch slice.
towers.append(model(slice_g))
# Merge multi-gpu outputs with cpu
with tf.device('/cpu:0'):
merged = merge(towers, mode='concat', concat_axis=0)
return Model(input=[x], output=merged)
else:
return model
def baseline_model(num_pixels, num_classes, n_gpus):
# create model
model = Sequential()
model.add(Dense(num_pixels, input_dim=num_pixels, init='normal', activation='relu'))
model.add(Dense(num_classes, init='normal', activation='softmax'))
model = to_multi_gpu(model, n_gpus)
# Compile model
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
if __name__ == '__main__':
model = baseline_model(784, 9, 8)