English Русский 中文 Español Deutsch 日本語 한국어 Français Italiano Türkçe
preview
Ciência de Dados e Aprendizado de Máquina (Parte 05): Árvores de Decisão

Ciência de Dados e Aprendizado de Máquina (Parte 05): Árvores de Decisão

MetaTrader 5Negociação | 29 setembro 2022, 09:32
745 0
Omega J Msigwa
Omega J Msigwa

O que é uma árvore de decisão?

Uma árvore de decisão é um tipo de técnica de aprendizado de máquina supervisionada usada para categorizar ou fazer previsões com base em respostas de um conjunto anterior de perguntas. O modelo é uma forma de aprendizado supervisionado, o que significa que o modelo é treinado e testado em um conjunto de dados que contém a categorização desejada.

A árvore de decisão nem sempre fornece respostas ou decisões claras. Em vez disso, ela pode apresentar as opções para que o cientista de dados possa tomar sua própria decisão fundamentada nela. As árvores de decisão imitam a maneira como nós, humanos, pensamos, por isso geralmente é fácil para os cientistas de dados entender e interpretar os resultados.

Imagem do artigo de árvores de decisão

Alerta de terminologia!

Eu esqueci de descrever a terminologia do aprendizado supervisionado e não supervisionado em meu primeiro artigo desta série, então aqui está.


Aprendizado Supervisionado

O aprendizado supervisionado é uma abordagem para a criação da inteligência artificial (IA), onde um algoritmo de computador é treinado com os dados de entrada e rotulados para uma saída específica, o modelo é treinado até que se possa detectar os padrões e relacionamentos subjacentes entre os dados de entrada e a saída rotuladas, permitindo que ele produza resultados precisos quando apresentados a dados nunca vistos antes.

Em contraste com a aprendizagem supervisionada, nesta abordagem, o algoritmo é apresentado com os dados não rotulados e projetado para detectar padrões ou semelhanças por conta própria.

Os algoritmos comumente usados em programas de aprendizado supervisionado incluem o seguinte:

A principal diferença entre o aprendizado supervisionado e o não supervisionado está em como o algoritmo aprende. No aprendizado não supervisionado, o algoritmo recebe os dados não rotulados como um conjunto de treinamento. Ao contrário do aprendizado supervisionado, não há valores de saída corretos; o algoritmo determina padrões e semelhanças dentro dos dados em vez de relacioná-los com algumas medidas externas, ou seja, os algoritmos podem funcionar livremente para aprender mais sobre os dados e encontrar coisas interessantes ou inesperadas que os seres humanos não estavam procurando. 

Nós estamos trabalhando atualmente com a aprendizagem supervisionada, aprenderemos sobre o aprendizado não supervisionado nos próximos artigos.


Como funcionam as Árvores de Decisão?

As árvores de decisão usam vários algoritmos para decidir dividir um nó em dois ou mais nós do subconjunto. A criação dos sub-nós aumenta a homogeneidade dos sub-nós resultantes. Em outras palavras, nós podemos dizer que a pureza do nó aumenta em relação à variável alvo. O algoritmo da árvore de decisão divide os nós em todas as variáveis disponíveis e então seleciona a divisão que resulta nos sub-nós mais homogêneos.

exemplo de árvore de decisão

A seleção do algoritmo é baseada no tipo de variáveis de destino.

A seguir estão os algoritmos usados na Árvore de Decisão:

  1. ID3 > Extensão de D3
  2. C4.5 > Sucessor de ID3
  3. CART > Árvore de Classificação e Regressão
  4. CHAID > Detecção Automática da Interação Qui-quadrado, executa divisões em vários níveis ao calcular as árvores de classificação
  5. MARS > Splines de Regressão Adaptativa Multivariada

Neste artigo eu vou criar uma árvore de decisão baseada no algoritmo ID3, nós vamos discutir e usar os outros algoritmos nos próximos artigos desta série.


O Objetivo da Árvore de Decisão

O principal objetivo do algoritmo das árvores de decisão é separar os dados impuros e puros ou próximos aos nós, por exemplo, há uma cesta misturada com maçãs e laranjas. Quando a árvore de decisão aprende como as maçãs se parecem em termos de sua cor e tamanho, ela irá separar as maçãs em uma cesta e as laranjas em outra.


Algoritmo ID3

ID3 significa Iterative Dichotomiser 3, ele é chamado assim porque o algoritmo iterativamente (repetidamente) dicotomiza (divide) os recursos em dois ou mais grupos em cada etapa.

Inventado por Ross Quinlan, o ID3 usa a busca gulosa de cima para baixo para construir uma árvore de decisão. Em outras palavras, a busca gulosa de cima para baixo significa que ele começa a construir a árvore do topo e a cada iteração é selecionado a melhor função no momento presente para a criação de um nó.

Geralmente, o ID3 é usado apenas para problemas de classificação com os dados nominais (basicamente, os dados que não podem ser medidos).

Dito isto, existem dois tipos de Árvores de Decisão.

  1. Árvores de Classificação
  2. Árvores de Regressão

01: Árvores de Classificação

A árvore de classificação é como a árvore que nós vamos aprender neste artigo, onde temos características sem valores numéricos contínuos ou ordenados, que nós queremos classificar.

As árvores de classificação classificam as coisas em categorias.

02: Árvores de Regressão

Estes são construídos com os valores ordenados e com os valores contínuos.

A Árvore de Decisão prevê os valores numéricos.


Etapas no algoritmo ID3

01: Ele começa com o conjunto de dados original como o nó raiz.

Para construir a biblioteca básica, nós usaremos o conjunto de dados simples sobre jogar tênis em determinadas condições climáticas. Temos abaixo a nossa visão geral do conjunto de dados, este é um conjunto de dados pequeno (apenas 14 linhas).

jogando tênis versus conjunto de dados climáticos para árvore de decisão

Para desenhar uma árvore de decisão usando este Algoritmo, nós precisamos entender quais atributos fornecem mais ganho de informação de todos os Atributos, deixe-me explicar.

Um desses atributos (colunas) deve ser um nó raiz para começar, mas como decidir qual coluna será um nó raiz? É aqui que nós usamos o ganho de Informação.

Ganho de informações

O ganho de informação calcula a redução da entropia e mede quão bem uma determinada característica separa ou classifica as classes de destino. A característica com o maior ganho de informação é selecionada como a melhor.

fórmula do ganho de informação das árvores de decisão

Entropia

entropia é a medida de incerteza de uma variável aleatória, ela caracteriza a impureza na amostra dada.

A fórmula da entropia é,

fórmula da entropia da árvore de decisão

A primeira coisa que nós temos a fazer é encontrar a entropia de todo o conjunto de dados, isso significa encontrar a entropia das variáveis objetivo, pois todas essas colunas são projetadas na coluna objetivo PlayTennis.

coluna objetivo da variável de jogar tênis

vamos escrever algum código, 

nós sabemos com certeza que antes de podermos encontrar a entropia de nossas variáveis objetivo, nós precisamos ter o número total dos valores negativos rotulados como No e os valores positivos rotulados como Yes, esses valores podem nos ajudar a obter a probabilidade dos elementos dentro de nossa coluna. Para obter tais valores, escreveremos o código para fazer tal coisa dentro da Função de entropia

double CDecisionTree::Entropy(int &SampleNumbers[],int total)
 {
    double Entropy = 0;
    double entropy_out =0; //the value of entropy that will be returned
     
     for (int i=0; i<ArraySize(SampleNumbers); i++)
        {                   
              double probability1 = Proba(SampleNumbers[i],total); 
              Entropy += probability1 * log2(probability1);
        }
     
    entropy_out = -Entropy;
    
    return(entropy_out);
 }

