Scikit-learn: GridSearchCV se fige indéfiniment avec le multithreading activé (c'est-à-dire w / n_jobs! = 1)

Créé le 12 août 2015  ·  88Commentaires  ·  Source: scikit-learn/scikit-learn

Je rencontre par intermittence ce problème (dans le sujet) avec GridSearchCV depuis un an maintenant, sur python 2.7, 3.3 et 3.4, deux emplois, plusieurs plates-formes / ordinateurs portables mac osx différents et de nombreuses versions différentes de numpy et scikit- apprendre (je les garde assez bien à jour).

J'ai essayé toutes ces suggestions et aucune d'entre elles ne fonctionne toujours :

https://github.com/scikit-learn/scikit-learn/issues/3605 - Définition de la méthode de démarrage multiprocesseur sur 'forkserver'
https://github.com/scikit-learn/scikit-learn/issues/2889 - Ayant des problèmes UNIQUEMENT lorsque les fonctions de notation personnalisées sont passées (j'ai absolument eu ce problème où le même GridSearchCV appelle avec n_jobs! = 1 gel avec un buteur personnalisé mais se débrouille très bien sans un)
https://github.com/joblib/joblib/issues/138 - Définition des variables d'environnement à partir du nombre de threads MKL (j'ai essayé cela lors de l'exécution d'un numpy / sklearn construit contre mkl à partir d'une distribution Anaconda)
Mettre à l'échelle les entrées et s'assurer qu'il n'y a pas d'erreurs avec n_jobs = 1 - Je suis tout à fait sûr que les choses que j'essaie de faire sur plusieurs threads fonctionnent correctement sur un thread, et dans un court laps de temps

C'est un problème très frustrant qui semble toujours réapparaître quand je suis convaincu qu'il est parti, et la SEULE solution de contournement qui fonctionne à 100% du temps pour moi est d'aller à la source de GridSearchCV dans n'importe quelle distribution sklearn sur laquelle je suis. en changeant manuellement le backend défini dans l'appel à Paralell en «threading» (au lieu de multiprocessing).

Je n'ai pas évalué la différence entre ce hack et la définition de n_jobs = 1, mais y aurait-il une raison de s'attendre à des gains avec le backend de threading sur aucune parallélisation du tout? Certes, ce ne serait pas aussi bon que le multitraitement mais au moins c'est plus stable.

btw les versions les plus récentes sur lesquelles j'ai eu le même problème sont:

  • Mac OS 10.9.5
  • Python 3.4.3 :: Continuum Analytics, Inc.
  • scikit-learn == 0.16.1
  • scipy == 0.16.0
  • numpy == 1.9.2
  • pandas == 0.16.2
  • joblib == 0.8.4
Bug

Commentaire le plus utile

@ eric-czech Si vous êtes sous Python 3.4 ou 3.5, essayez de définir la variable d'environnement suivante, puis redémarrez votre programme python:

export JOBLIB_START_METHOD="forkserver"

comme expliqué dans la documentation joblib . Le mode forkserver is n'est pas activé par défaut car il interrompt les fonctions définies de manière interactive.

Tous les 88 commentaires

Avez-vous des problèmes constamment sur cette plate-forme?

En termes de multithreading: il existe certains estimateurs pour lesquels le multithreading donnera probablement des gains substantiels, ceux où la plupart du travail est effectué dans des opérations numpy ou Cython sans GIL. Vraiment, je ne pense pas que cela ait été beaucoup évalué; backend='threading' est une chose assez récente.

La vraie question est: que pouvons-nous faire de plus pour identifier quel est le problème?

Pour commencer, quels estimateurs de base avez-vous envisagés?

@jnothman Par plateforme utilisez-vous OSX 10.9.5? Si c'est le cas, alors oui, ce n'est pas la première fois que j'ai ce problème.

Un détail peut-être majeur que j'ai omis auparavant est que j'utilise toujours des blocs-notes IPython lorsque j'ai des problèmes. J'ai un noyau pour un cahier chargé en ce moment où si j'ajoute un argument "scoring" avec n_jobs! = 1 alors GridSearchCV se bloque pour toujours mais si je supprime cet argument, tout va bien. Même si la fonction de notation que je donne ne fait rien d'autre que retourner une valeur flottante constante, elle se fige toujours (mais fait exactement ce que vous attendez avec n_jobs = 1).

Re: threading c'est bon à entendre, alors peut-être que cette option pour GridSearchCV aurait alors un sens.

En ce qui concerne les estimateurs avec lesquels j'ai des problèmes, je ne suis pas sûr de pouvoir le réduire beaucoup. J'en essaie normalement autant que possible pour obtenir des informations utiles pour vous ici, je viens de vérifier que je pouvais reproduire les conditions que j'ai mentionnées ci-dessus avec n'importe quel estimateur et j'ai constaté que je pouvais dans tous les cas (ou du moins j'ai essayé LogisticRegression, SGDClassifier, GBRT et RF).

J'adorerais faire tout ce que je peux pour fournir quelque chose de plus, même si je ne suis pas familier avec le contexte généralement le plus utile pour les problèmes de multithreading comme celui-ci. Avez-vous des suggestions pour moi?

Utilisez-vous numpy lié au cadre d'accélération?

Non, sauf si je manque quelque chose. Je pensais que la version numpy installée change lorsque vous faites cela ou à tout le moins que le package d'accélération serait présent:

(research3.4) eczech $ pip freeze | grep numpy
numpy == 1.9.2
(research3.4) Mise à jour eczech $ conda accélérer
Erreur: le package 'accelerate' n'est pas installé dans /Users/eczech/anaconda/envs/research3.4

Pardonnez mon ignorance de ne pas pouvoir répondre à cela avec une confiance à 100%, mais je n'ai certainement rien fait intentionnellement pour l'installer.

Conda Accelerate n'est pas la même chose que Apple Accelerate:
http://docs.continuum.io/accelerate/index
https://developer.apple.com/library/mac/documentation/Accelerate/Reference/AccelerateFWRef/

