Scikit-learn: adicionar pós-poda para árvores de decisão

Criado em 16 mar. 2016  ·  64Comentários  ·  Fonte: scikit-learn/scikit-learn

Freqüentemente sou questionado sobre a pós-poda. Freqüentemente, o uso de árvores únicas é importante para a interpretabilidade e a pós-poda pode ajudar tanto na interpretabilidade quanto no desempenho de generalização.
[Estou surpreso que não haja nenhum problema em aberto sobre isso, mas não consegui encontrar um]

Moderate New Feature help wanted

Comentários muito úteis

Olá a todos ,
Eu implementei:
Algoritmo CCP (Poda de complexidade de custo) em
sklearn-CART-Classification-model em Python,

Algoritmo ECP (poda de complexidade de erro) ativado
sklearn-CART-Regression-model em Python,

aqui está o link:
https://github.com/appleyuchi/Decision_Tree_Prune
você pode gostar.

Todos 64 comentários

Eu posso tentar isso :)

O título deste problema está relacionado https://github.com/scikit-learn/scikit-learn/issues/4630 .

Este problema # 941 também parece propor um método de poda para a árvore, mas o código mudou consideravelmente nesse ínterim, suponho.

Sobre o tópico de interpretabilidade, também foi publicado trabalho sobre a criação de árvores de decisão únicas de florestas aleatórias. Por mais contra-intuitivo que pareça, devido à não otimização dos algoritmos de árvore de decisão padrão, isso pode aparentemente fornecer uma árvore de decisão única que é interpretável e também classificadores / regressores melhores do que você obteria de outra forma.

@amueller Você poderia explicar esse problema um pouco? Eu quero trabalhar nisso.

na verdade, talvez a primeira coisa a fazer seja adicionar um critério de parada com base em informações mútuas ...

@lesshaste você pode dar uma citação? (Eu estive pensando sobre isso recentemente, droga, obviamente foi feito ^^)

@amueller Já se passou muito tempo desde que olhei para isso, mas:

Seção 2.2 de
"Extração de regra da floresta aleatória: os métodos RF + HC" de Morteza Mashayekhi e Robin Gras tem todas as citações relevantes que conheço. Informe-me se não tiver acesso a este documento.

Em uma nota apenas ligeiramente relacionada, lembro-me de olhar para http://blog.datadive.net/interpreting-random-forests/ com algum interesse.

na verdade, talvez a primeira coisa a fazer seja adicionar um critério de parada com base em informações mútuas ...

Uma adição fácil seria parar a construção quando p(t) i(t, s*) < beta , ou seja, quando a impureza ponderada p(t) i(t, s*) para a melhor divisão s* torna-se menor do que algum limite definido pelo usuário beta .

Freqüentemente sou questionado sobre a pós-poda. Freqüentemente, o uso de árvores únicas é importante para a interpretabilidade e a pós-poda pode ajudar tanto na interpretabilidade quanto no desempenho de generalização.

Eu acho que isso também pode ser benéfico para alguns algoritmos de ensemble como (gradiente) boosting, embora normalmente não esteja aumentando a precisão preditiva para ensembles de estilo bagging (por exemplo, florestas aleatórias).

A poda também pode ser útil para economizar memória e diminuir um pouco os tempos de previsão.

@amueller / others: @jmschrei e eu nos encontramos para discutir a questão da pós-poda algumas semanas atrás, e não tínhamos certeza de como isso se encaixaria na API scikit-learn atual. Geralmente, a pós-poda precisa de um conjunto de validação, mas isso não parece se encaixar bem com a forma como a biblioteca está organizada atualmente (ou seja, questões como a criação / origem do conjunto de validação e se isso seria um argumento adequado ou método vem à mente). Como você achava que isso seria implementado do ponto de vista da API?
Por enquanto, estou trabalhando para examinar o código splitter.pyx e adicionar os critérios de parada antecipada com base na impureza ponderada para GSoC enquanto penso no MAE.

Parece que houve alguma discussão sobre problemas de API em https://github.com/scikit-learn/scikit-learn/pull/941 , mas o módulo de árvore mudou um pouco e talvez devêssemos discutir novamente. Por um lado, temos parâmetros como max_leaf_nodes e max_depth para controlar um pouco o crescimento da árvore.

Eu estaria inclinado a definir a poda como um método separado. Na verdade, uma função separada que pega uma árvore e retorna a versão podada seria adequada para começar. Esta é a abordagem usada em https://github.com/ajtulloch/sklearn-compiledtrees para gerar código otimizado para árvores.

@ nelson-liu Com relação às opções de regularização, elas às vezes levam a subárvores com todos os nós pertencentes à mesma classe. Embora não seja uma poda no sentido de regularização, seria bom ter uma função para se livrar desses nós extras que apenas adicionam custo computacional durante a predição.

