entrenamiento multi-GPU de tensorflow 1.14 keras

Aunque ya estamos en 2021, un trabajo reciente debe usar tf1.14 para entrenar y generar un modelo. Escribir tf puro es un poco complicado, así que usé tf.keras para hacerlo. Aquí hay algunos problemas encontrados por tf.keras en tf1 .14., especialmente entrenamiento multi-GPU

from tensorflow.keras.utils import multi_gpu_model

gpu_list = '0,1,2,3,4,5'
os.environ['CUDA_VISIBLE_DEVICES']=gpu_list #指定哪几块GPU
gpu_num = len(gpu_list.split(','))
single_model = build_model()
single_model.load_weights(path, by_name=True)
model=multi_gpu_model(single_model, gpus=gpu_num)

Primero especifique el número de serie de la GPU, cree el modelo, cargue los pesos previos al entrenamiento y llame a multi_gpu_model para generar un modelo de entrenamiento de múltiples GPU.

Asegúrese de cargar los pesos primero, porque el modelo después de llamar a multi_gpu_model ha cambiado sus nombres de variables internas y no se puede cargar.

 

Guardar resultados de entrenamiento intermedios

ModelCheckpoint no se puede utilizar directamente. Revisé algunos blogs y la mayoría de la gente dijo que se deriva de la siguiente manera:

class ParallelModelCheckpoint(ModelCheckpoint):
    def __init__(self,model,filepath, monitor='val_loss', verbose=0,
                 save_best_only=False, save_weights_only=False,
                 mode='auto', period=1):
        self.single_model = model
        super(ParallelModelCheckpoint,self).__init__(filepath, monitor, verbose,save_best_only, save_weights_only,mode, period)

    def set_model(self, model):
        super(ParallelModelCheckpoint,self).set_model(self.single_model)

checkpoint = ParallelModelCheckpoint(model, filepath='./cifar10_resnet_ckpt.h5', monitor='val_loss', verbose=1, save_best_only=True)

Pero tengo un problema al usarlo: no se guarda una vez por cada época, sino una vez por cada lote, y val_loss no se puede usar.

Después de una búsqueda, encontré el siguiente método en github

def get_smallest_loss(dir):
    pattern = 'model.(?P<epoch>\d+)-(?P<val_loss>[0-9]*\.?[0-9]*).h5'
    p = re.compile(pattern)
    losses = [float(p.match(f).groups()[1]) for f in os.listdir(dir) if p.match(f)]
    if len(losses) == 0:
        import sys
        return sys.float_info.max
    else:
        return np.min(losses)

class MyModelCheckpoint(Callback):
    def __init__(self, model, log_dir):
        Callback.__init__(self)
        self.model_to_save = model
        self.log_dir = log_dir
    def on_epoch_end(self, epoch, logs=None):
        fmt = self.log_dir + 'model.%04d-%.4f.h5'
        smallest_loss = get_smallest_loss(self.log_dir)
        if float(logs['val_loss']) < smallest_loss:
            self.model_to_save.save(fmt % (epoch, logs['val_loss']))

model_checkpoint = MyModelCheckpoint(single_model, log_dir)

Derive uno directamente de Callback, jaja, puedes guardar el peso intermedio más pequeño de val_loss al final de cada época.

Puede consultar la documentación oficial de keras aquí, https://keras.io/guides/writing_your_own_callbacks/ , que explica cómo definir las operaciones iniciales y finales de cada etapa.

 

==================================================== =====================

Es demasiado doloroso que parte del hardware solo admita versiones específicas de tf. Los modelos onnx y tf2 no ​​se pueden trasplantar directamente. Solo se pueden volver a entrenar con tf1.14. Si se trata solo de detección y segmentación, está bien. Si hay otros complejos o quieres trasplantarlos. Algunas operaciones nuevas no se pueden resolver en absoluto.

Guess you like

Origin blog.csdn.net/bcfd_yundou/article/details/112600549