conda accelerate est une version accélérée des packages MKL, Apple accelerate est leur alternative à MKL.

pouvez-vous nous donner numpy.__config__.show() ?

le multitraitement ne fonctionne pas avec Accelerate IIRC. ping @ogrisel

certainement:

np. config .show ()
atlas_3_10_blas_threads_info:
INDISPONIBLE
atlas_info:
INDISPONIBLE
atlas_3_10_info:
INDISPONIBLE
atlas_threads_info:
INDISPONIBLE
atlas_3_10_blas_info:
INDISPONIBLE
blas_opt_info:
extra_compile_args = ['-msse3', '-DAPPLE_ACCELERATE_SGEMV_PATCH', '-I / System / Library / Frameworks / vecLib.framework / Headers']
extra_link_args = ['-Wl, -framework', '-Wl, Accelerate']
define_macros = [('NO_ATLAS_INFO', 3)]
lapack_mkl_info:
INDISPONIBLE
atlas_blas_info:
INDISPONIBLE
mkl_info:
INDISPONIBLE
lapack_opt_info:
extra_compile_args = ['-msse3', '-DAPPLE_ACCELERATE_SGEMV_PATCH']
extra_link_args = ['-Wl, -framework', '-Wl, Accelerate']
define_macros = [('NO_ATLAS_INFO', 3)]
blas_mkl_info:
INDISPONIBLE
atlas_3_10_threads_info:
INDISPONIBLE
openblas_info:
INDISPONIBLE
openblas_lapack_info:
INDISPONIBLE
atlas_blas_threads_info:
INDISPONIBLE

Oui, c'est un problème connu que je ne trouve pas dans le suivi des problèmes. Accelerate ne fonctionne pas avec le multitraitement.

Je suis un peu confus. Le backend de threading ne fait quelque chose que lorsque le GIL est publié, non?

Gotcha, savez-vous comment je devrais procéder pour reconstruire numpy alors? Dois-je simplement l'installer au lieu d'utiliser le package conda pour cela? Ou est-ce que je ferais mieux de construire à partir des sources et de m'assurer que ces arguments d'accélération Apple ne sont pas présents?

On dirait que c'est un peu un non-début d'un problème malgré tout. Fermer si c'est juste battre un cheval mort.

si vous pouvez accélérer le conda, cela fonctionnerait;)

peut-être pourrions-nous essayer de renflouer joblib ?

Ah super, le continuum a dû payer Apple pour faire ça haha.

Vous avez des suggestions à 0 $? Et merci pour la perspicacité de toute façon.

Oh, et je sais que cela a déjà été demandé, mais le fait que je n'ai ce problème que sur ma plate-forme actuelle lorsque j'utilise une fonction de notation personnalisée est-il quelque chose à faire? Pour la vie de moi, je ne vois pas ce qui pourrait être problématique à ce sujet étant donné le code source de grid_search.py, mais cela pourrait-il avoir quelque chose à voir avec le décapage de la fonction personnalisée?

Et quelque peu sans rapport avec cela, je viens de me rappeler que j'ai également essayé de contourner ce problème dans le passé en créant une version modifiée de GridSearchCV qui utilise le backend parallèle IPython à la place, donc en supposant que je revisite cette solution, cela vaudrait-il la peine d'être partagé d'une manière ou d'une autre? Cette solution fonctionnait très bien mais était un peu pénible à utiliser car toutes les classes et fonctions personnalisées devaient être disponibles sur le pythonpath plutôt que dans les cahiers eux-mêmes, mais s'il n'y a pas d'autres meilleures options, peut-être que l'une a des jambes.

Vous pouvez créer un lien avec l'atlas, mais ce sera plus lent [apple] accélérer, me semble-t-il.
Peut-être existe-t-il un numpy gratuit lié à MKL pour OS X? Il y en a un pour Windows.

