Scikit-learn: GridSearchCV congela indefinidamente com multithreading ativado (ou seja, w / n_jobs! = 1)

Criado em 12 ago. 2015  ·  88Comentários  ·  Fonte: scikit-learn/scikit-learn

Eu tenho encontrado este problema intermitentemente (no assunto) com GridSearchCV há mais de um ano, em python 2.7, 3.3 e 3.4, dois trabalhos, várias plataformas / laptops mac osx diferentes e muitas versões diferentes de numpy e scikit- aprender (eu os mantenho muito bem atualizados).

Tentei todas essas sugestões e nenhuma delas sempre funciona:

https://github.com/scikit-learn/scikit-learn/issues/3605 - Definição do método de início de multiprocessamento para 'forkserver'
https://github.com/scikit-learn/scikit-learn/issues/2889 - Tendo problemas SOMENTE quando as funções de pontuação personalizadas são passadas (eu absolutamente tive esse problema onde o mesmo GridSearchCV chama com n_jobs! = 1 congelamento com um marcador personalizado, mas se sai bem sem ele)
https://github.com/joblib/joblib/issues/138 - Definindo variáveis ​​de ambiente a partir de contagens de threads MKL (eu tentei isso ao executar um numpy / sklearn construído contra mkl de uma distribuição Anaconda)
Escalando entradas e certificando-se de que não haja erros com n_jobs = 1 - Tenho certeza de que as coisas que estou tentando fazer em vários threads são executadas corretamente em um thread e em um pequeno período de tempo

É um problema muito frustrante que sempre parece surgir de volta quando estou confiante de que foi embora, e a ÚNICA solução alternativa que funciona 100% do tempo para mim é ir para a fonte do GridSearchCV em qualquer distribuição do sklearn em que estou alterar manualmente o back-end definido na chamada de Paralell para 'threading' (em vez de multiprocessamento).

Eu não comparei a diferença entre esse hack e definir n_jobs = 1, mas haveria alguma razão para esperar algum ganho com o back-end de threading sem paralelização? Certamente, não seria tão bom quanto o multiprocessamento, mas pelo menos é mais estável.

entre as versões mais recentes que tive o mesmo problema são:

  • 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

Comentários muito úteis

@ eric-czech Se você estiver no Python 3.4 ou 3.5, tente definir a seguinte variável de ambiente e reinicie seu programa Python:

export JOBLIB_START_METHOD="forkserver"

conforme explicado na documentação do

Todos 88 comentários

Você tem problemas de forma consistente nessa plataforma ??

Em termos de multithreading: existem alguns estimadores para os quais multithreading provavelmente dará ganhos substanciais, aqueles em que a maior parte do trabalho é feita em operações numpy ou Cython sem GIL. Realmente, não acho que isso tenha sido muito avaliado; backend='threading' é algo recente.

A verdadeira questão é: o que mais podemos fazer para identificar qual é o problema?

Para começar, quais estimadores de base você considerou?

@jnothman Por plataforma você

Um detalhe possivelmente importante que omiti antes, no entanto, é que sempre uso notebooks IPython quando tenho problemas. Eu tenho um kernel para um notebook carregado agora onde se eu adicionar um argumento de "pontuação" com n_jobs! = 1 então GridSearchCV trava para sempre, mas se eu remover esse argumento, está tudo bem. Mesmo que a função de pontuação que forneço não faça nada além de retornar um valor flutuante constante, ela ainda congela (mas faz exatamente o que você esperaria com n_jobs = 1).

Re: threading é bom ouvir, então talvez essa opção para GridSearchCV faça sentido então.

No que diz respeito aos estimadores com os quais tenho problemas, não tenho certeza se posso reduzir muito. Eu normalmente tento tantos deles quanto consigo para obter alguma informação útil para você aqui, eu apenas verifiquei que poderia reproduzir as condições que mencionei acima com qualquer estimador e descobri que poderia em todos os casos (ou pelo menos tentei LogisticRegression, SGDClassifier, GBRT e RF).