A função é fácil de entender de relance, especialmente se você leu a fórmula, mas preste atenção a matriz SampleNumbers[]. As amostras são o que está dentro da coluna, nós também podemos nos referir a amostras como sendo as classes, por exemplo, nesta coluna objetivo, nossas amostras são Yes e No.

A Execução bem-sucedida da função na coluna TargetArray resultará em

12:37:48.394    TestScript      There are 5 No
12:37:48.394    TestScript      There are 9 Yes
12:37:48.394    TestScript      There are 2 classes
12:37:48.394    TestScript      "No"  "Yes"
12:37:48.394    TestScript      5     9
12:37:48.394    TestScript      Total contents = 14

Agora que nós temos esses números, vamos continuar encontrando a entropia usando esta nossa fórmula

Fórmula da entropia para as árvores de decisão

se você prestar atenção na fórmula, notará que o logaritmo com o qual nós estamos lidando aqui é o da base 2, que é o logaritmo binário (leia para mais informações) para encontrar o log da base 2 dividimos o log2 pelo log do valor do argumento.

double CDecisionTree::log2(double value)
 {
   return (log10(value)/log10(2));
 }

Como a base é a mesma, está tudo bem.

Eu também codifiquei a função Proba( ) para nos ajudar a obter a probabilidade de uma classe de valores, aqui está.

double CDecisionTree::Proba(int number,double total)
 {
    return(number/total);
 }

Elefante no quarto. Para encontrar a probabilidade de um elemento em nossa coluna, nós encontramos quantas vezes ele apareceu dividindo pelo número total de todos os elementos nessa coluna, você deve ter notado que existem 5 elementos que são No e 9 elementos que são Yes assim,

probabilidade de No = 5/14 (número total de elementos) = 0,357142..

probabilidade de Yes = 9/14 (mesma história) = 0,6428571...

Finalmente, para encontrar a entropia de uma coluna de atributo/conjunto de dados

     for (int i=0; i<ArraySize(SampleNumbers); i++)
        {                   
              double probability1 = Proba(SampleNumbers[i],total); 
              Entropy += probability1 * log2(probability1);
        }
      entropy_out = -Entropy;
    

Se executarmos esta função na variável Target, obteremos o seguinte 

13:37:54.273    TestScript      Proba1 0.35714285714285715
13:37:54.273    TestScript      Proba1 0.6428571428571429
13:37:54.273    TestScript      Entropy of the entire dataset = 0.9402859586706309

B  A  M

Agora sabemos a entropia de todo o conjunto de dados que é basicamente a entropia dos valores de y, e temos a função para encontrar a entropia em mãos. Vamos encontrar a entropia de cada coluna no conjunto de dados.

Agora que nós temos a entropia de todo o conjunto de dados, o próximo passo é encontrar a entropia dos membros dentro de cada coluna da variável independente. Ganho de informação, para cada coluna de dados.

Antes de usarmos a nossa Biblioteca para encontrar a Entropia da coluna do Outlook, vamos calculá-la manualmente para que você possa ter uma compreensão clara do que está sendo feito.

Vamos comparar a coluna outlook com a sua variável objetivo.

Coluna Outlook vs PlayTennis

outlook vs playtennis

Ao contrário de como nós encontramos a entropia de todo o conjunto de dados, que também é referido como a entropia da variável objetivo, para encontrar a entropia de uma variável independente, temos que referenciá-la à variável objetivo, pois esse é o nosso objetivo,

Valores em Outlook 

Temos 3 valores diferentes que são Sunny, Overcast e Rain. Temos que encontrar a entropia de cada um desses valores em relação à sua variável objetivo

Amostras (Sunny) (amostras positivas e negativas de Sunny) = [2 Positivo (Yes), 3 Negativo (No)]

árvore de decisão Sunny 

Agora que nós temos o número de resultados positivos e negativos, a probabilidade de uma decisão positiva Yes para jogar tênis em um dia ensolarado será

probabilidade1= 2(número de vezes que Yes apareceu) / 5(número total de dias ensolarados)

então 2/5 = 0.4

Em contraste

A probabilidade de não jogar em dia ensolarado será de 0.6 ou seja, 3/5 = 0.6

Finalmente, a entropia de jogar em dias ensolarados será, consulte a fórmula

Entropy(Sunny) = - (P1*log2P1 + P2*log2P2)
Entropy(Sunny) = -(0.4*log2 0.4 + 0.6*log2 0.6)

Entropy(Sunny) =  0.97095

Agora vamos encontrar a entropia de Overcast 

Árvore de decisão da entropia nublada

Amostras em nublado.

Amostras positivas 4(amostras com Yes na coluna Target), Amostras negativas 0(amostras com No na coluna Target). Esta Situação é uma exceção.

Exceções no algoritmo ID3

Quando temos zero (0) amostras negativas enquanto houver amostras positivas ou o contrário, zero (0) amostras positivas enquanto houver amostras negativas, sempre que isso acontecer a entropia será vinculada a zero (0).

Nós dizemos que é um nó puro, não há necessidade de separá-lo, pois possui amostras homogêneas você entenderá melhor o que quero dizer com isso quando desenharmos uma árvore.

Outra exceção é:

Quando o número de Amostras Positivas e Amostras Negativas forem iguais, matematicamente a entropia será igual a um (1).

A única exceção que devemos tratar de forma eficaz é quando há valores iguais a zero nas amostras porque zero pode levar a divisão por zero, segue a nova função, com a capacidade de lidar com essas exceções.

double CDecisionTree::Entropy(int &SampleNumbers[],int total)
 {
    double Entropy = 0;
    double entropy_out =0; //the value of entropy that will be returned
     
     for (int i=0; i<ArraySize(SampleNumbers); i++)
        {       
            if (SampleNumbers[i] == 0) { Entropy = 0; break; } //Exception
            
              double probability1 = Proba(SampleNumbers[i],total); 
              Entropy += probability1 * log2(probability1);
        }
     
     if (Entropy==0)     entropy_out = 0;  //handle the exception
     else                entropy_out = -Entropy;
    
    return(entropy_out);
 }

Por último, vamos encontrar a Entropia da Chuva (Rain)

árvores de decisão da entropia da chuva

Amostras da Chuva;

Existem 3 amostras positivas (Amostras com Yes na coluna Target).

Existem 2 Amostras Negativas (Amostras com No na coluna Target).

Finalmente a Entropia de jogar Tênis em um dia chuvoso.

Entropy(Rain) = - (P1*log2P1 + P2*log2P2)
Entropy(Rain) = -(0.6*log2 0.6 + 0.4*log2 0.4)

Entropy(Rain) =  0.97095

Aqui estão os valores da entropia que nós obtivemos da coluna Outlook

Entropia da coluna Outlook
Entropy(Sunny) =  0.97095
Entropy(Overcast) = 0
Entropy(Rain) =  0.97095  

Então, é assim que encontramos a entropia das amostras manualmente agora, se nós usarmos nosso programa para encontrar essas entropias, a saída será:

PD      0       13:47:20.571    TestScript      <<<<<<<<    Parent Entropy  0.94029  A = 0  >>>>>>>> 
FL      0       13:47:20.571    TestScript         <<<<<   C O L U M N  Outlook   >>>>>  
CL      0       13:47:20.571    TestScript           <<   Sunny   >> total > 5
MH      0       13:47:20.571    TestScript      "No"  "Yes"
DM      0       13:47:20.571    TestScript      3 2
CQ      0       13:47:20.571    TestScript      Entropy of Sunny = 0.97095
LD      0       13:47:20.571    TestScript           <<   Overcast   >> total > 4
OI      0       13:47:20.571    TestScript      "No"  "Yes"
MJ      0       13:47:20.571    TestScript      0 4
CM      0       13:47:20.571    TestScript      Entropy of Overcast = 0.00000
JD      0       13:47:20.571    TestScript           <<   Rain   >> total > 5
GN      0       13:47:20.571    TestScript      "No"  "Yes"
JH      0       13:47:20.571    TestScript      2 3
HR      0       13:47:20.571    TestScript      Entropy of Rain = 0.97095