[si vous êtes un universitaire, l'accélération du continuum est gratuite.]

Je suis presque sûr que cela n'a aucun rapport avec l'utilisation d'une fonction de notation personnalisée.
Pouvez-vous donner des extraits autonomes qui rompent avec une fonction de notation personnalisée, mais pas sans?

Peut-être que le fait de la fonction de notation personnalisée est pertinent (par exemple, des problèmes de décapage ou un parallélisme imbriqué peuvent être pertinents). Pouvons-nous voir le code?

Ou voulez-vous simplement dire une métrique standard avec make_scorer ?

Certes, voici une partie pertinente et il semble que tout va bien avec make_scorer mais pas avec une fonction personnalisée:

from sklearn.linear_model import LogisticRegression
from sklearn.grid_search import GridSearchCV
from sklearn.cross_validation import StratifiedKFold
from sklearn.metrics import average_precision_score, make_scorer
import functools

res = []
clfs = []

for response in responses:
    X, y = d_in[features], d_in[response]
    for i, (train, test) in enumerate(StratifiedKFold(y, 5)):
        X_train, y_train, X_test, y_test = X.iloc[train], y.iloc[train], X.iloc[test], y.iloc[test]
        clf = LogisticRegression(penalty='l1')
        grid = {
            'class_weight': [{0: 1, 1: 10}, {0: 1, 1: 100}, {0: 1, 1: 1000}],
            'C': np.logspace(-3, 0, num=4)
        }

        # Using make_scorer doesn't cause any issues
        # clf = GridSearchCV(clf, grid, cv=StratifiedKFold(y_train, 3),  
        #                    scoring=make_scorer(average_precision_score), n_jobs=-1)

        # This however is a problem:
        def avg_prec_score(estimator, X, y):
            return average_precision_score(y, estimator.predict_proba(X)[:, 1])
        clf = GridSearchCV(clf, grid, cv=StratifiedKFold(y_train, 5),  
                           scoring=avg_prec_score, n_jobs=-1)

        clf = clf.fit(X_train, y_train)
        print('Best parameters for response {} inferred in fold {}: {}'.format(response, i, clf.best_params_))

        y_pred = clf.predict(X_test)
        y_proba = clf.predict_proba(X_test)

        clfs.append((response, i, clf))
        res.append(pd.DataFrame({
            'y_pred': y_pred, 
            'y_actual': y_test, 
            'y_proba': y_proba[:,1],
            'response': np.repeat(response, len(y_pred))
        }))

res = functools.reduce(pd.DataFrame.append, res)
res.head()

Je vais travailler sur une version autonome qui implique une version des données que j'utilise aussi (mais cela prendra plus de temps). En attendant, le décapage de ces fonctions personnalisées semble être une bonne piste - je l'ai essayé plusieurs fois pour être sûr et il se bloque 100% du temps avec une fonction personnalisée et 0% du temps lors de l'utilisation de make_scorer avec certaines fonctions métriques connues et importées.

Et est-ce que dans main (c'est-à-dire le script de premier niveau en cours d'interprétation) ou un
module importé?

Le 15 août 2015 à 23h37, Eric Czech [email protected] a écrit:

Certainement, voici une partie pertinente et il semble que tout va bien
avec make_scorer mais pas avec une fonction personnalisée:

depuis sklearn.linear_model import LogisticRegression depuis sklearn.grid_search import GridSearchCV depuis sklearn.cross_validation import StratifiedKFold depuis sklearn.metrics import average_precision_score, make_scorerimport functools

res = []
clfs = []
pour réponse dans les réponses:
X, y = d_in [fonctionnalités], d_in [réponse]
pour i, (train, test) dans enumerate (StratifiedKFold (y, 5)):
X_train, y_train, X_test, y_test = X.iloc [train], y.iloc [train], X.iloc [test], y.iloc [test]
clf = LogisticRegression (pénalité = 'l1')
grille = {
'class_weight': [{0: 1, 1: 10}, {0: 1, 1: 100}, {0: 1, 1: 1000}],
'C': np.logspace (-3, 0, num = 4)
}

    # Using make_scorer doesn't cause any issues
    # clf = GridSearchCV(clf, grid, cv=StratifiedKFold(y_train, 3),
    #                    scoring=make_scorer(average_precision_score), n_jobs=-1)

    # This however is a problem:
    def avg_prec_score(estimator, X, y):
        return average_precision_score(y, estimator.predict_proba(X)[:, 1])
    clf = GridSearchCV(clf, grid, cv=StratifiedKFold(y_train, 5),
                       scoring=avg_prec_score, n_jobs=-1)

    clf = clf.fit(X_train, y_train)
    print('Best parameters for response {} inferred in fold {}: {}'.format(response, i, clf.best_params_))

    y_pred = clf.predict(X_test)
    y_proba = clf.predict_proba(X_test)

    clfs.append((response, i, clf))
    res.append(pd.DataFrame({
        'y_pred': y_pred,
        'y_actual': y_test,
        'y_proba': y_proba[:,1],
        'response': np.repeat(response, len(y_pred))
    }))

res = functools.reduce (pd.DataFrame.append, res)
res.head ()

Je vais travailler sur une version autonome qui implique une version du
les données que j'utilise aussi (mais cela prendra plus de temps). En attendant,
le décapage de ces fonctions personnalisées semble être une bonne piste - je l'ai essayé
plusieurs fois encore pour être sûr et ça se bloque 100% du temps avec un custom
et 0% du temps lors de l'utilisation de make_scorer avec certains connus,
fonction métrique importée.

-
Répondez directement à cet e-mail ou affichez-le sur GitHub
https://github.com/scikit-learn/scikit-learn/issues/5115#issuecomment -131376298
.

Oh, c'est ipynb. Hmmm intéressant. Oui, le décapage pourrait être un problème ..?

Le 15 août 2015 à 23h51, Joel Nothman joel. [email protected] a écrit:

Et est-ce que dans main (c'est-à-dire le script de premier niveau en cours d'interprétation) ou
un module importé?

Le 15 août 2015 à 23h37, Eric Czech [email protected] a écrit:

Certainement, voici une partie pertinente et il semble que tout va bien
avec make_scorer mais pas avec une fonction personnalisée:

depuis sklearn.linear_model import LogisticRegression depuis sklearn.grid_search import GridSearchCV depuis sklearn.cross_validation import StratifiedKFold depuis sklearn.metrics import average_precision_score, make_scorerimport functools

res = []
clfs = []
pour réponse dans les réponses:
X, y = d_in [fonctionnalités], d_in [réponse]
pour i, (train, test) dans enumerate (StratifiedKFold (y, 5)):
X_train, y_train, X_test, y_test = X.iloc [train], y.iloc [train], X.iloc [test], y.iloc [test]
clf = LogisticRegression (pénalité = 'l1')
grille = {
'class_weight': [{0: 1, 1: 10}, {0: 1, 1: 100}, {0: 1, 1: 1000}],
'C': np.logspace (-3, 0, num = 4)
}

    # Using make_scorer doesn't cause any issues
    # clf = GridSearchCV(clf, grid, cv=StratifiedKFold(y_train, 3),
    #                    scoring=make_scorer(average_precision_score), n_jobs=-1)

    # This however is a problem:
    def avg_prec_score(estimator, X, y):
        return average_precision_score(y, estimator.predict_proba(X)[:, 1])
    clf = GridSearchCV(clf, grid, cv=StratifiedKFold(y_train, 5),
                       scoring=avg_prec_score, n_jobs=-1)

    clf = clf.fit(X_train, y_train)
    print('Best parameters for response {} inferred in fold {}: {}'.format(response, i, clf.best_params_))

    y_pred = clf.predict(X_test)
    y_proba = clf.predict_proba(X_test)

    clfs.append((response, i, clf))
    res.append(pd.DataFrame({
        'y_pred': y_pred,
        'y_actual': y_test,
        'y_proba': y_proba[:,1],
        'response': np.repeat(response, len(y_pred))
    }))

res = functools.reduce (pd.DataFrame.append, res)
res.head ()

Je vais travailler sur une version autonome qui implique une version du
les données que j'utilise aussi (mais cela prendra plus de temps). En attendant,
le décapage de ces fonctions personnalisées semble être une bonne piste - je l'ai essayé
plusieurs fois encore pour être sûr et ça se bloque 100% du temps avec un custom
et 0% du temps lors de l'utilisation de make_scorer avec certains connus,
fonction métrique importée.

-
Répondez directement à cet e-mail ou affichez-le sur GitHub
https://github.com/scikit-learn/scikit-learn/issues/5115#issuecomment -131376298
.

C'est dans un cahier

Je vais essayer de l'importer à partir d'un module à la place et voir comment cela se passe

Hmm que savez-vous, fonctionne bien lorsqu'il est défini en dehors du cahier.

J'ai essentiellement le même code en cours d'exécution en python 2.7 (j'avais besoin d'une bibliothèque plus ancienne) ainsi que ce code en python 3.4 et même si j'ai le problème de blocage dans 2.7, qu'il s'agisse ou non d'une fonction personnalisée ou de quelque chose utilisant make_scorer, je Je pense que cela résout tous mes problèmes dans la nouvelle version afin que je puisse vivre avec des solutions de contournement dans l'ancienne.

Est-ce que je peux faire autre chose pour découvrir pourquoi les fonctions de décapage définies dans un bloc-notes peuvent poser problème?

Eh bien, nous aimerions comprendre:

  • le décapage et le décapage sont-ils généralement un problème pour les fonctions définies localement sur cette plate-forme, ou sommes-nous confrontés à un problème particulier?
  • pourquoi, si le décapage est un problème, est-il suspendu plutôt que de soulever une exception? Pourriez-vous s'il vous plaît essayer monkey-patching ou similaire, pour voir s'il remplace le pickle.dumps(function) check https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/externals/joblib/parallel. py # L150 avec pickle.loads(pickle.dumps(function)) entraîne une erreur? (Pour expliquer, il s'agit d'un contrôle de sécurité pour assurer la décapabilité avant d'exécuter le multitraitement.)

@ogrisel pourrait être intéressé par cela.

D'après ce que j'ai vu sur Windows, les ordinateurs portables ont des interactions étranges avec le multitraitement.

Avez-vous essayé de simplement décaper et décoller la fonction définie dans le même cahier?

Aujourd'hui, j'ai accidentellement vu ce https://pythonhosted.org/joblib/parallel.html#bad -interaction-of-multiprocessing-and-third-party-libraries, n'est-ce pas lié?
Peut-être devriez-vous simplement passer à python 3.4 ou plus récent?

Désolé, j'ai passé de longues vacances. Pour répondre à vos questions cependant:

  1. re @jnothman : J'ai mis pickle.loads(pickle.dumps(function)) dans parallel.py et une instruction print après cela pour m'assurer qu'il s'exécutait proprement, et il n'y avait aucun problème. Pour être clair, GridSearchCV.fit appelé depuis le cahier est toujours resté bloqué comme auparavant sans changement (à l'exception de l'instruction d'impression que j'ai ajoutée apparaissant 16 fois avec n_jobs = -1).
  2. re @amueller : Si je vous comprends bien, j'ai exécuté quelque chose comme ça dans le cahier sans aucun problème:
def test_function(x):
    return x**2
pickle.loads(pickle.dumps(test_function))(3)
# 9
  1. re @olologin : je suis sur 3.4.3. Ou plus précisément: «3.4.3 | Continuum Analytics, Inc. | (par défaut, 6 mars 2015, 12:07:41) n [GCC 4.2.1 (Apple Inc. build 5577)] '

Je n'ai pas lu la conversation ci-dessus mais j'aimerais noter que ce test minimal échoue sous la version Python 2.6 de travis mais passe sous une configuration similaire sur mon PC ... (suggérant qu'il échoue lorsque n_jobs = -1 est défini sous une machine à un seul cœur pour les anciennes versions de python / joblib / scipy?)

def test_cross_val_score_n_jobs():
    # n_jobs = -1 seems to hang in older versions of joblib/python2.6
    # See issue 5115
    cross_val_score(LinearSVC(), digits.data, digits.target, cv=KFold(3),
                    scoring="precision_macro", n_jobs=-1)

+1 pour avoir rencontré ce problème, heureux de fournir des détails si cela peut aider

@ eric-czech Si vous êtes sous Python 3.4 ou 3.5, essayez de définir la variable d'environnement suivante, puis redémarrez votre programme python:

export JOBLIB_START_METHOD="forkserver"

comme expliqué dans la documentation joblib . Le mode forkserver is n'est pas activé par défaut car il interrompt les fonctions définies de manière interactive.

Avoir le même problème sur OS X 10.11.4 et Ubuntu 14.04 avec le dernier logiciel installé.

# Metrics
B_R = 10.0

def raw_TPR(y_true, y_pred):
    return np.sum((y_true == 1) & (y_pred == y_true))

def raw_FPR(y_true, y_pred):
    return np.sum((y_true == 0) & (y_pred != y_true))

def AMS(y_true, y_pred):
    print("Hello")
    tpr = raw_TPR(y_true, y_pred)
    fpr = raw_FPR(y_true, y_pred)
    score = np.sqrt(2 * ((tpr + fpr + B_R) * np.log(1 + tpr / (fpr + B_R))) - tpr)
    return score


# Grid search

param_grid = {
    "max_depth":[6, 10],
    "learning_rate":[0.01, 0.5],
    "subsample":[0, 1],
    "min_child_weight":[0.1, 1],
    "colsample_bytree":[0.1, 1],
    "base_score":[0.1, 1],
    "gamma":[0.5, 3.5]
}

scorer = make_scorer(AMS, greater_is_better=True)


clf = XGBClassifier()
gridclf = GridSearchCV(clf, param_grid, scorer, n_jobs=-1, verbose=2)
gridclf.fit(X_train, y_train)

En fait, ce code ne se fige que si n_jobs=1 .

Cela devrait maintenant fonctionner par défaut sur python 3 et être un wontfix sur python 2, n'est-ce pas @ogrisel ? Devrions-nous fermer?

S'il se bloque silencieusement sur Python 2 sans lancer d'avertissement ou d'erreur ("n_jobs> 1 non pris en charge sur Python 2"), ce n'est pas acceptable; pouvons-nous lancer une erreur?

@amueller sur Python 3, vous pouvez suivre https://github.com/scikit-learn/scikit-learn/issues/5115#issuecomment -187683383 pour contourner le problème, c'est-à-dire que cela ne fonctionnera pas par défaut même sur Python 3.

Je ne sais pas si nous devrions fermer car l'OP d'origine semblait dire que la définition de la méthode joblib start_method sur forkserver ne fonctionnait pas toujours ...

BTW, le xgboost est connu, voir https://github.com/scikit-learn/scikit-learn/issues/6627#issuecomment -206351138.

Edit: Le changement ci-dessous pourrait ne pas corriger les choses. J'ai également apporté un changement sans rapport avec la façon dont je gérais le multitraitement avec Pathos qui aurait pu être ma vraie solution.

Solution rapide:
np.random.seed(0)

Explication:
J'avais également rencontré ce problème, surtout dans la suite de tests pour auto_ml . Les premières (2?) Fois que j'ai exécuté GridSearchCV, c'était bien, mais les exécutions suivantes se bloquaient sans erreur.

Je viens de placer np.random.seed(0) dans chacun de mes tests, pour assurer la reproductibilité tout en me donnant la possibilité de réorganiser les tests au fil du temps sans jouer avec le caractère aléatoire. Dès que j'ai fait cela, tous les tests qui se sont accrochés à l'erreur GSCV ont recommencé à fonctionner.

def test_name():
    np.random.seed(0)
    test_code_involving_gscv_here

espérons que cela aide au débogage!

Environnement de développement:
Mac OS X (Sierra)
Python 2.7
Versions à jour des bibliothèques.

@ClimbsRocks et bien c'est probablement une erreur dans vos estimateurs. Faites-nous savoir si vous avez un exemple reproductible;)

@amueller : bon appel. Je me suis précipité pour couper une branche pour que vous puissiez le reproduire, mais tout s'est bien passé cette fois.

Je pense que c'était probablement un problème avec la parallélisation de GSCV, alors que j'utilise également la parallélisation de Pathos dans d'autres parties du programme. C'est la seule autre chose liée que j'ai changé au cours de la semaine dernière.

J'ai depuis remanié pour fermer et ouvrir plus complètement leur pool multitraitement.

Ce qui me fait penser que ce n'était pas seulement un bogue dans l'un des estimateurs, c'est que lors de la construction de la suite de tests, chacun des tests s'est exécuté et a réussi individuellement. Ce n'est que lorsque j'ai exécuté plusieurs tests dans la même passe que tout dépendait de GSCV qu'il a commencé à se bloquer.

Commentaire précédent modifié pour noter cette incertitude.

si vous combinez joblib avec une autre parallélisation, il est très probable que cela plantera et vous ne devriez pas essayer cela.

Désolé pour ce fil mais je rencontre également ce problème.
J'ai créé un noyau Python 3.5 et défini la méthode de démarrage de Job Lib sur forkserver mais j'ai toujours le problème.

En fait, cela ne fonctionne même pas avec n_jobs = 1. Je vois qu'il calcule sauf pour le dernier paramètre.

Il y a t-il du nouveau ?

En fait, cela ne fonctionne même pas avec n_jobs = 1. Je vois qu'il calcule sauf pour le dernier paramètre.

C'est étrange et très probablement pas lié à ce problème (qui est d'environ n_jobs != 1 ). La meilleure façon d'obtenir de bons commentaires serait d'ouvrir un problème distinct avec un extrait de code autonome reproduisant le problème.

Je suis presque sûr que je rencontre moi-même ce problème. Après avoir essayé de nombreuses combinaisons, tout ce que je fais avec n_jobs> 1 se fige simplement après quelques plis. Je suis sur un ordinateur portable Ubuntu Linux avec sklearn = 0.19.0, donc c'est une configuration différente des autres que j'ai lues. Voici le code "offensant":

import xgboost as xgb
from sklearn.model_selection import GridSearchCV
cv_params = {'max_depth': [3,5,7], 'min_child_weight': [1,3,5]}

ind_params = {'learning_rate': 0.1, 'n_estimators': 1000, 'seed':0, 'subsample': 0.8, 'colsample_bytree': 0.8,  'objective': 'binary:logistic'}
optimized_XGB = GridSearchCV(xgb.XGBClassifier(**ind_params), 
                            cv_params, scoring = 'roc_auc', cv = 5, n_jobs = 1, verbose=2) 
optimized_XGB.fit(xgboost_train, label_train,eval_metric='auc')

Une des choses intéressantes est que lorsque j'importe xgboost, j'obtiens un avertissement d'obsolescence sur GridSearchCV comme s'il n'importait pas depuis model_selection. Cependant, je suis sur xgboost 0.62 et en regardant leur référentiel, il semble qu'ils importent le bon GridSearchCV. Pour être clair, l'avertissement de dépréciation n'est pas le problème qui me préoccupe mais plutôt celui qui se pose: le blocage de l'exécution avec n_jobs> 1. Soulignez simplement au cas où cela pourrait aider.

pourriez-vous fournir des données pour aider à reproduire le problème?

Le 24 août 2017 à 20h29, Xavier Amatriain [email protected]
a écrit:

Je suis presque sûr que je rencontre moi-même ce problème. Après avoir essayé plusieurs
combinaisons, tout ce que je fais avec n_jobs> 1 se fige simplement après quelques
plis. Je suis sur un ordinateur portable Ubuntu Linux avec sklearn = 0.19.0, donc c'est un
configuration différente des autres que j'ai lues. Voici la
code "offensant":

`importer xgboost comme xgb
depuis sklearn.model_selection import GridSearchCV
cv_params = {'max_depth': [3,5,7], 'min_child_weight': [1,3,5]}

ind_params = {'learning_rate': 0.1, 'n_estimators': 1000, 'seed': 0,
'sous-échantillon': 0.8, 'colsample_bytree': 0.8, 'objective': ' binaire: logistique '}
optimisé_XGB = GridSearchCV (xgb.XGBClassifier (** ind_params),
cv_params, score = 'roc_auc', cv = 5, n_jobs = 1, verbeux = 2)
optimisé_XGB.fit (xgboost_train, label_train, eval_metric = 'auc') `

Une des choses intéressantes est que lorsque j'importe xgboost, j'obtiens un
avertissement d'obsolescence sur GridSearchCV comme s'il n'importait pas depuis
model_selection. Cependant, je suis sur xgboost 0.62 et en regardant leur
référentiel il semble qu'ils importent le bon GridSearchCV. Être
clair, l'avertissement de dépréciation n'est pas le problème qui me préoccupe mais plutôt
celui à portée de main: l'exécution gelée avec n_jobs> 1. Juste en soulignant
cas cela pourrait aider.

-
Vous recevez cela parce que vous avez été mentionné.
Répondez directement à cet e-mail, affichez-le sur GitHub
https://github.com/scikit-learn/scikit-learn/issues/5115#issuecomment-324597686 ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/AAEz66DbfTlnU_-dcxLKa5zkrcZ-0qVOks5sbVCmgaJpZM4FqYlN
.

Bien sûr, vous pouvez télécharger les fichiers exacts que j'utilise à partir de:
https://xamat.github.io/xgboost_train.csv
https://xamat.github.io/label_train.csv

HTTP404

Désolé, il y a eu une erreur dans le premier lien, elle devrait maintenant être corrigée. Le 2ème devrait également être ok, je viens de vérifier.

Problème connu avec xgboost, voir https://github.com/scikit-learn/scikit-learn/issues/6627#issuecomment -206351138 par exemple.

Pour info , le backend

Est-ce toujours un bug? J'ai le même problème avec les valeurs par défaut (n_jobs = 1) ainsi qu'avec pre_dispatch = 1, en utilisant un RandomForestClassifier , avec 80 combinaisons de paramètres et ShuffleSplit CV (n = 20).

Il se bloque également pour un Pipeline ( SelectKBest(score_func=mutual_info_classif, k=10) suivi de RandomForestClassifier ), à la fois sous la dernière version ainsi que dans la version de développement.

Faites-moi savoir si vous avez trouvé une solution de contournement ou d'autres méthodes de sélection de modèle qui fonctionnent de manière fiable. Vous songez à essayer scikit-optimize .

Voulez-vous dire n_jobs = 1 ou est-ce une faute de frappe? Ce problème concerne n_jobs! = 1.

La meilleure façon d'obtenir un retour d'information de qualité est de fournir un moyen de reproduire le problème. Veuillez ouvrir un autre problème dans ce cas si le problème que vous rencontrez est bien avec n_jobs = 1.

J'ai écrit ce que je voulais dire, à savoir "le multithreading activé"
n_jobs! = 1 comme dans 'différent de 1'. De manière équivalente, n_jobs> 1. Par exemple, n_jobs = 4

Êtes-vous en train de dire que vous ne pouvez pas reprocher le gel pour n_jobs = 4?

Si tel est le cas, je fournirai un testcase dans un délai d'un mois (je passe à une nouvelle machine.)

Le 12 septembre 2017, à 7h10, Loïc Estève < [email protected] [email protected] > a écrit:

Voulez-vous dire n_jobs = 1 ou est-ce une faute de frappe? Ce problème concerne n_jobs! = 1.

La meilleure façon d'obtenir un retour d'information de qualité est de fournir un moyen de reproduire le problème. Veuillez ouvrir un autre problème dans ce cas si le problème que vous rencontrez est bien avec n_jobs = 1.

-
Vous recevez cela parce que vous avez été mentionné.
Répondez directement à cet e-mail, affichez-le sur GitHub https://github.com/scikit-learn/scikit-learn/issues/5115#issuecomment-328864498 , ou désactivez le fil https://github.com/notifications/unsubscribe- auth / ABH-rd7wgU5lcS6oD5VMl0YOB8CXfSTJks5shpDZgaJpZM4FqYlN .

@smcinerney êtes-vous @raamana? Je pense que @lesteve a répondu à @raamana qui a écrit n_jobs=1 , ce qui ne semble pas lié à ce problème.

Oh désolé, non, je ne suis pas @raamana. Oui, le problème de @ raamana est différent (mais probablement dû au même code)

Le 12 septembre 2017, à 9h23, Andreas Mueller < [email protected] [email protected] > a écrit:

@smcinerney https://github.com/smcinerney êtes-vous @raamana https://github.com/raamana ? Je pense que @lesteve https://github.com/lesteve a répondu à @raamana https://github.com/raamana qui a écrit n_jobs = 1, ce qui ne semble pas lié à ce problème.

-
Vous recevez cela parce que vous avez été mentionné.
Répondez directement à cet e-mail, affichez-le sur GitHub https://github.com/scikit-learn/scikit-learn/issues/5115#issuecomment-328905819 , ou désactivez le fil https://github.com/notifications/unsubscribe- auth / ABH-rYKQA3L5ifINBX6enrk5oDIsf1Lqks5shrASgaJpZM4FqYlN .

Mon mauvais, je ne voulais pas mélanger les choses. Je vais ouvrir un autre problème (avec un code minimal pour le reproduire), mais GridSearchCV n'est-il pas suspendu même avec n_jobs = 1 par défaut est un problème plus important (étant donné qu'il est par défaut et est censé fonctionner) que n_jobs> 1.