Adoraria fazer tudo e qualquer coisa que puder para fornecer algo mais para prosseguir, embora não esteja familiarizado com o contexto que geralmente é mais útil para problemas de multithreading como este. Tem alguma sugestão para mim?

Você usa o numpy ligado ao framework de aceleração?

Não, a menos que esteja faltando alguma coisa. Eu pensei que a versão numpy instalada mudaria quando você fizer isso ou pelo menos que o pacote de aceleração estaria presente:

(research3.4) eczech $ pip freeze | grep numpy
numpy == 1.9.2
(pesquisa 3.4) atualização acelerada de eczech $ conda
Erro: o pacote 'accelerate' não está instalado em /Users/eczech/anaconda/envs/research3.4

Perdoe minha ignorância por não poder responder com 100% de confiança, mas certamente não fiz nada intencionalmente para instalá-lo.

conda accelerate não é o mesmo que apple accelerate:
http://docs.continuum.io/accelerate/index
https://developer.apple.com/library/mac/documentation/Accelerate/Reference/AccelerateFWRef/

O conda accelerate é uma versão acelerada de pacotes MKL, e o apple accelerate é a alternativa ao MKL.

você pode nos dar numpy.__config__.show() ?

o multiprocessamento não funciona com o acelerador IIRC. ping @ogrisel

Certamente:

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

Sim, é um problema conhecido que não consigo encontrar no rastreador de problemas. O Accelerate não funciona com multiprocessamento.

Estou um pouco confuso. O back-end de threading só faz algo quando o GIL é lançado, certo?

Te peguei, você sabe como eu deveria reconstruir numpy então? Devo apenas instalá-lo em vez de usar o pacote conda para ele? Ou seria melhor construir a partir da fonte e garantir que esses argumentos de aceleração da maçã não estejam presentes?

Parece que isso é um pouco como um obstáculo para um problema, independentemente. Fechar se for apenas bater em um cavalo morto.

se você conseguir acelerar o conda, funcionaria;)

talvez pudéssemos tentar resgatar joblib ?

Ah ótimo, continuum deve ter pago a apple para fazer isso haha.

Tem alguma sugestão $ 0? E obrigado pelo insight de qualquer maneira.

Ah, e também sei que isso já foi perguntado antes, mas o fato de que só estou tendo esse problema na minha plataforma atual ao usar uma função de pontuação personalizada é algo para continuar? Pela minha vida, não consigo ver o que poderia ser problemático, dado o código-fonte grid_search.py, mas poderia ter algo a ver com a decapagem da função personalizada?

E algo não relacionado a isso, acabei de lembrar que também tentei contornar isso no passado criando uma versão modificada do GridSearchCV que usa o back-end paralelo IPython, então supondo que eu revisitei essa solução, valeria a pena compartilhar de alguma forma? Essa solução funcionou bem, mas foi um pouco difícil de usar porque todas as classes e funções personalizadas tinham que estar disponíveis no pythonpath em vez dos próprios notebooks, mas se não houver outras opções melhores, talvez esse tenha algumas pernas.

Você pode fazer um link com o atlas, mas isso vai ser mais lento [apple] acelerar, me parece.
Talvez haja um numpy vinculado MKL gratuito lá fora para OS X? Existe um para janelas.

[se você for um acadêmico, aceleração contínua é grátis aliás]

Tenho certeza de que isso não está relacionado ao uso de uma função de pontuação personalizada.
Você pode dar sniplets independentes que quebram com uma função de pontuação personalizada, mas não sem?

Talvez o fato da função de pontuação customizada seja relevante (por exemplo, problemas de decapagem ou paralelismo aninhado podem ser pertinentes). Podemos ver o código?

Ou você quer dizer apenas uma métrica padrão com make_scorer ?

Certamente, aqui está uma parte relevante e parece que tudo está bem com make_scorer, mas não com uma função personalizada:

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()

