Melhore a classificação com muitas variáveis ​​categóricas

37

Estou trabalhando em um conjunto de dados com mais de 200.000 amostras e aproximadamente 50 recursos por amostra: 10 variáveis ​​contínuas e as outras ~ 40 são variáveis ​​categóricas (países, idiomas, campos científicos etc.). Para essas variáveis ​​categóricas, você tem, por exemplo, 150 países diferentes, 50 idiomas, 50 campos científicos, etc.

Até agora, minha abordagem é:

  1. Para cada variável categórica com muitos valores possíveis, pegue apenas a que possui mais de 10000 amostras que recebem esse valor. Isso reduz para 5 a 10 categorias em vez de 150.

  2. Crie uma variável fictícia para cada uma das categorias (se 10 países, em seguida, para cada amostra, adicione um vetor binário de tamanho 10).

  3. Alimente um classificador de floresta aleatório (valide cruzadamente os parâmetros etc ...) com esses dados.

Atualmente, com essa abordagem, eu só consigo obter 65% de precisão e sinto que mais pode ser feito. Especialmente, não estou satisfeito com o meu 1), pois sinto que não deveria remover arbitrariamente os "valores menos relevantes" de acordo com o número de amostras que eles têm, porque esses valores menos representados poderiam ser mais discriminatórios. Por outro lado, minha RAM não pode permitir adicionar 500 colunas * 200000 linhas aos dados, mantendo todos os valores possíveis.

Você teria alguma sugestão para lidar com tantas variáveis ​​categóricas?

Bertrand R
fonte
2
Se você ainda estiver interessado, verifique minha resposta sobre redução de dimensionalidade e minha resposta sobre classificação hierárquica .
Aleksandr Blekh
11
Quando você diz "criar variável fictícia para cada uma das categorias" , parece que você está usando Python e não R? A floresta aleatória R pode lidar nativamente com categorias, também com consequente redução de memória. Tente R.
smci
Consulte também stats.stackexchange.com/questions/146907/…
kjetil b halvorsen

Respostas:

20

1) As florestas aleatórias devem ser capazes de lidar com valores categóricos de forma nativa; portanto, procure uma implementação diferente para que você não precise codificar todos esses recursos e usar toda a sua memória.

2) O problema com os recursos categóricos de alta cardinalidade é que é fácil se ajustar a eles. Você pode ter dados suficientes para que isso não seja um problema, mas tenha cuidado.

3) Sugiro olhar para a seleção aleatória de recursos baseados em florestas, usando o método proposto por Brieman ou contrastes artificiais . O método de contrastes artificiais (ACE) é interessante porque compara a importância do recurso à importância de uma versão embaralhada de si mesma que combate alguns dos problemas de alta cardinalidade. Existe um novo artigo "Florestas aleatórias guiadas por módulo" que pode ser interessante se você tiver muitos outros recursos, pois utiliza um método de seleção de recursos que conhece grupos de recursos altamente correlacionados.

4) Outra opção usada em algum momento é ajustar o algoritmo para que ele use as malas fora da bolsa para fazer a seleção final do recurso depois de ajustar as divisões nas malas na bolsa, o que às vezes ajuda a combater o excesso de ajustes.

Existe uma implementação de ás quase completa aqui e eu tenho uma implementação de memória eficiente / rápida em rf que lida com variáveis ​​categóricas nativamente aqui ... a opção -evaloob suporta a opção 4 Estou trabalhando para adicionar suporte para o ACE e algumas outras rf com base em métodos de seleção de recursos, mas ainda não foi concluído.