@raamana oui, c'est une plus grande préoccupation, mais il est également peu probable qu'il soit causé par un problème connexe.

@ eric-tchèque @jnothman
Donc, si vous décidez d'utiliser backend = 'threading'. Une méthode simple sans changer le code sklearn serait d'utiliser le gestionnaire de contexte parallel_backend et de ne pas changer la méthode fit du GSV.

from sklearn.externals.joblib import parallel_backend

clf = GridSearchCV()
with parallel_backend('threading'):
    clf.fit(x_train, y_train)

PS: Je ne suis pas sûr que le "filetage" fonctionne pour tous les estimateurs. Mais j'avais le même problème avec mon estimateur avec GSV njob> 1 et son utilisation fonctionne comme prévu pour moi sans changer la bibliothèque.

Système essayé:
MAC OS: 10.12.6
Python: 3,6
numpy == 1.13.3
pandas == 0.21.0
scikit-learn == 0.19.1

Hmm ... Il peut y avoir des problèmes de concurrence avec l'utilisation du backend de threading dans
la recherche de grille, par exemple le bogue dans # 10329 crée des conditions de course ...

Le 22 décembre 2017 à 03h59, Trideep Rath [email protected] a écrit:

@ eric-tchèque https://github.com/eric-czech @jnothman
https://github.com/jnothman
Donc, si vous décidez d'utiliser backend = 'threading'. Une méthode simple sans
changer le code sklearn serait d'utiliser le gestionnaire de contexte parallel_backend
et pas de changement dans la méthode d'ajustement du GSV.