Vou trabalhar em uma versão independente que envolve alguma versão dos dados que estou usando também (mas vai demorar mais). Nesse ínterim, porém, a decapagem dessas funções personalizadas soa como uma boa pista - eu tentei várias vezes novamente para ter certeza e trava 100% do tempo com uma função personalizada e 0% do tempo ao usar make_scorer com alguma função métrica importada conhecida.

E é isso em principal (ou seja, o script de nível superior sendo interpretado) ou um
módulo importado?

Em 15 de agosto de 2015 às 23:37, Eric Czech [email protected] escreveu:

Certamente, aqui está uma parte relevante e parece que tudo está bem
com make_scorer, mas não com uma função personalizada:

from sklearn.linear_model import LogisticRegressionfrom sklearn.grid_search import GridSearchCVfrom sklearn.cross_validation import StratifiedKFoldfrom sklearn.metrics import average_precision_score, make_scorerimport functools

res = []
clfs = []
para resposta em respostas:
X, y = d_in [recursos], d_in [resposta]
para i, (treinar, testar) em enumerar (StratifiedKFold (y, 5)):
X_train, y_train, X_test, y_test = X.iloc [trem], y.iloc [trem], X.iloc [teste], y.iloc [teste]
clf = LogisticRegression (penalty = 'l1')
grade = {
'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 ()

Vou trabalhar em uma versão independente que envolve alguma versão do
dados que estou usando também (mas vai demorar mais). Entretanto,
decapagem dessas funções personalizadas soa como uma boa pista - eu tentei
várias vezes novamente para ter certeza e trava 100% do tempo com um personalizado
função e 0% do tempo ao usar make_scorer com algum conhecido,
função métrica importada.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/scikit-learn/scikit-learn/issues/5115#issuecomment -131376298
.

Oh, é ipynb. Hmmm interessante. Sim, a decapagem pode ser um problema ..?

Em 15 de agosto de 2015 às 23:51, Joel Nothman joel. [email protected] escreveu:

E é isso em principal (ou seja, o script de nível superior sendo interpretado) ou
um módulo importado?

Em 15 de agosto de 2015 às 23:37, Eric Czech [email protected] escreveu:

Certamente, aqui está uma parte relevante e parece que tudo está bem
com make_scorer, mas não com uma função personalizada:

from sklearn.linear_model import LogisticRegressionfrom sklearn.grid_search import GridSearchCVfrom sklearn.cross_validation import StratifiedKFoldfrom sklearn.metrics import average_precision_score, make_scorerimport functools

res = []
clfs = []
para resposta em respostas:
X, y = d_in [recursos], d_in [resposta]
para i, (treinar, testar) em enumerar (StratifiedKFold (y, 5)):
X_train, y_train, X_test, y_test = X.iloc [trem], y.iloc [trem], X.iloc [teste], y.iloc [teste]
clf = LogisticRegression (penalty = 'l1')
grade = {
'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 ()

Vou trabalhar em uma versão independente que envolve alguma versão do
dados que estou usando também (mas vai demorar mais). Entretanto,
decapagem dessas funções personalizadas soa como uma boa pista - eu tentei
várias vezes novamente para ter certeza e trava 100% do tempo com um personalizado
função e 0% do tempo ao usar make_scorer com algum conhecido,
função métrica importada.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/scikit-learn/scikit-learn/issues/5115#issuecomment -131376298
.

Isso está em um caderno

Vou tentar importá-lo de um módulo e ver como isso funciona

Hmm o que você sabe, funciona bem quando definido fora do notebook.

Eu tenho essencialmente o mesmo código em execução no python 2.7 (eu precisava de uma lib mais antiga), bem como este código no python 3.4 e embora eu tenha o problema de suspensão no 2.7, independentemente de ser ou não uma função personalizada ou algo usando make_scorer, eu acho que isso resolve todos os meus problemas na versão mais recente, para que eu possa viver com soluções alternativas na versão antiga.

Posso fazer mais alguma coisa para descobrir por que as funções de decapagem definidas em um notebook podem ser um problema?

Bem, gostaríamos de entender:

  • A decapagem e retirada da picada geralmente é um problema para funções definidas localmente nessa plataforma ou estamos encontrando um obstáculo específico?
  • por que, se a decapagem é um problema, ela está suspensa em vez de levantar uma exceção? Você poderia tentar o monkey-patching ou similar, para ver se substituindo o pickle.dumps(function) check https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/externals/joblib/parallel. py # L150 com pickle.loads(pickle.dumps(function)) resulta em um erro? (Para explicar, esta é uma verificação de segurança para garantir a capacidade de separação antes de executar o multiprocessamento.)

@ogrisel pode estar interessado nisso.

Pelo que vi no Windows, notebooks têm interações estranhas com multiprocessamento.

Você já tentou apenas decapar e desfazer a função definida no mesmo notebook?

Hoje eu acidentalmente vi esta https://pythonhosted.org/joblib/parallel.html#bad -interaction-of-multiprocessing-and-third-party-libraries, não está relacionado?
Talvez você deva apenas atualizar para o python 3.4 ou mais recente?

Desculpe, saiu de férias longas. Para responder às suas perguntas:

  1. re @jnothman : Coloquei pickle.loads(pickle.dumps(function)) em parallel.py e uma instrução de impressão depois dele para ter certeza de que estava sendo executado de forma limpa e não houve problemas. Para ser claro, GridSearchCV.fit chamado do bloco de notas ainda travou como antes, sem nenhuma alteração (exceto para a instrução de impressão que adicionei, aparecendo 16 vezes com n_jobs = -1).
  2. re @amueller : Se estou entendendo corretamente, então corri algo assim no notebook sem problemas:
def test_function(x):
    return x**2
pickle.loads(pickle.dumps(test_function))(3)
# 9
  1. re @olologin : Estou no 3.4.3. Ou mais especificamente: '3.4.3 | Continuum Analytics, Inc. | (padrão, 6 de março de 2015, 12:07:41) n [GCC 4.2.1 (Apple Inc. build 5577)] '

Eu não li a conversa acima, mas gostaria de observar que este teste mínimo falha no build do Python 2.6 do travis, mas passou em uma configuração semelhante no meu PC ... (sugerindo que falha quando n_jobs = -1 está definido em uma máquina de núcleo único para versões antigas 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 por ter esse problema, fico feliz em fornecer detalhes se isso for ajudar

@ eric-czech Se você estiver no Python 3.4 ou 3.5, tente definir a seguinte variável de ambiente e reinicie seu programa Python:

export JOBLIB_START_METHOD="forkserver"

conforme explicado na documentação do

Têm o mesmo problema no OS X 10.11.4 e no Ubuntu 14.04 com o software mais recente instalado.

# 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)

Na verdade, este código não congela apenas se n_jobs=1 .

Isso agora deve funcionar por padrão no python 3 e ser uma correção habitual no python 2, certo @ogrisel ? Devemos fechar?

Se ele travar silenciosamente no Python 2 sem lançar qualquer aviso ou erro ("n_jobs> 1 não suportado no Python 2"), isso não é aceitável; podemos lançar um erro?

@amueller no Python 3 você pode seguir https://github.com/scikit-learn/scikit-learn/issues/5115#issuecomment -187683383 para contornar o problema, ou seja, ele não funcionará por padrão, mesmo no Python 3.

Não tenho certeza se devemos fechar porque o OP original parecia dizer que definir o joblib start_method para forkserver nem sempre funcionou ...

BTW, o xgboost é um conhecido, consulte https://github.com/scikit-learn/scikit-learn/issues/6627#issuecomment -206351138.

Edit: A mudança abaixo pode não corrigir as coisas. Houve uma mudança não relacionada que fiz também em como estava lidando com o multiprocessamento com Pathos que pode ter sido minha verdadeira solução.

Conserto rápido:
np.random.seed(0)

Explicação:
Eu também estava enfrentando esse problema, de forma mais aguda no conjunto de testes para auto_ml . Nas primeiras (2?) Vezes que executei o GridSearchCV, estava tudo bem, mas as execuções subsequentes travavam sem erros.

Acabei de definir np.random.seed(0) dentro de cada um dos meus testes, para garantir a reprodutibilidade enquanto ainda me dou a flexibilidade de reordenar os testes ao longo do tempo sem mexer com a aleatoriedade. Assim que fiz isso, todos os testes que travaram no erro GSCV começaram a funcionar novamente.

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

espero que isso ajude com a depuração!

Ambiente Dev:
Mac OS X (Sierra)
Python 2.7
Versões atualizadas de bibliotecas.

@ClimbsRocks bem, provavelmente é algum erro em seus estimadores. Informe-nos se tiver um exemplo reproduzível;)

@amueller : boa

Acho que provavelmente foi um problema ao usar a paralelização do GSCV, quando também estou usando a paralelização do Pathos em outras partes do programa. Essa é a única outra coisa relacionada que mudei na semana passada ou assim.

Desde então, refatorei para fechar e abrir mais completamente seu pool de multiprocessamento.

O que me faz pensar que não era apenas um bug em um dos estimadores é que, ao construir o conjunto de testes, cada um dos testes foi executado e aprovado individualmente. Foi apenas quando eu executei vários testes na mesma passagem que todos dependiam do GSCV que ele começou a travar.

Comentário anterior editado para observar esta incerteza.

se você combinar joblib com qualquer outra paralelização, é muito provável que ele trave e você não deve tentar isso.

Desculpe por subir neste tópico, mas também encontro esse problema.
Eu criei um kernel Python 3.5 e defini o método job lib start para forkserver, mas ainda tenho o problema.

Na verdade, nem mesmo funciona com n_jobs = 1. Vejo que ele computa, exceto para o último parâmetro.

Há alguma novidade ?

Na verdade, nem mesmo funciona com n_jobs = 1. Vejo que ele computa, exceto para o último parâmetro.

Isso é estranho e muito provavelmente não está relacionado a esse problema (que é cerca de n_jobs != 1 ). A melhor maneira de obter um bom feedback seria abrir um problema separado com um fragmento autônomo reproduzindo o problema.

Tenho certeza de que estou enfrentando esse problema sozinho. Depois de tentar muitas combinações, tudo o que faço com n_jobs> 1 simplesmente congela após algumas dobras. Estou em um laptop Ubuntu Linux com sklearn = 0.19.0, então esta é uma configuração diferente de outras que já li. Aqui está o código "ofensivo":

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')

Uma das coisas interessantes é que quando eu importo xgboost, recebo um aviso de depreciação no GridSearchCV como se ele não estivesse importando de model_selection. No entanto, estou no xgboost 0.62 e olhando para o repositório deles, parece que eles estão importando o GridSearchCV correto. Para ser claro, o aviso de depreciação não é o problema que me preocupa, mas sim o que está em mãos: o congelamento da execução com n_jobs> 1. Apenas apontando para o caso de poder ajudar.

você poderia fornecer dados para ajudar a replicar o problema?

Em 24 de agosto de 2017 às 20:29, Xavier Amatriain [email protected]
escrevi:

Tenho certeza de que estou enfrentando esse problema sozinho. Depois de tentar muitos
combinações, tudo o que faço com n_jobs> 1 simplesmente congela após alguns
dobras. Estou em um laptop Ubuntu Linux com sklearn = 0.19.0, então este é um
configuração diferente de outras que já li. Aqui está o
código "ofensivo":

`importar xgboost como xgb
de 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,
'subamostra': 0,8, 'colsample_bytree': 0,8, 'objetivo': ' binário: logístico '}
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') `

Uma das coisas interessantes é que quando eu importo xgboost, eu obtenho um
aviso de reprovação em GridSearchCV como se não estivesse importando de
model_selection. No entanto, estou no xgboost 0.62 e olhando para seus
repositório parece que eles estão importando o GridSearchCV correto. Ser estar
claro, o aviso de suspensão de uso não é o problema que me preocupa, mas sim
o que está em mãos: o congelamento da execução com n_jobs> 1. Apenas apontando em
caso isso pudesse ajudar.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/scikit-learn/scikit-learn/issues/5115#issuecomment-324597686 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAEz66DbfTlnU_-dcxLKa5zkrcZ-0qVOks5sbVCmgaJpZM4FqYlN
.

Claro, você pode baixar os arquivos exatos que estou usando em:
https://xamat.github.io/xgboost_train.csv
https://xamat.github.io/label_train.csv

HTTP404

Desculpe, houve um erro no primeiro link, agora deve ser corrigido. O segundo também deve estar ok, acabei de verificar.

Problema conhecido com xgboost, consulte https://github.com/scikit-learn/scikit-learn/issues/6627#issuecomment -206351138 por exemplo.

Para sua informação, o back-end loky no joblib vai se livrar desse tipo de problema, mas isso só estará disponível no scikit-learn 0.20.

Isso ainda é um bug? Estou tendo o mesmo problema com padrões (n_jobs = 1), bem como com pre_dispatch = 1, usando um RandomForestClassifier , com 80 combinações de parâmetros e ShuffleSplit CV (n = 20).

Ele também trava para um Pipeline ( SelectKBest(score_func=mutual_info_classif, k=10) seguido por RandomForestClassifier ), tanto na versão mais recente quanto na versão devel.

Deixe-me saber se vocês encontraram uma solução alternativa ou outros métodos de seleção de modelo que funcionam de forma confiável. Estou pensando em dar uma chance a scikit-optimize .

Você quer dizer n_jobs = 1 ou é um erro de digitação? Este problema é sobre n_jobs! = 1.

A melhor maneira de obter feedback de qualidade é fornecer uma maneira de reproduzir o problema. Abra um problema separado neste caso se o problema que você está vendo realmente é com n_jobs = 1.

Eu escrevi o que quis dizer, que é "multithreading ativado"
n_jobs! = 1 como em 'diferente de 1'. Equivalentemente, n_jobs> 1. Por exemplo, n_jobs = 4

Você está dizendo que não pode reproduzir o congelamento para n_jobs = 4?

Nesse caso, fornecerei o caso de teste dentro de um mês (estou mudando para uma nova máquina).

Em 12 de setembro de 2017, às 7h10, Loïc Estève < [email protected] [email protected] > escreveu:

Você quer dizer n_jobs = 1 ou é um erro de digitação? Este problema é sobre n_jobs! = 1.

A melhor maneira de obter feedback de qualidade é fornecer uma maneira de reproduzir o problema. Abra um problema separado neste caso se o problema que você está vendo realmente é com n_jobs = 1.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub https://github.com/scikit-learn/scikit-learn/issues/5115#issuecomment-328864498 ou ignore o tópico https://github.com/notifications/unsubscribe- auth / ABH-rd7wgU5lcS6oD5VMl0YOB8CXfSTJks5shpDZgaJpZM4FqYlN .

@smcinerney você é @raamana? Acho que @lesteve respondeu a @raamana que escreveu n_jobs=1 , o que parece não estar relacionado a esse problema.

Oh, desculpe, não, eu não sou @raamana. Sim, o problema de @raamana é diferente (mas provavelmente devido ao mesmo código)

Em 12 de setembro de 2017, às 9h23, Andreas Mueller < [email protected] [email protected] > escreveu:

@smcinerney https://github.com/smcinerney você está @raamana https://github.com/raamana ? Acho que @lesteve https://github.com/lesteve respondeu a @raamana https://github.com/raamana que escreveu n_jobs = 1, que parece não estar relacionado a esse problema.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub https://github.com/scikit-learn/scikit-learn/issues/5115#issuecomment-328905819 ou ignore o tópico https://github.com/notifications/unsubscribe- auth / ABH-rYKQA3L5ifINBX6enrk5oDIsf1Lqks5shrASgaJpZM4FqYlN .

Que pena, eu não queria misturar as coisas. Vou abrir outro problema (com código mínimo para reproduzi-lo), mas o GridSearchCV travar mesmo com o padrão n_jobs = 1 é uma preocupação maior (já que é padrão e deve funcionar) do que n_jobs> 1.

@raamana sim, é uma preocupação maior, mas também é improvável que seja causado por um problema relacionado.

@ eric-czech @jnothman
Então, se você decidir usar backend = 'threading'. Um método fácil sem alterar o código do sklearn seria usar o gerenciador de contexto parallel_backend e não alterar o método de ajuste do GSV.

from sklearn.externals.joblib import parallel_backend

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

PS: Não tenho certeza se "threading" funciona para todos os estimadores. Mas eu estava tendo o mesmo problema com meu estimador com GSV njob> 1 e usando isso funciona conforme o esperado para mim, sem alterar a biblioteca.

Sistema testado em:
MAC OS: 10.12.6
Python: 3.6
numpy == 1.13.3
pandas == 0.21.0
scikit-learn == 0.19.1

Hmm ... Pode haver alguns problemas de simultaneidade com o uso de back-end de threading em
pesquisa de grade, por exemplo, o bug em # 10329 cria condições de corrida ...

Em 22 de dezembro de 2017 às 03:59, Trideep Rath [email protected] escreveu:

@ eric-czech https://github.com/eric-czech @jnothman
https://github.com/jnothman
Então, se você decidir usar backend = 'threading'. Um método fácil sem
alterar o código do sklearn seria usar o gerenciador de contexto parallel_backend
e não mudança no método de ajuste do GSV.

de sklearn.externals.joblib import parallel_backend

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

PS: Não tenho certeza se "threading" funciona para todos os estimadores. Mas eu estava
tendo o mesmo problema com meu estimador com GSV njob> 1 e usando este
funciona conforme o esperado para mim, sem alterar a biblioteca.

Sistema testado em:
MAC OS: 10.12.6
Python: 3.6
numpy == 1.13.3
pandas == 0.21.0
scikit-learn == 0.19.1

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/scikit-learn/scikit-learn/issues/5115#issuecomment-353402474 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAEz64SfwYpjLU1JK0vukBRXJvWYs3LKks5tCo51gaJpZM4FqYlN
.

Caso: Usando backend como "threading" e usando Estimator que estende BaseEstimator e ClassifierMixin. Não tenho certeza de onde a condição de corrida é causada. Você pode elaborar.

De acordo com minha compreensão e experimentos, não observei nenhuma condição de corrida.

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 é chamado no clone (base_estimator). Isso faz uma deep_copy e tem uma cópia de seus próprios dados.

out é a saída do método _fit_and_score. Depois disso, todos os threads concluíram a execução do método de ajuste do estimador e relataram os resultados.

Os resultados são o que você obtém de GCV_clf.cv_results_

Você pode explicar, neste caso específico, por que isso causaria uma condição de corrida?

A condição de corrida ocorre se você estiver definindo parâmetros aninhados, ou seja, quando
um parâmetro alterado é um estimador e outro é um parâmetro desse
estimador.

Estou tendo o mesmo problema ao usar make_scorer em combinação com GridSearchCv e n_jobs=-1 no Win 7 com versões recentes:

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 obrigado por postar suas versões e plataforma! A melhor chance de obter algum feedback de boa qualidade é fornecer um snippet autônomo para reproduzir o problema. Leia https://stackoverflow.com/help/mcve para mais detalhes.

Enfrentando o mesmo problema no Win7 com quaisquer etapas de pré-processamento personalizadas.
Conjunto de ferramentas:

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))