Nós vamos usar esses valores para encontrar o ganho de informação de todos os dados usando a fórmula que discutimos anteriormente.

árvore de decisão do ganho de informação

Agora, vamos encontrar a entropia manualmente para que você entenda o que está acontecendo do outro lado da porta.

Ganho de Informação(IG) = EntropiaDeTodoDataset - Soma do produto da probabilidade de uma amostra e sua entropia.

IG = E(dataset) - ( Prob(sunny) * E(sunny) + Prob(Overcast)*E(Overcast) + Prob(Rain)*E(Rain) )

IG = 0.9402 - ( 5/14 * (0.97095) + 4/14 * (0) + 5/14(0.97095) )

IG = 0.2467 (Este é um ganho de informação da Coluna Outlook)

Quando nós convertermos a fórmula em código será:

double CDecisionTree::InformationGain(double parent_entropy, double &EntropyArr[], int &ClassNumbers[], int rows_)
 {
    double IG = 0;
    
    for (int i=0; i<ArraySize(EntropyArr); i++)
      {  
        double prob = ClassNumbers[i]/double(rows_); 
        IG += prob * EntropyArr[i];
      }
     
     return(parent_entropy - IG);
 }

Chamada da função

    if (m_debug)  printf("<<<<<<  Column Information Gain %.5f >>>>>> \n",IGArr[i]);

Resultado

PF      0       13:47:20.571    TestScript      <<<<<<  Column Information Gain 0.24675 >>>>>> 

Agora, nós temos que repetir o processo para todas as colunas e encontrar o seus Ganhos de informação. A saída será:

RH      0       13:47:20.571    TestScript (EURUSD,H1)  Default Parent Entropy 0.9402859586706309
PD      0       13:47:20.571    TestScript (EURUSD,H1)  <<<<<<<<    Parent Entropy  0.94029  A = 0  >>>>>>>> 
FL      0       13:47:20.571    TestScript (EURUSD,H1)     <<<<<   C O L U M N  Outlook   >>>>>  
CL      0       13:47:20.571    TestScript (EURUSD,H1)       <<   Sunny   >> total > 5
MH      0       13:47:20.571    TestScript (EURUSD,H1)  "No"  "Yes"
DM      0       13:47:20.571    TestScript (EURUSD,H1)  3 2
CQ      0       13:47:20.571    TestScript (EURUSD,H1)  Entropy of Sunny = 0.97095
LD      0       13:47:20.571    TestScript (EURUSD,H1)       <<   Overcast   >> total > 4
OI      0       13:47:20.571    TestScript (EURUSD,H1)  "No"  "Yes"
MJ      0       13:47:20.571    TestScript (EURUSD,H1)  0 4
CM      0       13:47:20.571    TestScript (EURUSD,H1)  Entropy of Overcast = 0.00000
JD      0       13:47:20.571    TestScript (EURUSD,H1)       <<   Rain   >> total > 5
GN      0       13:47:20.571    TestScript (EURUSD,H1)  "No"  "Yes"
JH      0       13:47:20.571    TestScript (EURUSD,H1)  2 3
HR      0       13:47:20.571    TestScript (EURUSD,H1)  Entropy of Rain = 0.97095
PF      0       13:47:20.571    TestScript (EURUSD,H1)  <<<<<<  Column Information Gain 0.24675 >>>>>> 
QP      0       13:47:20.571    TestScript (EURUSD,H1)  
KH      0       13:47:20.571    TestScript (EURUSD,H1)     <<<<<   C O L U M N  Temp   >>>>>  
PR      0       13:47:20.571    TestScript (EURUSD,H1)       <<   Hot   >> total > 4
QF      0       13:47:20.571    TestScript (EURUSD,H1)  "No"  "Yes"
OS      0       13:47:20.571    TestScript (EURUSD,H1)  2 2
NK      0       13:47:20.571    TestScript (EURUSD,H1)  Entropy of Hot = 1.00000
GO      0       13:47:20.571    TestScript (EURUSD,H1)       <<   Mild   >> total > 6
OD      0       13:47:20.571    TestScript (EURUSD,H1)  "No"  "Yes"
KQ      0       13:47:20.571    TestScript (EURUSD,H1)  2 4
GJ      0       13:47:20.571    TestScript (EURUSD,H1)  Entropy of Mild = 0.91830
HQ      0       13:47:20.571    TestScript (EURUSD,H1)       <<   Cool   >> total > 4
OJ      0       13:47:20.571    TestScript (EURUSD,H1)  "No"  "Yes"
OO      0       13:47:20.571    TestScript (EURUSD,H1)  1 3
IH      0       13:47:20.571    TestScript (EURUSD,H1)  Entropy of Cool = 0.81128
OR      0       13:47:20.571    TestScript (EURUSD,H1)  <<<<<<  Column Information Gain 0.02922 >>>>>> 
ID      0       13:47:20.571    TestScript (EURUSD,H1)  
HL      0       13:47:20.571    TestScript (EURUSD,H1)     <<<<<   C O L U M N  Humidity   >>>>>  
FH      0       13:47:20.571    TestScript (EURUSD,H1)       <<   High   >> total > 7
KM      0       13:47:20.571    TestScript (EURUSD,H1)  "No"  "Yes"
HF      0       13:47:20.571    TestScript (EURUSD,H1)  4 3
GQ      0       13:47:20.571    TestScript (EURUSD,H1)  Entropy of High = 0.98523
QK      0       13:47:20.571    TestScript (EURUSD,H1)       <<   Normal   >> total > 7
GR      0       13:47:20.571    TestScript (EURUSD,H1)  "No"  "Yes"
DD      0       13:47:20.571    TestScript (EURUSD,H1)  1 6
OF      0       13:47:20.571    TestScript (EURUSD,H1)  Entropy of Normal = 0.59167
EJ      0       13:47:20.571    TestScript (EURUSD,H1)  <<<<<<  Column Information Gain 0.15184 >>>>>> 
EL      0       13:47:20.571    TestScript (EURUSD,H1)  
GE      0       13:47:20.571    TestScript (EURUSD,H1)     <<<<<   C O L U M N  Wind   >>>>>  
IQ      0       13:47:20.571    TestScript (EURUSD,H1)       <<   Weak   >> total > 8
GE      0       13:47:20.571    TestScript (EURUSD,H1)  "No"  "Yes"
EO      0       13:47:20.571    TestScript (EURUSD,H1)  2 6
LI      0       13:47:20.571    TestScript (EURUSD,H1)  Entropy of Weak = 0.81128
FS      0       13:47:20.571    TestScript (EURUSD,H1)       <<   Strong   >> total > 6
CK      0       13:47:20.571    TestScript (EURUSD,H1)  "No"  "Yes"
ML      0       13:47:20.571    TestScript (EURUSD,H1)  3 3
HO      0       13:47:20.571    TestScript (EURUSD,H1)  Entropy of Strong = 1.00000
LE      0       13:47:20.571    TestScript (EURUSD,H1)  <<<<<<  Column Information Gain 0.04813 >>>>>> 
IE      0       13:47:20.571    TestScript (EURUSD,H1)  


Agora que nós temos os Ganhos de Informação para todas as colunas, vamos começar a desenhar nossa Árvore de Decisão. Como?

O objetivo deste processo inicial foi encontrar os ganhos de informação para todas as colunas para que nós possamos decidir qual coluna será o Nó Raiz, a coluna com maior ganho de informação que todas as outras se tornará o nó raiz, neste caso o Outlook tem o maior ganho de informação, então ele se tornará o Nó Raiz da nossa árvore de decisão, vamos desenhar a árvore agora.