depuis sklearn.externals.joblib import parallel_backend

clf = GridSearchCV ()
avec parallel_backend ('threading'):
clf.fit (x_train, y_train)

PS: Je ne suis pas sûr que le "filetage" fonctionne pour tous les estimateurs. Mais j'étais
ayant le même problème avec mon estimateur avec GSV njob> 1 et en utilisant ceci
fonctionne comme prévu pour moi sans changer la bibliothèque.

Système essayé:
MAC OS: 10.12.6
Python: 3,6
numpy == 1.13.3
pandas == 0.21.0
scikit-learn == 0.19.1

-
Vous recevez cela parce que vous avez été mentionné.
Répondez directement à cet e-mail, affichez-le sur GitHub
https://github.com/scikit-learn/scikit-learn/issues/5115#issuecomment-353402474 ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/AAEz64SfwYpjLU1JK0vukBRXJvWYs3LKks5tCo51gaJpZM4FqYlN
.

Cas: Utilisation du backend comme "threading" et utilisation de Estimator qui étend BaseEstimator et ClassifierMixin. Je ne sais pas d'où vient la condition de course. Pouvez-vous s'il vous plaît élaborer.

Selon ma compréhension et mes expériences, je n'ai observé aucune condition de race.

out = Parallel(
    n_jobs=self.n_jobs, verbose=self.verbose,
    pre_dispatch=pre_dispatch
)(delayed(_fit_and_score)(clone(base_estimator), X, y, scorers, train,
                          test, self.verbose, parameters,
                          fit_params=fit_params,
                          return_train_score=self.return_train_score,
                          return_n_test_samples=True,
                          return_times=True, return_parameters=False,
                          error_score=self.error_score)
  for parameters, (train, test) in product(candidate_params,
                                           cv.split(X, y, groups)))

