Estou tendo muitos problemas para entender como funciona o class_weight
parâmetro na regressão logística do scikit-learn.
A situação
Quero usar a regressão logística para fazer a classificação binária em um conjunto de dados muito desequilibrado. As classes são rotuladas 0 (negativo) e 1 (positivo) e os dados observados estão em uma proporção de cerca de 19: 1 com a maioria das amostras tendo resultado negativo.
Primeira tentativa: preparando manualmente os dados de treinamento
Divido os dados que tinha em conjuntos separados para treinamento e teste (cerca de 80/20). Em seguida, fiz uma amostra aleatória dos dados de treinamento à mão para obter dados de treinamento em proporções diferentes de 19: 1; de 2: 1 -> 16: 1.
Em seguida, treinei a regressão logística nesses diferentes subconjuntos de dados de treinamento e a recordação plotada (= TP / (TP + FN)) como uma função das diferentes proporções de treinamento. Claro, o recall foi calculado nas amostras de TESTE disjuntas que tinham as proporções observadas de 19: 1. Observe que, embora eu tenha treinado os diferentes modelos em dados de treinamento diferentes, calculei a recuperação de todos eles nos mesmos dados de teste (separados).
Os resultados foram os esperados: o recall foi de cerca de 60% nas proporções de treinamento de 2: 1 e caiu bem rápido quando chegou a 16: 1. Havia várias proporções 2: 1 -> 6: 1 onde o recall estava decentemente acima de 5%.
Segunda tentativa: Pesquisa de grade
Em seguida, eu queria testar diferentes parâmetros de regularização e então usei GridSearchCV e fiz uma grade de vários valores do C
parâmetro, bem como do class_weight
parâmetro. Para traduzir minhas proporções n: m de amostras de treinamento negativo: positivo para a linguagem do dicionário, class_weight
pensei que apenas especificaria vários dicionários da seguinte forma:
{ 0:0.67, 1:0.33 } #expected 2:1
{ 0:0.75, 1:0.25 } #expected 3:1
{ 0:0.8, 1:0.2 } #expected 4:1
e eu também incluí None
e auto
.
Desta vez, os resultados foram totalmente malucos. Todas as minhas recuperações foram mínimas (<0,05) para cada valor de class_weight
exceto auto
. Portanto, só posso supor que meu entendimento de como definir o class_weight
dicionário está errado. Curiosamente, o class_weight
valor de 'auto' na pesquisa de grade foi em torno de 59% para todos os valores de C
, e imaginei que equilibra para 1: 1?
Minhas perguntas
Como você usa adequadamente
class_weight
para obter balanços diferentes nos dados de treinamento do que você realmente fornece? Especificamente, que dicionário devoclass_weight
usar para usar proporções n: m de amostras de treinamento negativas: positivas?Se você passar vários
class_weight
dicionários para o GridSearchCV, durante a validação cruzada ele irá reequilibrar os dados da dobra de treinamento de acordo com o dicionário, mas usar as verdadeiras proporções de amostra fornecidas para calcular minha função de pontuação na dobra de teste? Isso é crítico, pois qualquer métrica só é útil para mim se vier de dados nas proporções observadas.O que o
auto
valor declass_weight
faz em relação às proporções? Eu li a documentação e presumo que "equilibra os dados inversamente proporcionais à sua frequência" significa apenas 1: 1. Isso está correto? Se não, alguém pode esclarecer?
fonte
Respostas:
Em primeiro lugar, pode não ser bom ir apenas por recall. Você pode simplesmente atingir um recall de 100% classificando tudo como a classe positiva. Normalmente sugiro usar AUC para selecionar parâmetros e, em seguida, encontrar um limite para o ponto operacional (digamos, um determinado nível de precisão) no qual você está interessado.
Para saber como
class_weight
funciona: Penaliza erros em amostras declass[i]
com emclass_weight[i]
vez de 1. Portanto, maior peso da classe significa que você deseja colocar mais ênfase em uma classe. Pelo que você disse, parece que a classe 0 é 19 vezes mais frequente do que a classe 1. Portanto, você deve aumentar oclass_weight
da classe 1 em relação à classe 0, digamos {0: .1, 1: .9}. Seclass_weight
não somar 1, basicamente mudará o parâmetro de regularização.Para saber como
class_weight="auto"
funciona, você pode dar uma olhada nesta discussão . Na versão dev você pode usarclass_weight="balanced"
, o que é mais fácil de entender: basicamente significa replicar a classe menor até que você tenha tantas amostras quanto na classe maior, mas de forma implícita.fonte
A primeira resposta é boa para entender como funciona. Mas eu queria entender como deveria usá-lo na prática.
RESUMO
class_weight="balanced"
funciona decentemente na ausência de você querer otimizar manualmenteclass_weight="balanced"
você captura mais eventos verdadeiros (maior TRUE recall), mas também é mais provável que você receba alertas falsos (menor precisão TRUE)NB
O resultado pode ser diferente ao usar RF ou GBM. sklearn não tem
class_weight="balanced"
para GBM, mas lightgbm temLGBMClassifier(is_unbalance=False)
CÓDIGO
fonte