Primeira divisão da árvore de decisão

Essas informações sobre o outlook são fornecidas pela Biblioteca, quando você executa o Script Test Script anexado ao final do artigo, muitas informações estão sendo impressas quando você está no modo debug da biblioteca que é padrão.

O ganho de informação foi obtido, a partir de sua função e então armazenado dentro de uma matriz de valores do tipo double que armazena todos os ganhos de informação, em seguida, o nosso valor objetivo será o maior valor da matriz.

         //--- Finding the Information Gain
                        
                        ArrayResize(IGArr,i+1); //information gains matches the columns number
                        
                        IGArr[i] = InformationGain(P_EntropyArr[A],EntropyArr,ClassNumbers,rows);
                        
                        max_gain = ArrayMaximum(IGArr); 
A saída será 
QR      0       13:47:20.571    TestScript (EURUSD,H1)  Parent Noce will be Outlook with IG = 0.24675
IK      0       13:47:20.574    TestScript (EURUSD,H1)  Parent Entropy Array and Class Numbers
NL      0       13:47:20.574    TestScript (EURUSD,H1)  "Sunny"    "Overcast" "Rain"    
NH      0       13:47:20.574    TestScript (EURUSD,H1)  0.9710 0.0000 0.9710
FR      0       13:47:20.574    TestScript (EURUSD,H1)  5 4 5

Mais explicações sobre a Árvore que traçamos para este ponto.

Explicações da árvore de decisão

Este foi o primeiro passo crucial em que estávamos encontrando o nó raiz e dividindo esse nó raiz em ramos e folhas, continuaremos a dividir os dados até que não haja mais nada para dividir, agora vamos continuar o processo dividindo o ramo com os itens Sunny e o ramo com os itens Rain.

Overcast consiste em itens homogêneos (ele é puro) então nós dizemos que ele foi completamente classificado, quando se trata da árvore de decisão, nós chamamos de folha. Ele não vai gerar ramificações.

Mas antes de nós dividirmos mais os dados, há etapas cruciais que nós precisamos fazer com o conjunto de dados atual que nós temos.

CLASSIFICAÇÃO DA MATRIZ DO CONJUNTO DE DADOS RESTANTE

Temos que classificar a matriz do conjunto de dados restante para colocar as linhas com os mesmos valores em ordem crescente, isso será útil para criar as ramificações e folhas com o conteúdo homogêneo (algo que estamos ansiosos para alcançar).

void CDecisionTree::MatrixClassify(string &dataArr[],string &Classes[], int cols)
 {
   string ClassifiedArr[];
   ArrayResize(ClassifiedArr,ArraySize(dataArr));
   
   int fill_start = 0, fill_ends = 0;
   int index = 0;
   for (int i = 0; i<ArraySize(Classes); i++)
     {
      int start = 0;  int curr_col = 0;
      for (int j = 0; j<ArraySize(dataArr); j++)
        { 
          curr_col++;
          
            if (Classes[i] == dataArr[j])
              {
                //printf("Classes[%d] = %s dataArr[%d] = %s ",i,Classes[i],j,dataArr[j]);
                
                 if (curr_col == 1) 
                     fill_start =  j;
                 else
                   {
                      if (j>curr_col)
                        fill_start = j - (curr_col-1);
                      else fill_start = (curr_col-1) - j;
                          
                      fill_start  = fill_start;
                      //Print("j ",j," j-currcol ",j-(curr_col-1)," curr_col ",curr_col," columns ",cols," fill start ",fill_start );
                      
                   }
                 
                 fill_ends = fill_start + cols; 
                 
                 //printf("fillstart %d fillends %d j index = %d i = %d ",fill_start,fill_ends,j,i);
//---
                  //if (ArraySize(ClassifiedArr) >= ArraySize(dataArr)) break;
                  //Print("ArraySize Classified Arr ",ArraySize(ClassifiedArr)," dataArr size ",ArraySize(dataArr)," i ",i);
                  
                  
                  for (int k=fill_start; k<fill_ends; k++)
                    {
                      index++;
                      //printf(" k %d index %d",k,index);
                      //printf("dataArr[%d] = %s index = %d",k,dataArr[k],index-1);
                      ClassifiedArr[index-1] = dataArr[k];
                    }
                    
                if (index >= ArraySize(dataArr)) break; //might be infinite loop if this occurs
              }
              
          if (curr_col == cols) curr_col = 0;
        } 
         
      if (index >= ArraySize(dataArr)) break; //might be infinite loop if this occurs
     }
     
    ArrayCopy(dataArr,ClassifiedArr);
    ArrayFree(ClassifiedArr);
 }

Por que há tantas linhas de códigos comentadas? Nossa biblioteca ainda precisa de melhorias e os comentários são para depuração, espero que você brinque com eles.

Quando nós chamamos esta função e imprimimos a saída, nós obteremos

JG      0       13:47:20.574    TestScript (EURUSD,H1)  Classified matrix dataset
KL      0       13:47:20.574    TestScript (EURUSD,H1)  "Outlook"     "Temp"        "Humidity"    "Wind"        "PlayTennis "
GS      0       13:47:20.574    TestScript (EURUSD,H1)  [ 
QF      0       13:47:20.574    TestScript (EURUSD,H1)  "Sunny" "Hot"   "High"  "Weak"  "No"   
DN      0       13:47:20.574    TestScript (EURUSD,H1)  "Sunny"  "Hot"    "High"   "Strong" "No"    
JF      0       13:47:20.574    TestScript (EURUSD,H1)  "Sunny" "Mild"  "High"  "Weak"  "No"   
ND      0       13:47:20.574    TestScript (EURUSD,H1)  "Sunny"  "Cool"   "Normal" "Weak"   "Yes"   
PN      0       13:47:20.574    TestScript (EURUSD,H1)  "Sunny"  "Mild"   "Normal" "Strong" "Yes"   
EH      0       13:47:20.574    TestScript (EURUSD,H1)  "Overcast" "Hot"      "High"     "Weak"     "Yes"     
MH      0       13:47:20.574    TestScript (EURUSD,H1)  "Overcast" "Cool"     "Normal"   "Strong"   "Yes"     
MN      0       13:47:20.574    TestScript (EURUSD,H1)  "Overcast" "Mild"     "High"     "Strong"   "Yes"     
DN      0       13:47:20.574    TestScript (EURUSD,H1)  "Overcast" "Hot"      "Normal"   "Weak"     "Yes"     
MG      0       13:47:20.574    TestScript (EURUSD,H1)  "Rain" "Mild" "High" "Weak" "Yes" 
QO      0       13:47:20.574    TestScript (EURUSD,H1)  "Rain"   "Cool"   "Normal" "Weak"   "Yes"   
LN      0       13:47:20.574    TestScript (EURUSD,H1)  "Rain"   "Cool"   "Normal" "Strong" "No"    
LE      0       13:47:20.574    TestScript (EURUSD,H1)  "Rain"   "Mild"   "Normal" "Weak"   "Yes"   
FE      0       13:47:20.574    TestScript (EURUSD,H1)  "Rain"   "Mild"   "High"   "Strong" "No"    
GS      0       13:47:20.574    TestScript (EURUSD,H1)  ] 
DH      0       13:47:20.574    TestScript (EURUSD,H1)  columns = 5 rows = 70

B  A  M, A função funciona como mágica

Ok, o próximo passo crucial é 

REMOVER OS NÓS FOLHA DO CONJUNTO DE DADOS

Antes da próxima iteração de todo o processo que nós fizemos até este ponto, é muito importante remover os nós folha, pois eles não farão ramificações, faz sentido certo? Além disso, eles são nós de valores puros.