Quando você obteria uma subárvore com todos os nós prevendo a mesma classe? Você não faria uma divisão se não houvesse um ganho em seu critério.

Em essência, o que eu gostaria é um método do tipo 'início quente' para construir uma árvore, como se tivéssemos um início quente para construir uma floresta aleatória. Você deve ter um método para adicionar um único nó a uma árvore, mas ainda obter um estimador válido antes e depois de adicionar o nó. Isso permitiria aos usuários avaliar o desempenho das árvores no conjunto de avaliação à medida que o construíam, da mesma forma que você pode adicionar árvores a uma floresta aleatória, avaliando seu desempenho no conjunto de validação a cada vez. Isso não deve ser terrivelmente difícil de adicionar funcionalmente, o maior problema é apenas a API para isso. @ogrisel @glouppe , você tem alguma opinião?

@jmschrei
Eu quis dizer que uma divisão de 90:10 em 80: 0 e 10:10 não mudará o desempenho se a árvore parar aí.

@pixelou, outra coisa importante a considerar é se queremos que isso seja utilizável com GridSearchCV ... um método separado quebraria isso, eu acho.

@ Nelson-liu Desculpe, não fui claro: eu quis dizer que a maior parte do trabalho árduo é escrever os procedimentos de poda em si. A integração não deve ser muito difícil (mas não sou eu que faço isso, obviamente :-))

No topo da minha cabeça, vejo várias opções de integração:

  • as opções fornecidas ao construtor da árvore são então levadas em consideração por .fit
  • opções são dadas a .fit diretamente
  • um método .prune ou .post_prune separado deve ser chamado explicitamente
  • uma função prune_tree ou post_prune_tree separada pega a árvore e retorna outra árvore podada

Depende de você decidir sobre isso, mas acho que é possível escrever um método privado (classe?) Separado para remoção e disponibilizá-lo para a API como uma das soluções acima.

Observe que acabei de fornecer os pontos acima sem pensar mais ;-). 2 e 4 não são claramente a maneira de aprender de fazer as coisas, e você acabou de mencionar como o 3 pode ser um problema.

A primeira opção parece ser a mais consistente com o sklearn.

@ameuller @glouppe @GaelVaroquaux alguma opinião sobre a API para pós poda? Eu vejo essas três opções, a primeira das quais parece a melhor para mim. Só queria obter alguns esclarecimentos antes de começar a pensar sobre como trabalhar nisso:

  • as opções fornecidas ao construtor de árvore são então levadas em consideração por .fit
  • um método .prune ou .post_prune separado deve ser chamado após o ajuste
  • uma função prune_tree ou post_prune_tree separada pega a árvore e retorna outra árvore podada

Sim, a primeira opção é certamente a que melhor se adapta à nossa API.

Não é pré-poda se você faz no ajuste? Não devemos verificar a complexidade da árvore e usar a poda posterior para reduzi-la?

Comece com a terceira opção, então decida se as outras são adequadas ...

1 para isso

(quero dizer, o código de exemplo pode ajudar a decidir)

Não é pré-poda se você fizer no ajuste, se você construir a árvore completa e depois voltar e remover os nós. Eu concordo com @glouppe que o primeiro é a melhor opção, mas também concordo com @jnothman que, uma vez que o código dependerá de um método prune_tree ~ de qualquer maneira ~, pode ser melhor criar uma coisa autônoma durante os estágios de desenvolvimento.

Não é pré-poda se você fizer no ajuste, se você construir a árvore completa e depois voltar e remover os nós.

Presumi que o usuário gostaria de selecionar se deseja postar a poda ou não com base na árvore construída ...

Por exemplo, é assim que rpart faz isso - por um método prune separado que vai para trás e apara a árvore ...

Presumivelmente, você gostaria que o desempenho do conjunto de validação orientasse se / como podar a árvore.

Minha preocupação era - se os usuários quiserem dar uma olhada na árvore entre as operações fit e pós-poda, eles terão que caber novamente sem a pós-poda habilitada ...

Mas como você disse talvez isso não seja necessário se a necessidade de pós-poda for baseada no desempenho do conjunto de validação e não na decisão do usuário ...

@ nelson-liu Posso trabalhar nisso se você não estiver?

vá em frente, pode ser uma boa maneira de se familiarizar com o código da árvore. Definitivamente, não é uma tarefa fácil, então fique à vontade para perguntar se você precisa de ajuda ...

Obrigado @ nelson-liu.

Então, isso foi implementado ou ainda permanece?

@datavinci ainda está faltando.

