Scikit-learn: Sugestão: adicionar suporte para regressão logística não penalizada

Criado em 30 abr. 2016  ·  34Comentários  ·  Fonte: scikit-learn/scikit-learn

LinearRegression fornece OLS não penalizado e SGDClassifier , que oferece suporte a loss="log" , também oferece suporte a penalty="none" . Mas se você quiser a velha regressão logística não penalizada, terá que fingi-la definindo C em LogisticRegression como um número grande ou usar Logit de statsmodels em vez de.

Documentation Easy

Comentários muito úteis

Você está perguntando por que eu iria querer fazer regressão logística sem regularização? Porque (1) às vezes a amostra é grande o suficiente em proporção ao número de recursos que a regularização não vai comprar nada e (2) às vezes os coeficientes de melhor ajuste são de interesse, em oposição a maximizar a precisão preditiva.

Todos 34 comentários

você tem que fingir, definindo C em LogisticRegression para um grande número

Qual é o problema dessa abordagem?

Presumi que fosse inexato e mais lento do que uma implementação direta de regressão logística não penalizada. Estou errado?

Percebo que definir C muito alto, como a seguir, fará com que LogisticRegression.fit trave. Mas não sei se isso é um bug ou apenas uma propriedade inerente do algoritmo e sua implementação em um computador de 64 bits.

import numpy as np
from sklearn.linear_model import LogisticRegression

x = np.matrix([0, 0, 0, 0,  1, 1, 1, 1]).T
y =           [1, 0, 0, 0,  1, 1, 1, 0]

m = LogisticRegression(C = 1e200)
m.fit(x, y)
print m.intercept_, m.coef_

Percebo que definir C muito alto, como a seguir, fará com que LogisticRegression.fit trave

Sim, isso é esperado, pois o problema fica mal colocado quando C é grande. Os solucionadores iterativos são lentos com problemas mal apresentados.

Em seu exemplo, o algoritmo leva uma eternidade para atingir a tolerância desejada. Você precisa aumentar tol ou codificar max_iter .

@mblondel existe uma alternativa para "solucionadores iterativos"?
Você não obterá exatamente a opção não regularizada, certo?

@Kodiologist por que você quer isso?

Você está perguntando por que eu iria querer fazer regressão logística sem regularização? Porque (1) às vezes a amostra é grande o suficiente em proporção ao número de recursos que a regularização não vai comprar nada e (2) às vezes os coeficientes de melhor ajuste são de interesse, em oposição a maximizar a precisão preditiva.

Sim, essa foi a minha pergunta.

(1) não é verdade. Sempre comprará um solucionador mais rápido.

(2) está mais no domínio da análise estatística, que não é realmente o foco do scikit-learn. Acho que poderíamos adicionar isso, mas não sei qual solucionador usaríamos. Como um não estatístico, me pergunto para que serve quaisquer coeficientes que mudam com um pouco de regularização.

Não posso dizer muito sobre (1), pois computação não é meu forte. Para (2), sou um analista de dados com experiência em estatística. Sei que o scikit-learn se concentra no aprendizado de máquina tradicional, mas, na minha opinião, é o melhor pacote Python para análise de dados no momento, e acho que se beneficiará por não se limitar _muito_. (Eu também acho, seguindo Larry Wasserman e Andrew Gelman, que as estatísticas e o aprendizado de máquina se beneficiariam mutuamente se se misturassem mais, mas acho que é a sua própria lata de worms.) Todos os coeficientes mudarão com a regularização; é isso que a regularização faz.

Não me oponho a adicionar um solucionador sem regularização. Podemos verificar o que seria bom, ou apenas fiar e usar l-bfgs e verificar de antemão se está mal condicionado.

Sim, todos os coeficientes mudam com a regularização. Estou apenas curioso para saber o que você deseja fazer com eles depois.