Removemos todas as linhas que possuem o valor do Nó Folha. Neste caso, removemos todas as linhas com Overcast.

    //--- Search if there is zero entropy in the Array
         
            int zero_entropy_index = 0;
            bool zero_entropy = false;
            for (int e=0; e<ArraySize(P_EntropyArr); e++)
              if (P_EntropyArr[e] == 0) { zero_entropy = true; zero_entropy_index=e; break; }
            
            if (zero_entropy) //if there is zero in the Entropy Array 
              {
                MatrixRemoveRow(m_dataset,p_Classes[zero_entropy_index],cols);    
               
                rows_total = ArraySize(m_dataset); //New number of total rows from Array   
                 if (m_debug)
                  {
                    printf("%s is A LEAF NODE its Rows have been removed from the dataset remaining Dataset is ..",p_Classes[zero_entropy_index]);
                    ArrayPrint(DataColumnNames);
                    MatrixPrint(m_dataset,cols,rows_total);
                  }
                
                //we also remove the entropy from the Array and its information everywhere else from the parent Node That we are going to build next
                
                ArrayRemove(P_EntropyArr,zero_entropy_index,1);
                ArrayRemove(p_Classes,zero_entropy_index,1);
                ArrayRemove(p_ClassNumbers,zero_entropy_index,1);
              }
            
            if (m_debug)  
             Print("rows total ",rows_total," ",p_Classes[zero_entropy_index]," ",p_ClassNumbers[zero_entropy_index]);
            
            

A saída após a execução deste bloco de código será

NQ      0       13:47:20.574    TestScript (EURUSD,H1)  Overcast is A LEAF NODE its Rows have been removed from the dataset remaining Dataset is ..
GP      0       13:47:20.574    TestScript (EURUSD,H1)  "Outlook"     "Temp"        "Humidity"    "Wind"        "PlayTennis "
KG      0       13:47:20.574    TestScript (EURUSD,H1)  [ 
FS      0       13:47:20.575    TestScript (EURUSD,H1)  "Sunny" "Hot"   "High"  "Weak"  "No"   
GK      0       13:47:20.575    TestScript (EURUSD,H1)  "Sunny"  "Hot"    "High"   "Strong" "No"    
EI      0       13:47:20.575    TestScript (EURUSD,H1)  "Sunny" "Mild"  "High"  "Weak"  "No"   
IP      0       13:47:20.575    TestScript (EURUSD,H1)  "Sunny"  "Cool"   "Normal" "Weak"   "Yes"   
KK      0       13:47:20.575    TestScript (EURUSD,H1)  "Sunny"  "Mild"   "Normal" "Strong" "Yes"   
JK      0       13:47:20.575    TestScript (EURUSD,H1)  "Rain" "Mild" "High" "Weak" "Yes" 
FL      0       13:47:20.575    TestScript (EURUSD,H1)  "Rain"   "Cool"   "Normal" "Weak"   "Yes"   
GK      0       13:47:20.575    TestScript (EURUSD,H1)  "Rain"   "Cool"   "Normal" "Strong" "No"    
OI      0       13:47:20.575    TestScript (EURUSD,H1)  "Rain"   "Mild"   "Normal" "Weak"   "Yes"   
IQ      0       13:47:20.575    TestScript (EURUSD,H1)  "Rain"   "Mild"   "High"   "Strong" "No"    
LG      0       13:47:20.575    TestScript (EURUSD,H1)  ] 
IL      0       13:47:20.575    TestScript (EURUSD,H1)  columns = 5 rows = 50
HE      0       13:47:20.575    TestScript (EURUSD,H1)  rows total 50 Rain 5

B  A  M

Por último, mas não menos importante, está a etapa:

REMOÇÃO DA COLUNA PRINCIPAL OU NÓ RAIZ DO CONJUNTO DE DADOS

Como nós já o detectamos como o nó raiz e o desenhamos em nossa árvore, não precisamos mais dele em nosso conjunto de dados, nosso conjunto de dados deve permanecer com os valores não classificados

//---    REMOVING THE PARENT/ ROOT NODE FROM OUR DATASET

            MatrixRemoveColumn(m_dataset,max_gain,cols);
         
         // After removing the columns assign the new values to these global variables
         
            cols = cols-1;   // remove that one column that has been removed
            rows_total = rows_total - single_rowstotal; //remove the size of one column rows
            
         // we also remove the column from column names Array 
            ArrayRemove(DataColumnNames,max_gain,1);

//---

            printf("Column %d removed from the Matrix, The remaining dataset is",max_gain+1);
            ArrayPrint(DataColumnNames);
            MatrixPrint(m_dataset,cols,rows_total);

A saída deste bloco de código será 

OM      0       13:47:20.575    TestScript (EURUSD,H1)  Column 1 removed from the Matrix, The remaining dataset is
ON      0       13:47:20.575    TestScript (EURUSD,H1)  "Temp"        "Humidity"    "Wind"        "PlayTennis "
HF      0       13:47:20.575    TestScript (EURUSD,H1)  [ 
CR      0       13:47:20.575    TestScript (EURUSD,H1)  "Hot"  "High" "Weak" "No"  
JE      0       13:47:20.575    TestScript (EURUSD,H1)  "Hot"    "High"   "Strong" "No"    
JR      0       13:47:20.575    TestScript (EURUSD,H1)  "Mild" "High" "Weak" "No"  
NG      0       13:47:20.575    TestScript (EURUSD,H1)  "Cool"   "Normal" "Weak"   "Yes"   
JI      0       13:47:20.575    TestScript (EURUSD,H1)  "Mild"   "Normal" "Strong" "Yes"   
PR      0       13:47:20.575    TestScript (EURUSD,H1)  "Mild" "High" "Weak" "Yes" 
JJ      0       13:47:20.575    TestScript (EURUSD,H1)  "Cool"   "Normal" "Weak"   "Yes"   
QQ      0       13:47:20.575    TestScript (EURUSD,H1)  "Cool"   "Normal" "Strong" "No"    
OG      0       13:47:20.575    TestScript (EURUSD,H1)  "Mild"   "Normal" "Weak"   "Yes"   
KD      0       13:47:20.575    TestScript (EURUSD,H1)  "Mild"   "High"   "Strong" "No"    
DR      0       13:47:20.575    TestScript (EURUSD,H1)  ] 

B  A  M

Agora, a razão pelo qual nós deixamos algumas partes do conjunto de dados é porque a biblioteca está desenhando uma árvore que deixa pistas sobre onde o conjunto de dados entra, aqui está uma árvore que desenhamos até este ponto.

arquivo de texto da árvore de decisão

Parece feio, mas é bom o suficiente para fins de demonstração, nós tentaremos criá-lo com HTML na próxima série de artigos, ajude-me a conseguir isso no meu repositório do GitHub mais abaixo. Agora, vamos terminar descrevendo o processo restante na construção de uma árvore. Estes são os logs depois de iterarmos esse processo até que não haja nada mais para dividir

