strings como recursos na árvore de decisão / floresta aleatória

64

Estou fazendo alguns problemas em uma aplicação de árvore de decisão / floresta aleatória. Estou tentando ajustar um problema que possui números e seqüências de caracteres (como o nome do país) como recursos. Agora, a biblioteca, o scikit-learn usa apenas números como parâmetros, mas quero injetar as strings, assim como elas carregam uma quantidade significativa de conhecimento.

Como lidar com esse cenário?

Posso converter uma string em números por algum mecanismo, como o hash no Python. Mas eu gostaria de saber as melhores práticas sobre como as seqüências de caracteres são tratadas nos problemas da árvore de decisão.

user3001408
fonte
Em caso de sckitlearn tenho visto que precisamos para codificar as variáveis categóricas, método de ajuste mais poderia lançar um erro dizendo ValueError: não poderia converter string para flutuar
Kar

Respostas:

56

Na maioria dos sistemas de aprendizado de máquina bem estabelecidos, as variáveis ​​categóricas são tratadas naturalmente. Por exemplo, em R você usaria fatores, em WEKA você usaria variáveis ​​nominais. Este não é o caso do scikit-learn. As árvores de decisão implementadas no scikit-learn usam apenas recursos numéricos e esses recursos são interpretados sempre como variáveis ​​numéricas contínuas .

Portanto, a simples substituição das seqüências de caracteres por um código de hash deve ser evitada, pois, sendo considerada um recurso numérico contínuo, qualquer codificação que você usará induzirá uma ordem que simplesmente não existe em seus dados.

Um exemplo é codificar ['vermelho', 'verde', 'azul'] com [1,2,3], produziria coisas estranhas, como 'vermelho' é menor que 'azul' e, se você fizer uma média de 'vermelho' e um 'azul' você receberá um 'verde'. Outro exemplo mais sutil pode acontecer quando você codifica ['baixo', 'médio', 'alto'] com [1,2,3]. No último caso, pode haver uma ordenação que faça sentido, no entanto, algumas inconsistências sutis podem ocorrer quando 'médio' não está no meio de 'baixo' e 'alto'.

Por fim, a resposta para sua pergunta está na codificação do recurso categórico em vários recursos binários . Por exemplo, você pode codificar ['vermelho', 'verde', 'azul'] com 3 colunas, uma para cada categoria, tendo 1 quando a categoria corresponder e 0 caso contrário. Isso é chamado de codificação one-hot, codificação binária, codificação one-of-k ou qualquer outra coisa. Você pode verificar a documentação aqui para codificar recursos categóricos e extração de recursos - hash e dict . Obviamente, a codificação one-hot expandirá seus requisitos de espaço e, às vezes, prejudica o desempenho.

rapaio
fonte
2
É a implementação do scikit que ele não manipula variáveis ​​categóricas corretamente. Recodificar como sugere esta resposta é provavelmente o melhor que você pode fazer. Usuários mais sérios podem procurar pacotes alternativos.
SmallChess 18/09/16
3
Pode-se usar sklearn.preprocessing.LabelBinarizer para a codificação one-hot da variável categórica.
gusuku
@rapaio Acho que a codificação binária não é a mesma codificação quente. A codificação binária é quando você representa 8 categorias com 3 colunas ou entre 9 e 16 categorias com 4 colunas e assim por diante. Estou errado?
Alok Nayak
o pacote patsy python irá lidar com a codificação one-hot de variáveis ​​categóricas. patsy.readthedocs.io/en/latest/quickstart.html
zhespelt
5
Não use LabelBinarizer, use sklearn.preprocessing.OneHotEncoder . Se você estiver usando pandas para importar e pré-processar seus dados, também poderá fazer isso diretamente usando pandas.get_dummies . É péssimo que o scikit-learn não suporte variáveis ​​categóricas.
Ricardo Cruz
11

Você precisa codificar suas strings como recursos numéricos que o sci-kit pode usar para os algoritmos de ML. Essa funcionalidade é tratada no módulo de pré-processamento (por exemplo, consulte sklearn.preprocessing.LabelEncoder para obter um exemplo).

Kyle.
fonte
4
rapaio explica em sua resposta por que isso iria obter um resultado incorreto
Keith
7

Geralmente, você deve codificar de uma só vez as variáveis ​​categóricas para os modelos de aprendizado de scikit, incluindo floresta aleatória. A floresta aleatória geralmente funciona bem sem a codificação one-hot, mas geralmente tem um desempenho melhor se você fizer a codificação one-hot. As variáveis ​​de codificação one-hot e "dummying" significam a mesma coisa neste contexto. O Scikit-learn possui sklearn.preprocessing.OneHotEncoder e o Pandas possui pandas.get_dummies para fazer isso.

No entanto, existem alternativas. O artigo "Beyond One-Hot" no KDnuggets explica muito bem por que você precisa codificar variáveis ​​categóricas e alternativas à codificação one-hot.

Existem implementações alternativas de floresta aleatória que não exigem codificação one-hot, como R ou H2O. A implementação em R é computacionalmente cara e não funcionará se seus recursos tiverem muitas categorias . O H2O funcionará com um grande número de categorias. O Continuum disponibilizou o H2O no Anaconda Python.

Há um esforço contínuo para que o scikit-learn lide diretamente com os recursos categóricos .