Ryan Bressler
fonte
4
Todas essas sugestões são interessantes, eu concordo que a floresta aleatória deve lidar com variáveis ​​categóricas nativas, mas o scikit-learn não ... Acho que essa é uma das principais falhas do scikit. Vou testar seu código nos meus dados para ver o que acontece e veremos suas outras sugestões!
Bertrand.
11
Experimente a implementação do R. Executá-lo é um liner. A leitura dos dados é extremamente fácil e há uma nova implementação paralela, extremamente rápida e eficiente em termos de memória: r-bloggers.com/… Por outro lado. Suas aulas estão desequilibradas? Na implementação de r, você pode aumentar cada árvore a partir de uma amostra de bootstrap equilibrada sampsize = c (x, x). Isso produziu melhores classificações binárias para mim. Você pode brincar com os tamanhos e ajustar a classificação com muita facilidade usando as saídas R da matriz de confusão OOB.
JEquihua 26/04
2
A implementação randomForest de R permite fatores com um máximo de 32 níveis. O scikit-learn é menos restritivo, desde que você crie primeiro variáveis ​​fictícias (consulte a pandas.get_dummiesfunção). A implementação de floresta aleatória do H2O teve um desempenho muito bom para mim (consulte 0xdata.com/docs/master/model/rf ).
precisa
11
existe uma implementação mais recente e mais rápida de floresta aleatória, o pacote é chamado de guarda florestal. Grandes coisas realmente. Ordens de magnitude mais rápidas e não têm o limite de 32 níveis.
marbel
6

Em vez de dummificar suas categorias, por que você não usaria simplesmente uma única variável numérica para cada uma? No contexto de florestas aleatórias, sempre me perguntei sobre as consequências de fazer isso (porque concordo que parece suspeito introduzir ordinalidade em dados categóricos com os quais, se freqüentemente não faz sentido), mas na prática (pelo menos com a implementação de RFs do scikit-learn que tenho usado), observei muitas vezes que isso não faz diferença nos resultados (não sei por que).

cjauvin
fonte
11
Isso é bom para recursos categóricos com n <= 3, pois você pode gerar todas as mesmas divisões que faria considerando o recurso nativamente como categórico. Para n maior, é possível obter conjuntos de divisões equivalentes à divisão categórica, mas o algoritmo pode ou não encontrá-los com a mesma eficiência ... no entanto, se você dividir o recurso em n recursos numéricos, também estará reduzindo a eficiência com que o algoritmo pode encontrar divisões. Alguém precisa adicionar suporte a variáveis ​​categóricas na implementação do scikit-learn, pois é ótimo caso contrário.
precisa saber é o seguinte
Eu concordo com você quando você diz que parece suspeito introduzir ordinalidade em dados categóricos ... Prefiro não precisar fazer isso, mas pelo menos posso tentar e ver o que acontece!
Bertrand.
4
Eu tive uma longa discussão sobre esta questão na lista de discussão do sklearn (você pode ler partes dela aqui: mail-archive.com/[email protected]/… ). A opinião de um dos implementadores era que, com árvores suficientemente profundas, os recursos categóricos codificados em ordinais podem funcionar razoavelmente bem (além de serem mais eficientes em termos computacionais). De qualquer forma, se você tentar, eu ficaria muito interessado em ouvir sobre seus resultados / conclusões, pois esse é um problema que eu continuo encontrando.
precisa saber é
11
Então, tentei manter uma única variável numérica para as categóricas, e ela realmente funciona surpreendentemente bem e muito melhor do que adicionar um grande número de entradas binárias ... Também tentei classificar os valores de acordo com a média wrt no destino . E ele funciona bem também
Bertrand R
Não estou surpreso com isso, na verdade ... está alinhado com o que observei em algumas configurações diferentes, embora, a julgar pelo número de votos positivos, essa seja uma ideia bastante contra-intuitiva.
precisa saber é o seguinte
5

Eu acho que você deve considerar uma / mais técnica (s) de redução variável . Ele se livra dos preditores não tão influentes.

Eu tenho lido muito sobre pré-processamento de dados e é uma ótima solução para reduzir o n ° de suas variáveis.