HI      0       13:47:20.575    TestScript (EURUSD,H1)  Final Parent Entropy Array and Class Numbers
RK      0       13:47:20.575    TestScript (EURUSD,H1)  "Sunny" "Rain" 
CL      0       13:47:20.575    TestScript (EURUSD,H1)  0.9710 0.9710
CE      0       13:47:20.575    TestScript (EURUSD,H1)  5 5
EH      0       13:47:20.575    TestScript (EURUSD,H1)  <<<<<<<<    Parent Entropy  0.97095  A = 1  >>>>>>>> 
OF      0       13:47:20.575    TestScript (EURUSD,H1)     <<<<<   C O L U M N  Temp   >>>>>  
RP      0       13:47:20.575    TestScript (EURUSD,H1)       <<   Hot   >> total > 2
MD      0       13:47:20.575    TestScript (EURUSD,H1)  "No"  "Yes"
MQ      0       13:47:20.575    TestScript (EURUSD,H1)  2 0
QE      0       13:47:20.575    TestScript (EURUSD,H1)  Entropy of Hot = 0.00000
FQ      0       13:47:20.575    TestScript (EURUSD,H1)       <<   Mild   >> total > 5
KJ      0       13:47:20.575    TestScript (EURUSD,H1)  "No"  "Yes"
NO      0       13:47:20.575    TestScript (EURUSD,H1)  2 3
DH      0       13:47:20.575    TestScript (EURUSD,H1)  Entropy of Mild = 0.97095
IS      0       13:47:20.575    TestScript (EURUSD,H1)       <<   Cool   >> total > 3
KH      0       13:47:20.575    TestScript (EURUSD,H1)  "No"  "Yes"
LM      0       13:47:20.575    TestScript (EURUSD,H1)  1 2
FN      0       13:47:20.575    TestScript (EURUSD,H1)  Entropy of Cool = 0.91830
KD      0       13:47:20.575    TestScript (EURUSD,H1)  <<<<<<  Column Information Gain 0.20999 >>>>>> 
EF      0       13:47:20.575    TestScript (EURUSD,H1)  
DJ      0       13:47:20.575    TestScript (EURUSD,H1)     <<<<<   C O L U M N  Humidity   >>>>>  
HJ      0       13:47:20.575    TestScript (EURUSD,H1)       <<   High   >> total > 5
OS      0       13:47:20.575    TestScript (EURUSD,H1)  "No"  "Yes"
FD      0       13:47:20.575    TestScript (EURUSD,H1)  4 1
NG      0       13:47:20.575    TestScript (EURUSD,H1)  Entropy of High = 0.72193
KM      0       13:47:20.575    TestScript (EURUSD,H1)       <<   Normal   >> total > 5
CP      0       13:47:20.575    TestScript (EURUSD,H1)  "No"  "Yes"
JR      0       13:47:20.575    TestScript (EURUSD,H1)  1 4
MD      0       13:47:20.575    TestScript (EURUSD,H1)  Entropy of Normal = 0.72193
EL      0       13:47:20.575    TestScript (EURUSD,H1)  <<<<<<  Column Information Gain 0.24902 >>>>>> 
IN      0       13:47:20.575    TestScript (EURUSD,H1)  
CS      0       13:47:20.575    TestScript (EURUSD,H1)     <<<<<   C O L U M N  Wind   >>>>>  
OS      0       13:47:20.575    TestScript (EURUSD,H1)       <<   Weak   >> total > 6
CK      0       13:47:20.575    TestScript (EURUSD,H1)  "No"  "Yes"
GM      0       13:47:20.575    TestScript (EURUSD,H1)  2 4
OO      0       13:47:20.575    TestScript (EURUSD,H1)  Entropy of Weak = 0.91830
HE      0       13:47:20.575    TestScript (EURUSD,H1)       <<   Strong   >> total > 4
GI      0       13:47:20.575    TestScript (EURUSD,H1)  "No"  "Yes"
OJ      0       13:47:20.575    TestScript (EURUSD,H1)  3 1
EM      0       13:47:20.575    TestScript (EURUSD,H1)  Entropy of Strong = 0.81128
PG      0       13:47:20.575    TestScript (EURUSD,H1)  <<<<<<  Column Information Gain 0.09546 >>>>>> 
EG      0       13:47:20.575    TestScript (EURUSD,H1)  
HK      0       13:47:20.575    TestScript (EURUSD,H1)  Parent Noce will be Humidity with IG = 0.24902
OI      0       13:47:20.578    TestScript (EURUSD,H1)  Parent Entropy Array and Class Numbers
JO      0       13:47:20.578    TestScript (EURUSD,H1)  "High"   "Normal" "Cool"  
QJ      0       13:47:20.578    TestScript (EURUSD,H1)  0.7219 0.7219 0.9183
QO      0       13:47:20.578    TestScript (EURUSD,H1)  5 5 3
PJ      0       13:47:20.578    TestScript (EURUSD,H1)  Classified matrix dataset
NM      0       13:47:20.578    TestScript (EURUSD,H1)  "Temp"        "Humidity"    "Wind"        "PlayTennis "
EF      0       13:47:20.578    TestScript (EURUSD,H1)  [ 
FM      0       13:47:20.578    TestScript (EURUSD,H1)  "Hot"  "High" "Weak" "No"  
OD      0       13:47:20.578    TestScript (EURUSD,H1)  "Hot"    "High"   "Strong" "No"    
GR      0       13:47:20.578    TestScript (EURUSD,H1)  "Mild" "High" "Weak" "No"  
QG      0       13:47:20.578    TestScript (EURUSD,H1)  "Mild" "High" "Weak" "Yes" 
JD      0       13:47:20.578    TestScript (EURUSD,H1)  "Mild"   "High"   "Strong" "No"    
KS      0       13:47:20.578    TestScript (EURUSD,H1)  "Cool"   "Normal" "Weak"   "Yes"   
OJ      0       13:47:20.578    TestScript (EURUSD,H1)  "Mild"   "Normal" "Strong" "Yes"   
CL      0       13:47:20.578    TestScript (EURUSD,H1)  "Cool"   "Normal" "Weak"   "Yes"   
LJ      0       13:47:20.578    TestScript (EURUSD,H1)  "Cool"   "Normal" "Strong" "No"    
NH      0       13:47:20.578    TestScript (EURUSD,H1)  "Mild"   "Normal" "Weak"   "Yes"   
ER      0       13:47:20.578    TestScript (EURUSD,H1)  ] 
LI      0       13:47:20.578    TestScript (EURUSD,H1)  columns = 4 rows = 40
CQ      0       13:47:20.578    TestScript (EURUSD,H1)  rows total 36 High 5
GH      0       13:47:20.578    TestScript (EURUSD,H1)  Column 2 removed from the Matrix, The remaining dataset is
MP      0       13:47:20.578    TestScript (EURUSD,H1)  "Temp"        "Wind"        "PlayTennis "
QG      0       13:47:20.578    TestScript (EURUSD,H1)  [ 
LL      0       13:47:20.578    TestScript (EURUSD,H1)  "Hot"  "Weak" "No"  
OE      0       13:47:20.578    TestScript (EURUSD,H1)  "Hot"    "Strong" "No"    
QQ      0       13:47:20.578    TestScript (EURUSD,H1)  "Mild" "Weak" "No"  
QE      0       13:47:20.578    TestScript (EURUSD,H1)  "Mild" "Weak" "Yes" 
LQ      0       13:47:20.578    TestScript (EURUSD,H1)  "Mild"   "Strong" "No"    
HE      0       13:47:20.578    TestScript (EURUSD,H1)  "Cool" "Weak" "Yes" 
RM      0       13:47:20.578    TestScript (EURUSD,H1)  "Mild"   "Strong" "Yes"   
PF      0       13:47:20.578    TestScript (EURUSD,H1)  "Cool" "Weak" "Yes" 
MR      0       13:47:20.578    TestScript (EURUSD,H1)  "Cool"   "Strong" "No"    
IF      0       13:47:20.578    TestScript (EURUSD,H1)  "Mild" "Weak" "Yes" 
EN      0       13:47:20.578    TestScript (EURUSD,H1)  ] 
ME      0       13:47:20.578    TestScript (EURUSD,H1)  columns = 3 rows = 22
ER      0       13:47:20.578    TestScript (EURUSD,H1)  Final Parent Entropy Array and Class Numbers
HK      0       13:47:20.578    TestScript (EURUSD,H1)  "High"   "Normal" "Cool"  
CQ      0       13:47:20.578    TestScript (EURUSD,H1)  0.7219 0.7219 0.9183
OK      0       13:47:20.578    TestScript (EURUSD,H1)  5 5 3
NS      0       13:47:20.578    TestScript (EURUSD,H1)  <<<<<<<<    Parent Entropy  0.91830  A = 2  >>>>>>>> 
JM      0       13:47:20.578    TestScript (EURUSD,H1)     <<<<<   C O L U M N  Temp   >>>>>  
CG      0       13:47:20.578    TestScript (EURUSD,H1)       <<   Hot   >> total > 2
DM      0       13:47:20.578    TestScript (EURUSD,H1)  "No"  "Yes"
LF      0       13:47:20.578    TestScript (EURUSD,H1)  2 0
HN      0       13:47:20.578    TestScript (EURUSD,H1)  Entropy of Hot = 0.00000
OJ      0       13:47:20.578    TestScript (EURUSD,H1)       <<   Mild   >> total > 5
JS      0       13:47:20.578    TestScript (EURUSD,H1)  "No"  "Yes"
GD      0       13:47:20.578    TestScript (EURUSD,H1)  2 3
QG      0       13:47:20.578    TestScript (EURUSD,H1)  Entropy of Mild = 0.97095
LL      0       13:47:20.578    TestScript (EURUSD,H1)       <<   Cool   >> total > 3
JQ      0       13:47:20.578    TestScript (EURUSD,H1)  "No"  "Yes"
IR      0       13:47:20.578    TestScript (EURUSD,H1)  1 2
OE      0       13:47:20.578    TestScript (EURUSD,H1)  Entropy of Cool = 0.91830
RO      0       13:47:20.578    TestScript (EURUSD,H1)  <<<<<<  Column Information Gain 0.15733 >>>>>> 
PO      0       13:47:20.578    TestScript (EURUSD,H1)  
JS      0       13:47:20.578    TestScript (EURUSD,H1)     <<<<<   C O L U M N  Wind   >>>>>  
JR      0       13:47:20.578    TestScript (EURUSD,H1)       <<   Weak   >> total > 6
NH      0       13:47:20.578    TestScript (EURUSD,H1)  "No"  "Yes"
JM      0       13:47:20.578    TestScript (EURUSD,H1)  2 4
JL      0       13:47:20.578    TestScript (EURUSD,H1)  Entropy of Weak = 0.91830
QD      0       13:47:20.578    TestScript (EURUSD,H1)       <<   Strong   >> total > 4
JN      0       13:47:20.578    TestScript (EURUSD,H1)  "No"  "Yes"
JK      0       13:47:20.578    TestScript (EURUSD,H1)  3 1
DM      0       13:47:20.578    TestScript (EURUSD,H1)  Entropy of Strong = 0.81128
JF      0       13:47:20.578    TestScript (EURUSD,H1)  <<<<<<  Column Information Gain 0.04281 >>>>>> 
DG      0       13:47:20.578    TestScript (EURUSD,H1)  
LI      0       13:47:20.578    TestScript (EURUSD,H1)  Parent Noce will be Temp with IG = 0.15733
LH      0       13:47:20.584    TestScript (EURUSD,H1)  Parent Entropy Array and Class Numbers
GR      0       13:47:20.584    TestScript (EURUSD,H1)  "Hot"  "Mild" "Cool"
CD      0       13:47:20.584    TestScript (EURUSD,H1)  0.0000 0.9710 0.9183
GN      0       13:47:20.584    TestScript (EURUSD,H1)  2 5 3
CK      0       13:47:20.584    TestScript (EURUSD,H1)  Classified matrix dataset
RL      0       13:47:20.584    TestScript (EURUSD,H1)  "Temp"        "Wind"        "PlayTennis "
NK      0       13:47:20.584    TestScript (EURUSD,H1)  [ 
CQ      0       13:47:20.584    TestScript (EURUSD,H1)  "Hot"  "Weak" "No"  
LI      0       13:47:20.584    TestScript (EURUSD,H1)  "Hot"    "Strong" "No"    
JM      0       13:47:20.584    TestScript (EURUSD,H1)  "Mild" "Weak" "No"  
NI      0       13:47:20.584    TestScript (EURUSD,H1)  "Mild" "Weak" "Yes" 
CL      0       13:47:20.584    TestScript (EURUSD,H1)  "Mild"   "Strong" "No"    
KI      0       13:47:20.584    TestScript (EURUSD,H1)  "Mild"   "Strong" "Yes"   
LR      0       13:47:20.584    TestScript (EURUSD,H1)  "Mild" "Weak" "Yes" 
KJ      0       13:47:20.584    TestScript (EURUSD,H1)  "Cool" "Weak" "Yes" 
IQ      0       13:47:20.584    TestScript (EURUSD,H1)  "Cool" "Weak" "Yes" 
DE      0       13:47:20.584    TestScript (EURUSD,H1)  "Cool"   "Strong" "No"    
NR      0       13:47:20.584    TestScript (EURUSD,H1)  ] 
OI      0       13:47:20.584    TestScript (EURUSD,H1)  columns = 3 rows = 30
OO      0       13:47:20.584    TestScript (EURUSD,H1)  Hot is A LEAF NODE its Rows have been removed from the dataset remaining Dataset is ..
HL      0       13:47:20.584    TestScript (EURUSD,H1)  "Temp"        "Wind"        "PlayTennis "
DJ      0       13:47:20.584    TestScript (EURUSD,H1)  [ 
DL      0       13:47:20.584    TestScript (EURUSD,H1)  "Mild" "Weak" "No"  
LH      0       13:47:20.584    TestScript (EURUSD,H1)  "Mild" "Weak" "Yes" 
QL      0       13:47:20.584    TestScript (EURUSD,H1)  "Mild"   "Strong" "No"    
MH      0       13:47:20.584    TestScript (EURUSD,H1)  "Mild"   "Strong" "Yes"   
RQ      0       13:47:20.584    TestScript (EURUSD,H1)  "Mild" "Weak" "Yes" 
MI      0       13:47:20.584    TestScript (EURUSD,H1)  "Cool" "Weak" "Yes" 
KQ      0       13:47:20.584    TestScript (EURUSD,H1)  "Cool" "Weak" "Yes" 
FD      0       13:47:20.584    TestScript (EURUSD,H1)  "Cool"   "Strong" "No"    
HQ      0       13:47:20.584    TestScript (EURUSD,H1)  ] 
NN      0       13:47:20.584    TestScript (EURUSD,H1)  columns = 3 rows = 24
IF      0       13:47:20.584    TestScript (EURUSD,H1)  rows total 24 Mild 5
CO      0       13:47:20.584    TestScript (EURUSD,H1)  Column 1 removed from the Matrix, The remaining dataset is
DM      0       13:47:20.584    TestScript (EURUSD,H1)  "Wind"        "PlayTennis "
PD      0       13:47:20.584    TestScript (EURUSD,H1)  [ 
LN      0       13:47:20.584    TestScript (EURUSD,H1)  "Weak" "No"  
JI      0       13:47:20.584    TestScript (EURUSD,H1)  "Weak" "Yes" 
EL      0       13:47:20.584    TestScript (EURUSD,H1)  "Strong" "No"    
GO      0       13:47:20.584    TestScript (EURUSD,H1)  "Strong" "Yes"   
JG      0       13:47:20.584    TestScript (EURUSD,H1)  "Weak" "Yes" 
JN      0       13:47:20.584    TestScript (EURUSD,H1)  "Weak" "Yes" 
JE      0       13:47:20.584    TestScript (EURUSD,H1)  "Weak" "Yes" 
EP      0       13:47:20.584    TestScript (EURUSD,H1)  "Strong" "No"    
HK      0       13:47:20.584    TestScript (EURUSD,H1)  ] 
PP      0       13:47:20.584    TestScript (EURUSD,H1)  columns = 2 rows = 10
HG      0       13:47:20.584    TestScript (EURUSD,H1)  Final Parent Entropy Array and Class Numbers
FQ      0       13:47:20.584    TestScript (EURUSD,H1)  "Mild" "Cool"
OF      0       13:47:20.584    TestScript (EURUSD,H1)  0.9710 0.9183
IO      0       13:47:20.584    TestScript (EURUSD,H1)  5 3