Se ninguém estiver trabalhando neste recurso, gostaria de fazer isso comigo mesmo ou com @dalmia. OK?

Parece que isso está travado, então vá em frente.

Na quarta-feira, 19 de julho de 2017 às 14h32, avidale [email protected] escreveu:

Se ninguém estiver trabalhando neste recurso, eu gostaria de fazer isso sozinho ou
com @dalmia https://github.com/dalmia . OK?

-
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/6557#issuecomment-316524038 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/ADvEEOVYL_gQbMzWFixoHO1D0YfvuItCks5sPnXlgaJpZM4HybHH
.

Não acho que @dalmia tenha disponibilidade atualmente.

Em 20 de julho de 2017 às 08:01, Jacob Schreiber [email protected] escreveu:

Parece que isso está travado, então vá em frente.

Na quarta-feira, 19 de julho de 2017 às 14h32, avidale [email protected] escreveu:

Se ninguém estiver trabalhando neste recurso, eu gostaria de fazer isso sozinho
ou
com @dalmia https://github.com/dalmia . OK?

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
6557 # issuecomment-316524038>,
ou silenciar o tópico
gQbMzWFixoHO1D0YfvuItCks5sPnXlgaJpZM4HybHH>
.

>

-
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/6557#issuecomment-316531460 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAEz64HQd8rQr3u2hD0QFR-RxktyYZoaks5sPnzTgaJpZM4HybHH
.

Também estou vendo grandes subárvores prevendo a mesma classe. Mesmo a poda ingênua melhoraria a interpretabilidade em casos como esses (e não teria efeito nas previsões).

@cjmay isso mudaria as probabilidades previstas. Mas sim, adicionar qualquer tipo de poda seria bom;)

Seria bom ver benchmarks de pós-poda versus pré-poda. Acho que "min_impurity_decrease" é um critério de parada relativamente razoável. Ou você poderia pesquisar em grade n_leafs ... as pessoas geralmente pesquisam em grade o parâmetro de poda? (Eu imagino que sim). Seria interessante ver com que frequência isso dá resultados diferentes.

@amueller oh, entendo.

Ancioso!

Para alguns dos métodos de conjunto, isso poderia ser trabalhado naturalmente. Se houver ensacamento, a amostra OOB pode ser usada para validação e poda. Seria como oob_improvement_ é calculado em GradientBoostingClassifier

Alguém está trabalhando nisso agora?

Não que eu saiba

Alguém fez isso ???

alguém fez isso que poderia compartilhar seu código ...

remoção de complexidade de custo baseada em sklearn.decisiontreeclassifier ????

Alguém pode fazer a poda de complexidade de custo com base em sklearn.decisiontreeclassifier ()? Se não, vou perguntar novamente. Estou falando sério .......

Encontrei isto:
https://github.com/shenwanxiang/sklearn-post-prune-tree

Não tem certeza se é exatamente a poda de complexidade de custo?

@zanderbraam não é CCP

Olá a todos ,
Eu implementei:
Algoritmo CCP (Poda de complexidade de custo) em
sklearn-CART-Classification-model em Python,

Algoritmo ECP (poda de complexidade de erro) ativado
sklearn-CART-Regression-model em Python,

aqui está o link:
https://github.com/appleyuchi/Decision_Tree_Prune
você pode gostar.

@appleyuchi obrigado!
Acho um pouco difícil seguir a estrutura do código, principalmente porque os nomes dos arquivos e comentários estão em chinês. Também parece haver muitos códigos duplicados.

Eu não trabalho mais com DT, mas alguém deu uma olhada em https://github.com/beedotkiran/randomforestpruning-ismm-2017 ? Parece relevante para esta questão.

Uma árvore é apenas uma pequena floresta. Esta implementação não pode ser reduzida a árvores?

@appleyuchi Não tenho certeza se estou seguindo o que você está dizendo, mas não adotaremos uma implementação baseada em ir para JSON. Qualquer implementação no scikit-learn teria que funcionar diretamente com as estruturas de dados do scikit-learn.

@appleyuchi obrigado por seus esforços. Em relação ao quão complicado pode ser implementar esse recurso, reconhecemos que tocar na base do código da árvore não é necessariamente uma tarefa trivial. Houve esforços para mudar isso e ter uma implementação mais legível. Além disso, esse problema não é classificado como "Fácil" por esse motivo exato.

Espero que você encontre outros assuntos nos quais possa se interessar e continue o bom trabalho neles :)

Estou trabalhando neste problema com um algoritmo de poda de complexidade de custo (CPP). Vejo vários testes que podem ser usados ​​para verificar a poda de árvores:

  1. O aumento de alfa (no CPP) deve resultar em um número menor ou igual de nós.
  2. Certifique-se de que a árvore podada seja realmente uma subárvore da árvore original.