você está ciente de que o multiprocessamento python não funcionará no Windows sem if __name__ == '__main__' ?

Sim eu estou. Desculpe, esqueci de dizer que estou usando o Jupyter.
Um script autônomo com if __name__ == '__main__' imprime os seguintes traços e ainda congela:

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, interessante. Por pura preguiça, coloquei todo o script em if __name__ == '__main__' e obtive os resultados do comentário anterior.

Agora coloquei apenas pipeline = make_pipeline... e foi executado com sucesso. Talvez seja a causa em Jupyter?

De qualquer forma, não sei se o comportamento do comentário anterior é válido e causado pelo uso indevido de if __name__ == '__main__' , ou se é culpa do SkLearn.

parece que não é um problema com nossa biblioteca, mas sobre a execução
contexto para multiprocessamento em windows ...

Isso é nojento. E, de fato, não consegui reproduzir nenhum dos problemas do Ubuntu com as mesmas versões de tudo. Obrigado pela ajuda!

Pode confirmar que este bug está vivo e bem.

Executando no Windows 10 em um notebook jupyter, Python3, Sklearn 0.19.1

Mesmo problema no Linux Mint (Ubuntu 16.10) Python 3.5

Tudo fica preso na primeira Epoch em cada núcleo, e as CPUs estão ociosas, então nenhum trabalho está sendo feito.