AQUI ESTÁ UMA VISÃO GERAL DA ÁRVORE CONSTRUÍDA, eu achei este pedaço de código difícil e confuso de ler, que apesar do processo, ele parece fácil de calcular os valores manualmente. Assim, decidi explicá-lo em detalhes nesta seção.


void CDecisionTree::BuildTree(void)
 {   
    int ClassNumbers[];
    
    int max_gain = 0;
    double IGArr[]; 
    //double parent_entropy = Entropy(p_ClassNumbers,single_rowstotal);
    
    string p_Classes[];     //parent classes
    double P_EntropyArr[];  //Parent Entropy
    int p_ClassNumbers[]; //parent/ Target variable class numbers
    
    GetClasses(TargetArr,m_DatasetClasses,p_ClassNumbers);
    
    ArrayResize(P_EntropyArr,1);
    P_EntropyArr[0] = Entropy(p_ClassNumbers,single_rowstotal);

//--- temporary disposable arrays for parent node information

   string TempP_Classes[];
   double TempP_EntropyArr[];
   int    TempP_ClassNumbers[];
   
//---

    if (m_debug) Print("Default Parent Entropy ",P_EntropyArr[0]);
   
    int cols = m_colschosen; 
     
        
      for (int A =0; A<ArraySize(P_EntropyArr); A++)  
        {
           printf("<<<<<<<<    Parent Entropy  %.5f  A = %d  >>>>>>>> ",P_EntropyArr[A],A);
           
           
             for (int i=0; i<cols-1; i++) //we substract with one to remove the independent variable coumn
               {
                  int rows = ArraySize(m_dataset)/cols;
                    
                    string Arr[]; //ArrayFor the current column
                    string ArrTarg[]; //Array for the current target
                    
                    ArrayResize(Arr,rows);
                    ArrayResize(ArrTarg,rows);
                    
                       printf("   <<<<<   C O L U M N  %s   >>>>>  ",DataColumnNames[i]);
                       int index_target=cols-1;
                       for (int j=0; j<rows; j++) //get column data and its target column
                          {
                              int index = i+j * cols;
                              //Print("index ",index);
                              Arr[j] = m_dataset[index];
         
                              //printf("ArrTarg[%d] = %s m_dataset[%d] =%s ",j,ArrTarg[j],index_target,m_dataset[index_target]);
                              ArrTarg[j] = m_dataset[index_target];
                              
                              //printf("Arr[%d] = %s ArrTarg[%d] = %s ",j,Arr[j],j,ArrTarg[j]); 
                              
                              index_target += cols; //the last index of all the columns
                          }  
           
         //--- Finding the Entropy
                        
                     //The function to find the Entropy of samples in a given column inside its loop
                        //then restores all the entropy into one array
                
                        
         //--- Finding the Information Gain
                  
                        //The Function to find the information gain from the entropy array above

         //---

                        if (i == max_gain)
                         { 
                          //Get the maximum information gain of all the information gain in all columns then 
                        //store it to the parent information gain
                         }
                  
         //---
                  
                  ZeroMemory(ClassNumbers);
                  ZeroMemory(SamplesNumbers);
                  
               }
               
         //---- Get the parent Entropy, class and class numbers
               // here we store the obtained parent class from the information gain metric then we store them into a parent array
                  ArrayCopy(p_Classes,TempP_Classes);
                  ArrayCopy(P_EntropyArr,TempP_EntropyArr);
                  ArrayCopy(p_ClassNumbers,TempP_ClassNumbers);
               
         //---
         
            string Node[1]; 
            Node[0] = DataColumnNames[max_gain];
            
            if (m_debug)
            printf("Parent Node will be %s with IG = %.5f",Node[0],IGArr[max_gain]);
            
            if (A == 0)
             DrawTree(Node,"parent",A);

             DrawTree(p_Classes,"child",A);
            
       
            
         //---  CLASSIFY THE MATRIX
         MatrixClassify(m_dataset,p_Classes,cols);
         
          
         //--- Search if there is zero entropy in Array if there is any remove its data from the dataset
                 

            if (P_EntropyArr[e] == 0) { zero_entropy = true; zero_entropy_index=e; break; }
            
            if (zero_entropy) //if there is zero in the Entropy Array 
              {
                MatrixRemoveRow(m_dataset,p_Classes[zero_entropy_index],cols);    
               
                rows_total = ArraySize(m_dataset); //New number of total rows from Array   
           
                
                //we also remove the entropy from the Array and its information everywhere else from the parent Node That we are going to build next
                
                ArrayRemove(P_EntropyArr,zero_entropy_index,1);
                ArrayRemove(p_Classes,zero_entropy_index,1);
                ArrayRemove(p_ClassNumbers,zero_entropy_index,1);
              }
            
            if (m_debug)  
             Print("rows total ",rows_total," ",p_Classes[zero_entropy_index]," ",p_ClassNumbers[zero_entropy_index]);
            
//---    REMOVING THE PARENT/ ROOT NODE FROM OUR DATASET

            MatrixRemoveColumn(m_dataset,max_gain,cols);
         
         // After removing the columns assing the new values to these global variables
         
            cols = cols-1;   // remove that one column that has been removed
            rows_total = rows_total - single_rowstotal; //remove the size of one column rows
            
         // we also remove the column from column names Array 
            ArrayRemove(DataColumnNames,max_gain,1);

            
//---

         
      }

      
 }