Minhas sugestões são as seguintes:

  • para variáveis ​​qualitativas , substitua os valores ausentes pela categoria "ausente". Pode introduzir viés se os dados não estiverem faltando aleatoriamente, mas pelo menos você terá todas as suas observações intactas e a falta poderá revelar um comportamento diferente.
  • elimine preditores de variância zero ou preditores de variância quase zero (tenha cuidado para não eliminar variáveis ​​fictícias com categorias desequilibradas altas que podem separar seu Y com eficiência. Faça alguns gráficos para as variáveis ​​que você acha que são importantes). Em R, você pode usar a 'nzv'função do 'caret'pacote. Isso reduzirá bastante sua dimensão de dados.
  • eliminar preditores correlacionados . Use a matriz de correlação de Kendall porque é mais adequado construir na presença de variáveis ​​categóricas. A desvantagem é que você deve transformar todos os seus vars nominais em categóricos.
  • existem métodos de seleção de recursos que reduzirão ainda mais seu número (clustering - você escolhe um único representante de cada cluster, a regressão do LASSO, etc ...). Ainda não tive a chance de testá-los porque as outras etapas reduziram minhas variáveis ​​para menos de 100.

Além disso, eu sugeriria o uso do algoritmo AdaBoost em vez do RF. Pessoalmente, as pesquisas que fiz me deram coeficientes de Gini muito semelhantes para esses dois métodos. A parte boa do AdaBoost é que, no R, ele lida com as observações ausentes. Então você pode pular o primeiro passo desta lista

Espero que tenha ajudado um pouco. Boa sorte

Lorelai
fonte
4

Você pode considerar modelos de efeitos mistos. Eles são populares nas ciências sociais devido ao seu desempenho em dados categóricos de alta cardinalidade, e eu os usei para criar ótimos modelos preditivos que superam as abordagens populares de aprendizado de máquina, como árvores com gradiente, florestas aleatórias e regressão logística regularizada com rede elástica. A implementação mais conhecida é o pacote lme4 do R; a função que você usaria para classificação é glmer, que implementa regressão logística de efeitos mistos. Você pode ter problemas com a escala do seu conjunto de dados, mas eu fiz 80k linhas com 15 recursos sem muita dificuldade.

Paulo
fonte
2
  1. Quando você diz "criar variável fictícia para cada uma das categorias" , parece que você está usando Python e não R? A floresta aleatória R pode lidar nativamente com categorias, também com consequente redução de memória. Tente R.

  2. Em seguida, você não precisa remover / mesclar manualmente os níveis categóricos, isso soa como uma grande dor. E mesmo se você fez, você não tem garantia de que as categorias mais populosas são as mais preditivas. Controle a complexidade da floresta aleatória com o tamanho do nó : inicie com um tamanho de grande e reduza-o progressivamente (essa é a pesquisa por hiperparâmetro).

  3. A seleção de variáveis ​​será útil. @lorelai dá boas recomendações. Tente eliminar recursos inúteis (de baixa importância ou altamente correlacionados). A construção de árvores é quadrática em relação ao número de recursos, portanto, se você eliminar um terço, pagará dividendos.

smci
fonte
0

Você deve olhar para o pacote H2O.ai. Ele lida com variáveis ​​categóricas prontas para uso sem precisar fazer nenhuma codificação (verifique se as variáveis ​​são fatores).

Gosto particularmente da implementação do Gradient Boosted Machine (GBM), porque é possível analisar a importância da variável após a construção do modelo. Os GBMs também têm o bom recurso de serem resistentes a sobreposições.

Se você deseja explorar outros modelos, eles têm: GLM, Random Forest, Naive Bayes, Deep Learning, etc.

Consulte: http://docs.h2o.ai/h2o/latest-stable/h2o-docs/data-science/gbm.html

Também é fácil de instalar (Windows, Linux, Mac) e fácil de executar com APIs usando R, Python, Java e Scala.

Ele pode usar vários núcleos para acelerar as coisas.

Em um futuro próximo, eles oferecerão suporte a GPUs.

Também é de código aberto e gratuito (existe suporte para empresas).

Clem Wang
fonte