@MrLobs isso soa como um erro de decapagem, certo? coloque CustomTransformer em um arquivo python separado.

@ Chrisjw42 @avatsaev sem mais contexto, não podemos fazer muito.
@avatsaev parece que você está usando tensorflow?

@amueller sim é tensorflow

@avatsaev ainda não é informação suficiente. Você tem um exemplo mínimo para reproduzir? que blas você está usando, você está usando GPU, qual versão do scikit-learn você está usando ....

Ok, acontece que é porque estou usando TF GPU, então definir n_jobs como> 1 realmente não funciona, o que é normal porque eu só tenho uma GPU lol

sim, você realmente não deve usar n_jobs com TF de qualquer maneira.

Por que não?

@amueller , sim, colocar transformadores personalizados em um arquivo separado resolve

Seria possível para n_jobs! = 1 lançar um erro (ou pelo menos um aviso) nos ambientes em que vai travar? Acabei de encontrar esse problema em cadernos jupyter, e se eu fosse um usuário mais iniciante (como o resto da minha classe), nunca teria descoberto por que gridsearchcv ficava pendurado, na verdade, nosso professor até nos aconselhou a usar n_jobs = - 1 Se o problema aqui for conhecido, o pacote (keras ou sklearn, o que for) avisará que isso ocorrerá e evitará o travamento?