Este artigo tem uma explicação do algoritmo usado no H2O. Ele faz referência ao artigo acadêmico A Algoritmo de Árvore de Decisão Paralela em Fluxo e uma versão mais longa do mesmo artigo.

denson
fonte
5

Atualização de 2018!

Você pode criar um espaço de incorporação (vetor denso) para suas variáveis ​​categóricas. Muitos de vocês estão familiarizados com word2vec e fastext, que incorporam palavras em um espaço vetorial denso significativo. A mesma idéia aqui - suas variáveis ​​categóricas serão mapeadas para um vetor com algum significado.

Do artigo de Guo / Berkhahn :

A incorporação de entidade não apenas reduz o uso de memória e acelera as redes neurais em comparação com a codificação one-hot, mas, mais importante, mapeando valores semelhantes próximos um do outro no espaço de incorporação, revela as propriedades intrínsecas das variáveis ​​categóricas. Nós o aplicamos com sucesso em uma competição recente do Kaggle e conseguimos alcançar a terceira posição com recursos relativamente simples.

Os autores descobriram que representar variáveis ​​categóricas dessa maneira melhorou a eficácia de todos os algoritmos de aprendizado de máquina testados, incluindo floresta aleatória.

O melhor exemplo pode ser a aplicação da técnica do Pinterest para agrupar Pins relacionados:

insira a descrição da imagem aqui

O pessoal da fastai implementou casamentos categóricos e criou um post muito bom com o caderno de demonstração complementar .

Detalhes adicionais e explicação

Uma rede neural é usada para criar os embeddings, ou seja, atribuir um vetor a cada valor categórico. Depois de ter os vetores, você poderá usá-los em qualquer modelo que aceite valores numéricos. Cada componente do vetor se torna uma variável de entrada. Por exemplo, se você usou vetores 3D para incorporar sua lista categórica de cores, poderá obter algo como: vermelho = (0, 1,5, -2,3), azul = (1, 1, 0) etc. Você usaria três insira variáveis ​​em sua floresta aleatória correspondentes aos três componentes. Para coisas vermelhas, c1 = 0, c2 = 1,5 e c3 = -2,3. Para coisas azuis, c1 = 1, c2 = 1 e c3 = 0.

Na verdade, você não precisa usar uma rede neural para criar embeddings (embora eu não recomendo evitar a técnica). Você é livre para criar seus próprios casamentos à mão ou por outros meios, quando possível. Alguns exemplos:

  1. Mapeie cores para vetores RGB.
  2. Mapeie localizações para vetores latentes / longos.
  3. Em um modelo político dos EUA, mapeie as cidades para alguns componentes vetoriais que representam alinhamento esquerda / direita, carga tributária etc.
Pete
fonte
OK legal, mas a menos que eu tenha perdido alguma coisa, isso significa que as redes começam a terminar. Como criar uma incorporação e depois passar essa incorporação para um Forrest? Eu acho que você precisa treinar uma rede inteira com todos os recursos e, em seguida, pegar as primeiras camadas e usá-las como recurso de entrada no Forrest. Não está claro como isso seria feito.
Keith
@Kith com uma rede neural é usada para criar os embeddings, ou seja, atribuir um vetor a cada valor categórico. Depois de ter os vetores, você poderá usá-los em qualquer modelo que aceite valores numéricos. Cada componente do vetor se torna uma variável de entrada. Por exemplo, se você usou vetores 3D para incorporar sua lista categórica de cores, poderá obter algo como: vermelho = (0, 1.5, -2.3), azul = (1, 1, 0)etc. Você usaria três variáveis ​​de entrada em sua floresta aleatória correspondentes aos três componentes. Para coisas vermelhas, c1 = 0, c2 = 1,5 e c3 = -2,3. Para coisas azuis, c1 = 1, c2 = 1 e c3 = 0.
Pete
Eu entendo totalmente o conceito, pois é bem simples. Quero dizer, como isso seria feito na implementação? O notebook de demonstração fast.ai que você vincula possui um pouco com um RandomForestRegressor no final, mas eu realmente não vejo como isso adiciona os embeddings.
Keith
Eu acho que esse pode ser um bom exemplo de código no Keras github.com/entron/entity-embedding-rossmann
Keith
3

Você pode usar variáveis ​​fictícias nesses cenários. Com o panda, panda.get_dummiesvocê pode criar variáveis ​​fictícias para as seqüências de caracteres que deseja colocar na Árvore de Decisão ou na Floresta Aleatória.

Exemplo:

import pandas as pd
d = {'one' : pd.Series([1., 2., 3.,4.], index=['a', 'b', 'c','d']),'two' :pd.Series(['Paul', 'John', 'Micheal','George'], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)

df_with_dummies= pd.get_dummies(df,columns=["two"],drop_first=False)
df_with_dummies
ozn
fonte
2

Transforme-os em números, por exemplo, para cada país único, atribuindo um número único (como 1,2,3 e ...)

Também não é necessário usar a codificação One-Hot (também conhecida como variáveis ​​fictícias) ao trabalhar com floresta aleatória, porque as árvores não funcionam como outro algoritmo (como regressão linear / logística) e não funcionam à distância (elas trabalhe para encontrar uma boa divisão para seus recursos), portanto, NÃO É NECESSÁRIO para a codificação One-Hot

Arash Jamshidi
fonte
11
Na verdade, depende do algoritmo específico que treina a árvore. Em particular, o scikit NÃO suporta variáveis ​​categóricas.
chuse