Ei,
Qual é o status deste tópico? Eu estaria realmente interessado em uma regressão logística não penalizada. Desta forma, os valores de p significarão algo estatisticamente falando. Caso contrário, terei que continuar usando R 😢 para tais casos de uso ...
Obrigado,
Alex

Ou modelos de estado?

Que solucionadores você sugere implementar? Como isso seria diferente dos solucionadores que já temos com C -> infty?

Que solucionadores você sugere implementar? Como isso seria diferente dos solucionadores que já temos com C -> infty?

Você pode tentar olhar para R ou modelos de estatísticas para ter ideias. Não estou familiarizado com seus métodos, mas eles são razoavelmente rápidos e não usam nenhuma regularização.

Sim, os modelos de estatísticas também funcionam se você usar o algoritmo QR para inversão de matriz. Meu caso de uso gira em torno da interpretabilidade do modelo. Para desempenho, eu definitivamente usaria regularização.

Não acho que precisamos adicionar nenhum novo solucionador ... A regressão logística não tem uma solução de forma fechada, o que significa que o modelo de estatísticas deve usar um solucionador iterativo de algum tipo também (meu palpite seria mínimos quadrados reponderados iterativos, mas Eu não verifiquei). Definir C=np.inf (ou equivalentemente alpha = 0 ) deve, em princípio, funcionar com nossos solucionadores atuais. Minha recomendação seria mudar para o solucionador L-BFGS ou Newton-CG, já que liblinear pode realmente ser muito lento nesta configuração. Talvez possamos adicionar uma opção solver="auto" e mudar automaticamente para uma delas quando C=np.inf ou equivalentemente penalty="none" ?

estamos mudando o solucionador padrão para lbfgs em # 10001 fwiw

Para as pessoas que realmente querem regressão logística não regularizada (como eu). Eu tenho que me contentar em usar modelos de estatísticas e fazer uma classe de invólucro que imita a API SKLearn.

Alguma atualização sobre isso? Este é um grande obstáculo à minha vontade de recomendar o scikit-learn às pessoas. Também não é nada óbvio para quem vem de outras bibliotecas que o scikit-learn faz a regularização por padrão e que não há como desativá-lo.

@shermstats sugestões de como melhorar a documentação sobre isso? Eu concordo que pode não ser muito óbvio.
O l-bfgs permite C=np.inf ?

Você pode especificar C=np.inf , embora dê o mesmo resultado que C=large value . No exemplo que experimentei, deu um ajuste melhor do que o modelo estatístico e o modelo estatístico falhou em convergir com a maioria das outras sementes aleatórias:

from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
import statsmodels.api as sm

X, y = make_classification(random_state=2)
lr = LogisticRegression(C=np.inf, solver='lbfgs').fit(X, y)


logit = sm.Logit(y, X)
res = logit.fit()
Optimization terminated successfully.
         Current function value: 0.167162
         Iterations 10
from sklearn.metrics import log_loss
log_loss(y, lr.predict_proba(X))
log_loss(y, res.predict(X))
0.16197793224715606
0.16716164149746823

Portanto, eu diria que devemos apenas documentar que você pode obter um modelo não penalizado definindo C grande ou np.inf.

Eu sugiro adicionar ao docstring e ao guia do usuário
"O modelo LogisticRegregression é penalizado por padrão. Você pode obter um modelo não penalizado definindo C = np.inf e solver = 'lbfgs'."

deu um ajuste melhor do que o modelo estatístico e o modelo estatístico falhou em convergir com a maioria das outras sementes aleatórias

R's glm é mais maduro e pode servir para uma melhor comparação.

Eu sugiro adicionar ao docstring e ao guia do usuário
"O modelo LogisticRegregression é penalizado por padrão. Você pode obter um modelo não penalizado definindo C = np.inf e solver = 'lbfgs'."

Por que não adicionar allow penalty = "none" a la SGDClassifier ?