Acho que ninguém sabe em que ambiente isso vai se manter ... Não acredito que alguém tenha conseguido reproduzir esse bug de maneira confiável.

mas estamos trabalhando para melhorar nossa infraestrutura de multiprocessamento.
não está claro para mim se isso resolverá todos esses problemas.

@jnothman 👍

É ótimo ouvir isso!

Não sei por que isso está marcado como 0,21. Isso é resolvido em 0,20 na maioria dos casos. Acho que devemos encerrar isso e fazer com que as pessoas abram novas questões. Este é muito longo e não específico.

Acabei de encontrar o mesmo no AWS Ubuntu com jupyter ...

Usar o parallel_backend parece funcionar ...


from sklearn.externals.joblib import parallel_backend

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

@morienor se você pode reproduzir este problema com o scikit-learn 0.20.1, abra um novo problema com todos os detalhes necessários para que outra pessoa possa reproduzir o problema (o script completo com instruções de importação em um conjunto de dados aleatório falso) junto com todos os números de versão de python, scikit-learn, numpy, scipy e o sistema operacional.

Acabei de encontrar o mesmo no AWS Ubuntu com jupyter ...

Usar o parallel_backend parece funcionar ...


from sklearn.externals.joblib import parallel_backend

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

Isso funciona para mim! Muito obrigado!

@ jmq19950824 @morienor sim, mas não adianta usar threading backend devido ao GIL.

Acabei de encontrar o mesmo no AWS Ubuntu com jupyter ...

Usar o parallel_backend parece funcionar ...


from sklearn.externals.joblib import parallel_backend

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

o gênio trabalha para mim para

Esta página foi útil?
0 / 5 - 0 avaliações