_fit_and_score est appelé sur le clone (base_estimator). Cela fait un deep_copy et a une copie de ses propres données.

out est la sortie de la méthode _fit_and_score. Donc, après cela, tous les threads ont terminé l'exécution de la méthode d'ajustement de l'estimateur et ont rapporté les résultats.

Les résultats sont ce que vous obtenez de GCV_clf.cv_results_

Pouvez-vous s'il vous plaît expliquer dans ce cas précis pourquoi cela causerait une condition de concurrence?

La condition de concurrence se produit si vous définissez des paramètres imbriqués, c'est-à-dire lorsque
un paramètre modifié est un estimateur et un autre est un paramètre de cela
estimateur.

Je rencontre le même problème en utilisant make_scorer en combinaison avec GridSearchCv et n_jobs=-1 sous Win 7 avec les versions récentes:

Windows-7-6.1.7601-SP1
Python 3.6.4 |Anaconda, Inc.| (default, Jan 16 2018, 10:22:32) [MSC v.1900 64 bit (AMD64)]
NumPy 1.12.1
SciPy 1.0.0
Scikit-Learn 0.19.1

@mansenfranzen merci d'avoir publié vos versions et votre plateforme! La meilleure chance d'obtenir des commentaires de bonne qualité est de fournir un extrait de code autonome pour reproduire le problème. Veuillez lire https://stackoverflow.com/help/mcve pour plus de détails.