Que outros testes seriam apropriados para a poda de árvores?

@appleyuchi Obrigado por compartilhar! Minha preocupação é que, mesmo como chinês, ainda é muito difícil para mim seguir o código. Acho que é melhor ter o código mais modularizado para que outros possam aplicar sua implementação em quaisquer conjuntos de dados.

@ zhenyu-zhou
Porque quase todos vocês nunca leram o livro 《árvores de classificação e regressão》 cuidadosamente.

O primeiro autor deste livro já faleceu, então você não pode contatá-lo para perguntas.

O defeito deste livro é discutido em
http://www.dcc.fc.up.pt/~ltorgo/PhD/th4.pdf
ou
http://www.doc88.com/p-6445227043649.html

que apontam que a validação cruzada do algoritmo CCP / ECP falhará para conjuntos de dados pequenos e desequilibrados,
você deve compreender os materiais acadêmicos acima antes de implementá-los.

Analisei e resumi o defeito em:

https://blog.csdn.net/appleyuchi/article/details/84957220

O link do Github que forneço para CCP / ECP é apenas "estilo de aplicativo", NÃO do "estilo de variável inferior" do sklearn (o último será muito mais eficiente e rápido)
então eles rejeitam.

mesmo sendo um chinês, ainda é muito difícil para mim seguir o código. Acho que é melhor ter o código mais modularizado para que outros possam aplicar sua implementação em quaisquer conjuntos de dados.

Pode ser aplicado em muitos conjuntos de dados que testei, acho que você ainda NÃO clicou e leu as instruções no link do Github

@appleyuchi

Mas pode ser aplicado em qualquer conjunto de dados que você quiser, tenho certeza que você ainda NÃO clicou e leu as instruções no link

Você está ABSOLUTAMENTE ERRADO. Para resumir, só tenho uma pergunta para você: você fornece uma API limpa, como o sklearn fez?

Você não deve esperar que todos leiam todos os detalhes de seu código antes de usá-lo, e culpe os outros por isso, se você tratar seu código como uma biblioteca como sklearn. Essa é uma das razões pelas quais eles rejeitam o código. Considere isso quando estiver usando outras bibliotecas, tome sklearn como exemplo, se ele tiver apenas um monte de código independente para experimentos, o que requer um determinado formato de entrada, sem uma estrutura geral. Você precisa examinar cuidadosamente o código da biblioteca para determinar como dividir a lógica principal e aplicar ao seu conjunto de dados. Você vai usá-lo? Reconheço que o experimento é interessante, mas não é uma biblioteca. Eu só quero postar coisas em minha mente para melhorar o código, mas é muito difícil.

@ zhenyu-zhou

Você não deve esperar que todos leiam todos os detalhes do seu código antes de usá-lo e culpe os outros por isso,

você entendeu mal, o que eu disse é material, não código.
Observe que se refere a um livro, NÃO ao código que escrevi.

Quero dizer, 《árvores de classificação e regressão》 é um livro famoso, não o código que escrevi,
então isso não é culpa. e "você" se refere a novos contribuidores, NÃO ao membro existente do sklearn.

Eu só quero postar coisas em minha mente para melhorar o código, mas é muito difícil.

novamente, você deve ler o livro cuidadosamente antes de implementá-lo.

@ zhenyu-zhou

, se ele tiver apenas um monte de código autocontido para experimentos, o que requer um determinado formato de entrada, sem uma estrutura geral. Você precisa examinar cuidadosamente o código da biblioteca para determinar como dividir a lógica principal e aplicar ao seu conjunto de dados.

O estilo da API foi discutido vários meses atrás, quando você NÃO esteve aqui,
novamente,
o que implementei é "estilo de aplicativo", NÃO de "estrutura de dados inferior do sklearn"

Boa sorte.
问题

ps:A notificação deste problema foi cancelada porque estou ocupado.@me NÃO terá mais efeito.Se você tiver alguma dúvida, entre em contato comigo por e-mail.

@ameuller @glouppe @GaelVaroquaux alguma opinião sobre a API para pós poda? Eu vejo essas três opções, a primeira das quais parece a melhor para mim. Só queria obter alguns esclarecimentos antes de começar a pensar sobre como trabalhar nisso:

  • as opções fornecidas ao construtor de árvore são então levadas em consideração por .fit
  • um método .prune ou .post_prune separado deve ser chamado após o ajuste
  • uma função prune_tree ou post_prune_tree separada pega a árvore e retorna outra árvore podada
    você tem algum código para isso?
    obrigado
Esta página foi útil?
0 / 5 - 0 avaliações