Posso extrair as regras de decisão subjacentes (ou 'caminhos de decisão') de uma árvore treinada em uma árvore de decisão como uma lista textual?
Algo como:
if A>0.4 then if B<0.2 then if C>0.8 then class='X'
Obrigado pela ajuda.
python
machine-learning
scikit-learn
decision-tree
random-forest
Dror Hilman
fonte
fonte
Respostas:
Eu acredito que esta resposta é mais correta do que as outras respostas aqui:
Isso imprime uma função Python válida. Aqui está um exemplo de saída para uma árvore que está tentando retornar sua entrada, um número entre 0 e 10.
Aqui estão alguns obstáculos que eu vejo em outras respostas:
tree_.threshold == -2
para decidir se um nó é uma folha não é uma boa ideia. E se for um nó de decisão real com um limite de -2? Em vez disso, você deve olhar paratree.feature
outree.children_*
.features = [feature_names[i] for i in tree_.feature]
trava com a minha versão do sklearn, porque alguns valores detree.tree_.feature
são -2 (especificamente para nós de folha).fonte
print "{}return {}".format(indent, tree_.value[node])
deve ser alterado paraprint "{}return {}".format(indent, np.argmax(tree_.value[node][0]))
para a função retornar o índice de classe.RandomForestClassifier.estimators_
, mas não consegui descobrir como combinar os resultados dos estimadores.print "bla"
=>print("bla")
Criei minha própria função para extrair as regras das árvores de decisão criadas pelo sklearn:
Essa função começa primeiro com os nós (identificados por -1 nas matrizes filhas) e depois localiza recursivamente os pais. Eu chamo isso de 'linhagem' de um nó. No caminho, pego os valores necessários para criar a lógica SAS if / then / else:
Os conjuntos de tuplas abaixo contêm tudo o que preciso para criar instruções if / then / else do SAS. Não gosto de usar
do
blocos no SAS, e é por isso que crio uma lógica que descreve o caminho inteiro de um nó. O número inteiro único após as tuplas é o ID do nó do terminal em um caminho. Todas as tuplas anteriores se combinam para criar esse nó.fonte
(0.5, 2.5]
. As árvores são feitas com particionamento recursivo. Não há nada impedindo que uma variável seja selecionada várias vezes.Modifiquei o código enviado por Zelazny7 para imprimir algum pseudocódigo:
se você chamar
get_code(dt, df.columns)
o mesmo exemplo, obterá:fonte
(threshold[node] != -2)
para( left[node] != -1)
(semelhante ao método a seguir para obter ids de nós filhos)O Scikit learn introduziu um novo e delicioso método chamado
export_text
na versão 0.21 (maio de 2019) para extrair as regras de uma árvore. Documentação aqui . Não é mais necessário criar uma função personalizada.Depois de ajustar seu modelo, você só precisa de duas linhas de código. Primeiro, importe
export_text
:Segundo, crie um objeto que conterá suas regras. Para tornar as regras mais legíveis, use o
feature_names
argumento e passe uma lista dos nomes dos recursos. Por exemplo, se seu modelo for chamadomodel
e seus recursos forem nomeados em um dataframe chamadoX_train
, você poderá criar um objeto chamadotree_rules
:Em seguida, basta imprimir ou salvar
tree_rules
. Sua saída ficará assim:fonte
Há um novo
DecisionTreeClassifier
métododecision_path
, na versão 0.18.0 . Os desenvolvedores fornecem uma explicação extensa (bem documentada) .A primeira seção do código na explicação passo a passo que imprime a estrutura da árvore parece estar OK. No entanto, modifiquei o código na segunda seção para interrogar uma amostra. Minhas alterações denotadas com
# <--
Editar As alterações marcadas
# <--
no código abaixo foram atualizadas no link passo a passo depois que os erros foram apontados nas solicitações de recebimento nº 8653 e nº 10951 . É muito mais fácil acompanhar agora.Altere
sample_id
para ver os caminhos de decisão para outras amostras. Eu não perguntei aos desenvolvedores sobre essas mudanças, apenas pareceu mais intuitivo ao trabalhar com o exemplo.fonte
Você pode ver uma árvore do dígrafo. Então,
clf.tree_.feature
eclf.tree_.value
são a matriz de nós que divide o recurso e a matriz de valores de nós, respectivamente. Você pode consultar mais detalhes nesta fonte do github .fonte
Só porque todos foram muito prestativos, adicionarei uma modificação às belas soluções de Zelazny7 e Daniele. Este é para python 2.7, com abas para torná-lo mais legível:
fonte
Os códigos abaixo são minha abordagem no anaconda python 2.7 mais um nome de pacote "pydot-ng" para criar um arquivo PDF com regras de decisão. Espero que seja útil.
um gráfico de árvore mostra aqui
fonte
Eu já passei por isso, mas eu precisava que as regras fossem escritas neste formato
Então adaptei a resposta de @paulkernfeld (obrigado) que você pode personalizar de acordo com sua necessidade
fonte
Aqui está uma maneira de converter a árvore inteira em uma única expressão python (não necessariamente legível por humanos) usando a biblioteca SKompiler :
fonte
Isso se baseia na resposta de @paulkernfeld. Se você possui um dataframe X com seus recursos e um dataframe de destino y com suas ressonâncias e deseja ter uma idéia de qual valor y terminou em qual nó (e também formiga para plotá-lo adequadamente), você pode fazer o seguinte:
não é a versão mais elegante, mas faz o trabalho ...
fonte
Este é o código que você precisa
Modifiquei o código mais curtido para recuar em um notebook jupyter python 3 corretamente
fonte
Aqui está uma função, imprimindo regras de uma árvore de decisão scikit-learn no python 3 e com deslocamentos para blocos condicionais para tornar a estrutura mais legível:
fonte
Você também pode torná-lo mais informativo, distinguindo-o a qual classe pertence ou mesmo mencionando seu valor de saída.
fonte
Aqui está minha abordagem para extrair as regras de decisão de uma forma que possa ser usada diretamente no sql, para que os dados possam ser agrupados por nó. (Com base nas abordagens dos pôsteres anteriores.)
O resultado serão
CASE
cláusulas subseqüentes que podem ser copiadas para uma instrução sql, ex.SELECT COALESCE(*CASE WHEN <conditions> THEN > <NodeA>*, > *CASE WHEN <conditions> THEN <NodeB>*, > ....)NodeName,* > FROM <table or view>
fonte
Agora você pode usar export_text.
Um exemplo completo de [sklearn] [1]
fonte
Código de Zelazny7 modificado para buscar SQL na árvore de decisão.
fonte
Aparentemente, há muito tempo, alguém já decidiu tentar adicionar a seguinte função às funções de exportação de árvore do scikit oficial (que basicamente suportam apenas export_graphviz)
Aqui está o seu commit completo:
https://github.com/scikit-learn/scikit-learn/blob/79bdc8f711d0af225ed6be9fdb708cea9f98a910/sklearn/tree/export.py
Não sei exatamente o que aconteceu com esse comentário. Mas você também pode tentar usar essa função.
Eu acho que isso justifica uma solicitação de documentação séria para o pessoal do scikit-learn documentar adequadamente a
sklearn.tree.Tree
API, que é a estrutura de árvore subjacente queDecisionTreeClassifier
expõe como seu atributotree_
.fonte
Basta usar a função sklearn.tree como esta
E, em seguida, procure na pasta do projeto o arquivo tree.dot , copie TODO o conteúdo e cole-o aqui http://www.webgraphviz.com/ e gere seu gráfico :)
fonte
Obrigado pela maravilhosa solução de @paulkerfeld. No topo de sua solução, para todos aqueles que querem ter uma versão serializada de árvores, é só usar
tree.threshold
,tree.children_left
,tree.children_right
,tree.feature
etree.value
. Como as folhas não têm divisões e, portanto, nenhum nome de recurso e filhos, seu espaço reservado emtree.feature
etree.children_***
são_tree.TREE_UNDEFINED
e_tree.TREE_LEAF
. A cada divisão é atribuído um índice exclusivo pordepth first search
.Observe que o
tree.value
formato está em forma[n, 1, 1]
fonte
Aqui está uma função que gera código Python a partir de uma árvore de decisão, convertendo a saída de
export_text
:Uso da amostra:
Saída de amostra:
O exemplo acima é gerado com
names = ['f'+str(j+1) for j in range(NUM_FEATURES)]
.Um recurso útil é que ele pode gerar um tamanho de arquivo menor com espaçamento reduzido. Basta definir
spacing=2
.fonte