Vous rencontrez le même problème sous Win7 avec toutes les étapes de prétraitement personnalisées.
Chaîne d'outils:

Python 3.6.2
NumPy 1.13.1, 1.14.2 (under both)
SciPy 1.0.0
SkLearn 0.19.1

MCVE:

from sklearn.pipeline import Pipeline, make_pipeline
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score
import numpy as np

class CustomTransformer:
    def fit(self, X, y):
        return self

    def transform(self, X):
        return X

pipeline = make_pipeline(CustomTransformer(),
                         SVC())

X_train = np.array([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0], [7.0, 8.0]])
y_train = np.array([1.0, 0.0, 0.0, 1.0])

print(cross_val_score(pipeline, X_train, y_train, cv=2, n_jobs=-1))

savez-vous que le multitraitement python ne fonctionnera pas sous Windows sans if __name__ == '__main__' ?

Oui. Désolé, j'ai oublié de dire que j'utilise Jupyter.
Un script autonome avec if __name__ == '__main__' imprime les traces suivantes, puis se fige toujours:

Process SpawnPoolWorker-1:
Traceback (most recent call last):
  File "C:\Python\Python36\lib\multiprocessing\process.py", line 249, in _bootstrap
    self.run()
  File "C:\Python\Python36\lib\multiprocessing\process.py", line 93, in run
    self._target(*self._args, **self._kwargs)
  File "C:\Python\Python36\lib\multiprocessing\pool.py", line 108, in worker
    task = get()
  File "C:\Python\Python36\lib\site-packages\sklearn\externals\joblib\pool.py", line 362, in get
    return recv()
  File "C:\Python\Python36\lib\multiprocessing\connection.py", line 251, in recv
    return _ForkingPickler.loads(buf.getbuffer())