@Kodiologist Não me oponho a adicionar penalty="none" mas não tenho certeza de qual é o benefício de adicionar uma opção redundante.
E acho que gostaríamos de fazer comparações com glm. Não estou muito familiarizado com o glm, então provavelmente não sou uma boa pessoa para fazer a comparação. No entanto, estamos otimizando a perda de log, portanto, não deve haver realmente nenhuma diferença. Talvez eles implementem diferentes solucionadores, então ter um benchmark seria bom.

Não me oponho a adicionar penalty="none" mas não tenho certeza de qual é o benefício de adicionar uma opção redundante.

  1. Torna-se mais claro como obter um modelo não penalizado.
  2. Torna-se mais claro para o leitor o que o código que está usando um modelo não penalizado está tentando fazer.
  3. Ele permite que o sklearn mude sua implementação de modelos não regulamentados no futuro sem quebrar o código das pessoas.

Se você sentir que aumenta a capacidade de descoberta, podemos adicioná-lo, e 3 é um ponto válido (embora não possamos realmente mudar isso sem provavelmente depreciações, consulte a alteração atual do solucionador).
Você quer enviar um PR?

Não tenho macacões redondos para isso; desculpa.

@Kodiologist pelo menos você me ensinou um idioma que eu não conhecia;)

Então, abra para contribuidores: adicione penalty='none' como uma opção. Também é possível verificar quais solucionadores suportam isso / são eficientes com isso (provavelmente o liblinear não é) e restrinja a esses solucionadores.

Eu sugiro adicionar ao docstring e ao guia do usuário
"O modelo LogisticRegregression é penalizado por padrão. Você pode obter um modelo não penalizado definindo C = np.inf e solver = 'lbfgs'."

Isso parece razoável para mim. Eu também sugeriria colocar a primeira frase em negrito porque é legitimamente surpreendente para pessoas que vêm de outros ambientes de aprendizado de máquina ou análise de dados.

@shermstats Então @Kodiologist sugeriu adicionar penalty="none" para torná-lo mais explícito, o que seria apenas um apelido para C=np.inf . Faz sentido para mim tornar isso mais explícito dessa forma. Você tem alguma opinião sobre isso?
Então isso seria o que está na documentação. E eu concordo que negrito pode ser uma boa ideia.
Eu acho que para alguém com um histórico de ML isso é (talvez?) Esperado, para alguém com um histórico de estatísticas, isso parece muito surpreendente.

Exatamente! Eu tenho um histórico de estatísticas e trabalhei com muitas pessoas de estatísticas vindas de R ou mesmo de interfaces de apontar e clicar, e esse comportamento é muito surpreendente para nós. Acho que, por enquanto, penalty=None (não tenho certeza sobre "none" vs. None ) é uma boa solução. No futuro, devemos ter um solucionador separado que é chamado automaticamente para a regressão logística não penalizada para evitar os problemas descritos por @mblondel .

Desculpe, que problema você quer dizer? Estamos mudando para l-bfgs por padrão e também podemos mudar internamente o solucionador para l-bfgs automaticamente se alguém especificar penalty='none' (geralmente, Nenhum é um token especial que usamos para parâmetros obsoletos, mas paramos fazendo isso. Ainda assim, 'nenhum' seria mais consistente com o resto da biblioteca).
Precisamos de solver="auto" qualquer maneira, portanto, alterar o solucionador com base na penalidade não deve ser um problema.

Esse problema , que se refere ao algoritmo iterativo se tornando muito lento para grandes C. Não sou um especialista em análise numérica, mas se l-bfgs impede que ele diminua a velocidade, então essa parece a solução certa. penalty='none' também parece a maneira certa de lidar com isso.

@shermstats sim, com l-bfgs isso não parece ser um problema. Eu não executei benchmarks extensos, entretanto, e não terei tempo para fazê-lo. Se alguém quiser executar benchmarks, isso seria de grande ajuda.

Se penalidade = 'nenhum' deve ser incluído, sugiro adicionar ao guia do usuário o mesmo aviso sobre colinear X como para OLS (em particular para recursos codificados one-hot).

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