web-dev-qa-db-fra.com

Keras + Tensorflow et Multiprocessing dans Python

J'utilise Keras avec Tensorflow comme backend.

J'essaie d'enregistrer un modèle dans mon processus principal, puis de charger/exécuter (c'est-à-dire appeler model.predict) Dans un autre processus.

J'essaie actuellement l'approche naïve des documents pour enregistrer/charger le modèle: https://keras.io/getting-started/faq/#how-can-i-save-a-keras- modèle .
Donc en gros:

  1. model.save() dans le processus principal
  2. model = load_model() dans le processus enfant
  3. model.predict() dans le processus enfant

Cependant, il se bloque simplement sur l'appel load_model.

En cherchant, j'ai découvert cette réponse potentiellement liée suggérant que Keras ne peut être utilisé que dans un seul processus: en utilisant le multitraitement avec theano mais je ne suis pas sûr si c'est vrai (je ne peux pas trouver grand-chose à ce sujet) .

Existe-t-il un moyen d'atteindre mon objectif? Une description de haut niveau ou un court exemple est grandement apprécié.

Remarque: J'ai tenté des approches dans le sens de la transmission d'un graphique au processus, mais a échoué car il semble que les graphiques tensorflow ne soient pas sélectionnables (connexe SO poste pour cela ici: Tensorflow : Passer une session à un python multiprocess ). S'il y a bien un moyen de passer le graphique/modèle tensorflow au processus enfant alors je suis ouvert à cela aussi.

Merci!

27
John Cast

D'après mon expérience - le problème réside dans le chargement de Keras dans un processus, puis dans la création d'un nouveau processus lorsque le keras a été chargé dans votre environnement principal. Mais pour certaines applications (comme par exemple la formation d'un mélange de Kerasmodels), il est tout simplement préférable d'avoir toutes ces choses en un seul processus. Donc, ce que je conseille, c'est l'approche suivante (un peu lourde - mais qui fonctionne pour moi):

  1. NE CHARGEZ PAS DE KERAS DANS VOTRE ENVIRONNEMENT PRINCIPAL. Si vous souhaitez charger Keras/Theano/TensorFlow, faites-le uniquement dans l'environnement de fonction. Par exemple. ne pas faire faites ceci:

    import keras
    
    def training_function(...):
        ...
    

    mais procédez comme suit:

    def training_function(...):
        import keras
        ...
    
  2. Exécuter le travail connecté à chaque modèle dans un processus distinct: Je crée généralement des travailleurs qui font le travail (comme par exemple la formation, le réglage, la notation) et je les exécute dans des processus séparés. Ce qui est bien, c'est que toute la mémoire utilisée par ce processus est complètement libérée lorsque votre processus est terminé. Cela vous aide à résoudre de nombreux problèmes de mémoire que vous rencontrez généralement lorsque vous utilisez le multitraitement ou même exécutez plusieurs modèles en un seul processus. Donc, cela ressemble par exemple comme ça:

    def _training_worker(train_params):
        import keras
        model = obtain_model(train_params)
        model.fit(train_params)
        send_message_to_main_process(...)
    
    def train_new_model(train_params):
        training_process = multiprocessing.Process(target=_training_worker, args = train_params)
        training_process.start()
        get_message_from_training_process(...)
        training_process.join()
    

Une approche différente consiste simplement à préparer différents scripts pour différentes actions de modèle. Mais cela peut entraîner des erreurs de mémoire, en particulier lorsque vos modèles consomment de la mémoire. NOTEZ que pour cette raison, il est préférable de rendre votre exécution strictement séquentielle.

39
Marcin Możejko

J'ai créé un exemple simple pour montrer comment exécuter le modèle Keras dans plusieurs processus avec plusieurs GPU. J'espère que cet échantillon pourrait vous aider. https://github.com/yuanyuanli85/Keras-Multiple-Process-Prediction

5
VictorLi

J'ai créé un décorateur qui a corrigé mon code.

from multiprocessing import Pipe, Process

def child_process(func):
    """Makes the function run as a separate process."""
    def wrapper(*args, **kwargs):
        def worker(conn, func, args, kwargs):
            conn.send(func(*args, **kwargs))
            conn.close()
        parent_conn, child_conn = Pipe()
        p = Process(target=worker, args=(child_conn, func, args, kwargs))
        p.start()
        ret = parent_conn.recv()
        p.join()
        return ret
return wrapper

@child_process
def keras_stuff():
    """ Keras stuff here"""
1
Mark