Conclusão

Nós cobrimos os cálculos básicos envolvidos nas árvores de decisão. Este tópico é difícil e longo para cobrir em apenas um artigo, espero terminá-lo no próximo ou em dois artigos. Lembre-se, a biblioteca tem quase tudo o que você precisa para começar a construir os algoritmos de árvore de decisão para resolver os problemas de negociação com os quais você se importa.

Obrigado pela atenção! Link do meu repositório do GitHub: https://github.com/MegaJoctan/DecisionTree-Classification-tree-MQL5.

Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/11061

Arquivos anexados |
decisiontree_2.zip (42.95 KB)
Letreiro de Cotação — Versão Melhorada Letreiro de Cotação — Versão Melhorada
Que tão darmos uma apimentada na versão básica do Letreiro. Primeira coisa que iremos fazer, é modificar o letreiro de forma a acrescentar uma imagem, seja ela o logotipo do ativo, ou uma outra imagem qualquer, apenas para facilitar uma rápida identificação, de qual ativo estamos vendo.
Letreiro de Cotação — Versão Básica Letreiro de Cotação — Versão Básica
Aqui irei mostrar como criar aquelas faixas, normalmente usadas para mostrar cotações no caso das plataformas, mas usando pura e simplesmente MQL5, nada de programação externa complicada ou cheia de frescura.
Como desenvolver um sistema de negociação baseado no indicador Williams PR Como desenvolver um sistema de negociação baseado no indicador Williams PR
Bem-vindo a este novo artigo em nossa série sobre como aprender a desenvolver um sistema de negociação com base nos indicadores técnicos mais populares da MQL5. Neste artigo, nós aprenderemos como desenvolver um sistema de negociação pelo indicador %R de Williams.
Como desenvolver um sistema de negociação baseado no indicador Volumes Como desenvolver um sistema de negociação baseado no indicador Volumes
Aqui está um novo artigo da nossa série sobre como aprender a desenvolver um sistema de negociação com base nos indicadores técnicos mais populares. O artigo atual será dedicado ao indicador de Volumes. O volume como conceito é um dos fatores mais importantes na negociação nos mercados financeiros e nós temos que prestar atenção quanto a isso. Através deste artigo, nós aprenderemos como desenvolver um sistema de negociação simples pelo indicador Volumes.