AttributeError: Can't get attribute 'CustomTransformer' on <module '__mp_main__' from 'C:\\projects\\Python\\Sandbox\\test.py'>
< same for SpawnPoolWorker-3 here >

Oh intéressant. Par simple paresse, j'ai placé tout le script sous if __name__ == '__main__' et j'ai obtenu les résultats du commentaire précédent.

Maintenant, je n'ai placé que pipeline = make_pipeline... , et il s'est exécuté avec succès. C'est peut-être la cause de Jupyter?

Quoi qu'il en soit, je ne sais pas si le comportement du commentaire précédent est valide et provoqué par une mauvaise utilisation de if __name__ == '__main__' , ou si c'est la faute de SkLearn.

il semble que ce n'est pas un problème avec notre bibliothèque, mais à propos de l'exécution
contexte pour le multitraitement dans Windows ...

C'est sale. Et en effet, je n'ai pu reproduire aucun des problèmes sous Ubuntu avec les mêmes versions de tout. Merci pour l'aide!

Peut confirmer que ce bogue est bien vivant.

Exécution sous Windows 10 dans un notebook Jupyter, Python3, Sklearn 0.19.1

Même problème sur Linux Mint (Ubuntu 16.10) Python 3.5

Tout se bloque à la première Epoch sur chaque cœur et les processeurs sont inactifs, donc aucun travail n'est en cours.

@MrLobs cela ressemble à une erreur de décapage, non? placez CustomTransformer dans un fichier Python séparé.

@ Chrisjw42 @avatsaev sans plus de contexte, nous ne pouvons pas vraiment faire grand-chose.
@avatsaev semble que vous

@amueller oui c'est tensorflow

@avatsaev ce n'est toujours pas assez d'informations. Avez-vous un minimum d'exemple à reproduire? quel blas utilisez-vous, utilisez-vous GPU, quelle version de scikit-learn utilisez-vous ...

Ok, il s'avère que c'est parce que j'utilise TF GPU, donc définir n_jobs sur> 1 ne fonctionne pas vraiment, ce qui est normal car je n'ai qu'un seul GPU lol

ouais, vous ne devriez pas vraiment utiliser n_jobs avec TF de toute façon.

pourquoi pas?

@amueller , oui, mettre des transformateurs personnalisés dans un fichier séparé le résout

Serait-il possible pour n_jobs! = 1 de lancer une erreur (ou au moins un avertissement) dans les environnements dans lesquels il va se bloquer? Je viens de rencontrer ce problème dans les notebooks jupyter, et si j'étais un utilisateur plus débutant (comme le reste de ma classe), je n'aurais jamais compris pourquoi gridsearchcv continuait à se bloquer, en fait, notre professeur nous a même conseillé d'utiliser n_jobs = - 1. Si le problème ici est connu, le paquet (keras ou sklearn, selon le cas) pourrait-il avertir qu'il se produira et empêcher le blocage?

Je ne pense pas que quiconque sache dans quel environnement cela va s'accrocher ... Je ne pense pas que quiconque ait réussi à reproduire ce bogue de manière fiable.

mais nous travaillons à l'amélioration de notre infrastructure multitraitement.
je ne sais pas si cela résoudra tous ces problèmes.

@jnothman 👍

C'est formidable d'entrendre ça!

Je ne sais pas pourquoi il est étiqueté 0.21. Ce problème est résolu en 0.20 dans la plupart des cas. Je pense que nous devrions fermer cela et amener les gens à ouvrir de nouvelles questions. Celui-ci est trop long et non spécifique.

Je viens de rencontrer la même chose sur AWS Ubuntu avec jupyter ...

L'utilisation de parallel_backend semble fonctionner ...


from sklearn.externals.joblib import parallel_backend

clf = GridSearchCV(...)
with parallel_backend('threading'):
    clf.fit(x_train, y_train)

@morienor si vous pouvez reproduire ce problème avec scikit-learn 0.20.1, veuillez ouvrir un nouveau numéro avec tous les détails nécessaires pour que quelqu'un d'autre puisse reproduire le problème (le script complet avec des instructions d'importation sur un faux ensemble de données aléatoires) le long avec tous les numéros de version pour python, scikit-learn, numpy, scipy et le système d'exploitation.

Je viens de rencontrer la même chose sur AWS Ubuntu avec jupyter ...

L'utilisation de parallel_backend semble fonctionner ...


from sklearn.externals.joblib import parallel_backend

clf = GridSearchCV(...)
with parallel_backend('threading'):
    clf.fit(x_train, y_train)

Cela fonctionne pour moi! Merci beaucoup!

@ jmq19950824 @morienor ouais mais ça ne sert à rien d'utiliser threading backend à cause de GIL.

Je viens de rencontrer la même chose sur AWS Ubuntu avec jupyter ...

L'utilisation de parallel_backend semble fonctionner ...


from sklearn.externals.joblib import parallel_backend

clf = GridSearchCV(...)
with parallel_backend('threading'):
    clf.fit(x_train, y_train)

le génie travaille pour moi pour

Cette page vous a été utile?
0 / 5 - 0 notes