![Ciência de Dados e Aprendizado de Máquina (Parte 19): Supercharge Seus Modelos de IA com AdaBoost](https://c.mql5.com/2/65/Data_Science_and_Machine_Learning_7Part_191_Supercharge_Your_AI_models_with_AdaBoost_600x314.jpg)
Ciência de Dados e Aprendizado de Máquina (Parte 19): Supercharge Seus Modelos de IA com AdaBoost
O que é Adaboost?
Adaboost, abreviação de adaptive boosting, é um modelo de aprendizado de máquina em conjunto que tenta construir um classificador forte a partir de classificadores fracos.Como funciona?
- O algoritmo atribui pesos às instâncias com base em sua classificação correta ou incorreta.
- Ele combina aprendizes fracos usando uma soma ponderada.
- O aprendiz forte final é uma combinação linear de aprendizes fracos com pesos determinados durante o processo de treinamento.
Por que alguém deveria se importar em usar Adaboost?
Adaboost oferece vários benefícios, incluindo:
- Melhoria na Precisão – O Boosting pode melhorar a precisão geral do modelo combinando várias previsões de modelos fracos. Média das previsões feitas por todos os modelos para regressão ou votação sobre elas para classificação para aumentar a precisão do modelo finalidade
- Robustez contra Overfitting – O Boosting pode reduzir o risco de overfitting atribuindo pesos às entradas classificadas incorretamente.
- Melhor manejo de dados desbalanceados – O Boosting pode lidar com dados desbalanceados focando mais nos pontos de dados que são classificados incorretamente.
- Melhor interpretabilidade – O Boosting pode aumentar a interpretabilidade do modelo dividindo o processo de decisão do modelo em vários processos.
O que é um Stump de Decisão?
Um Stump de Decisão é um modelo simples de aprendizado de máquina usado como um aprendiz fraco em métodos de conjunto como Adaboost. Ele é essencialmente um modelo de aprendizado de máquina simplificado para tomar decisões com base em uma única característica e um limiar. O objetivo de usar um stump de decisão como um aprendiz fraco é capturar um padrão básico nos dados que pode contribuir para melhorar o modelo de conjunto geral.
Abaixo está uma breve explicação da teoria por trás de um stump de decisão, usando o classificador Árvore de Decisão como exemplo:
1. Estrutura:
Um stump de decisão toma uma decisão binária com base em uma única característica e um limiar.
Ele divide os dados em dois grupos: aqueles com valores de característica abaixo do limiar e aqueles com valores acima.
Isso é comumente implementado no construtor da maioria dos nossos classificadores nesta Biblioteca:
CDecisionTreeClassifier(uint min_samples_split=2, uint max_depth=2, mode mode_=MODE_GINI); ~CDecisionTreeClassifier(void);
2. Treinamento:.
Durante o treinamento, o stump de decisão identifica a característica e o limiar que minimizam um determinado critério, muitas vezes o erro de classificação ponderado.
O erro de classificação é calculado para cada possível divisão, e a que possui o menor erro é escolhida.
- A função fit é onde todo o treinamento é realizado:
void fit(matrix &x, vector &y);
3. Predição:
Para a predição, um ponto de dados é classificado com base em se seu valor de característica está acima ou abaixo do limiar escolhido.
double predict(vector &x); vector predict(matrix &x);
Comumente, os aprendizes fracos usados em métodos de ensemble como o AdaBoost incluem:
1.Stumps de Decisão/Árvores de Decisão:
Conforme descrito acima, stumps de decisão ou árvores de decisão rasas são comumente usados devido à sua simplicidade.
2. Modelos Lineares:
Modelos lineares como regressão logística ou SVMs lineares podem ser usados como aprendizes fracos.
3. Modelos Polinomiais:
Modelos polinomiais de grau mais alto podem capturar relações mais complexas, e usar polinomiais de baixo grau pode atuar como aprendizes fracos.
4. Redes Neurais (Rasas):
Redes neurais rasas com um pequeno número de camadas e neurônios são às vezes usadas.
5. Modelos Gaussianos:
Modelos gaussianos, como o Naive Bayes Gaussiano, podem ser empregados como aprendizes fracos.
A escolha de um aprendiz fraco depende das características específicas dos dados e do problema em questão. Na prática, stumps de decisão são populares devido à sua simplicidade e eficiência em algoritmos de boosting. A abordagem de ensemble do AdaBoost melhora o desempenho ao combinar as previsões desses aprendizes fracos.
Como um stump de decisão é um modelo, precisamos dar ao construtor da classe Adaboost os argumentos dos parâmetros do nosso modelo fraco.
class AdaBoost { protected: vector m_alphas; vector classes_in_data; uint m_min_split, m_max_depth; CDecisionTreeClassifier *weak_learners[]; //store weak_learner pointers for memory allocation tracking CDecisionTreeClassifier *weak_learner; uint m_estimators; public: AdaBoost(uint min_split, uint max_depth, uint n_estimators=50); ~AdaBoost(void); void fit(matrix &x, vector &y); int predict(vector &x); vector predict(matrix &x); };
Este exemplo usa a árvore de decisão, mas qualquer modelo de aprendizado de máquina de classificação pode ser implementado.
Construindo a classe AdaBoost:
O termo número de estimadores refere-se ao número de aprendizes fracos (modelos base ou stumps de decisão) que são combinados para criar o aprendiz forte final em um algoritmo de aprendizado em conjunto. No contexto de algoritmos como AdaBoost ou gradient boosting, esse parâmetro é frequentemente denotado como n_estimators.
AdaBoost::AdaBoost(uint min_split, uint max_depth, uint n_estimators=50) :m_estimators(n_estimators), m_min_split(min_split), m_max_depth(max_depth) { ArrayResize(weak_learners, n_estimators); //Resizing the array to retain the number of base weak_learners }
A partir da seção protegida da classe, você viu o vetor m_alphas , enquanto também ouviu o termo weights várias vezes neste artigo. Abaixo está a explicação:
Valores de Alph
Os valores de alpha representam a contribuição ou peso atribuído a cada aprendiz fraco no conjunto. Esses valores são calculados com base no desempenho de cada aprendiz fraco durante o treinamento.
Valores de alpha mais altos são atribuídos a aprendizes fracos que têm bom desempenho na redução de erros de treinamento.
A fórmula para calcular alpha é geralmente dada por:
onde:
é o erro ponderado do t-th aprendiz fraco.
Implementation:
double alpha = 0.5 * log((1-error) / (error + 1e-10));
Pesos:
Os vetores de pesos representam a importância de cada instância de treinamento em cada iteração.
Durante o treinamento, os pesos das instâncias classificadas incorretamente são aumentados para focar nos exemplos difíceis de classificar na próxima iteração.
A fórmula para atualizar os pesos das instâncias é geralmente dada por:
é o peso da instância i na iteração
é o peso atribuído ao t-th aprendiz fraco.
é o rótulo verdadeiro da instância
é a previsão do t-th aprendiz fraco na instância
é um fator de normalização para garantir que a soma dos pesos seja igual a 1.
Implementation:
for (ulong j=0; j<m; j++) misclassified[j] = (preds[j] != y[j]); error = (misclassified * weights).Sum() / (double)weights.Sum(); //--- Calculate the weight of a weak learner in the final model double alpha = 0.5 * log((1-error) / (error + 1e-10)); //--- Update instance weights weights *= exp(-alpha * y * preds); weights /= weights.Sum();
Treinando o modelo Adaboost:
Assim como outras técnicas de ensemble, n modelos (referidos como m_estimators na função abaixo) são usados para fazer previsões nos mesmos dados, o voto da maioria ou outras técnicas podem ser utilizadas para determinar o melhor resultado possível.
void AdaBoost::fit(matrix &x,vector &y) { m_alphas.Resize(m_estimators); classes_in_data = MatrixExtend::Unique(y); //Find the target variables in the class ulong m = x.Rows(), n = x.Cols(); vector weights(m); weights = weights.Fill(1.0) / m; //Initialize instance weights vector preds(m); vector misclassified(m); double error = 0; for (uint i=0; i<m_estimators; i++) { //--- weak_learner = new CDecisionTreeClassifier(this.m_min_split, m_max_depth); weak_learner.fit(x, y); //fitting the randomized data to the i-th weak_learner preds = weak_learner.predict(x); //making predictions for the i-th weak_learner for (ulong j=0; j<m; j++) misclassified[j] = (preds[j] != y[j]); error = (misclassified * weights).Sum() / (double)weights.Sum(); //--- Calculate the weight of a weak learner in the final weak_learner double alpha = 0.5 * log((1-error) / (error + 1e-10)); //--- Update instance weights weights *= exp(-alpha * y* preds); weights /= weights.Sum(); //--- save a weak learner and its weight this.m_alphas[i] = alpha; this.weak_learners[i] = weak_learner; } }
Assim como qualquer outra técnica de ensemble, bootstrapping é crucial também. Sem ele, todos os modelos e os dados são simplesmente os mesmos, o que poderia fazer com que o desempenho de todos os modelos se tornasse indistinguível um do outro. O bootstrapping precisa ser implementado:
void AdaBoost::fit(matrix &x,vector &y) { m_alphas.Resize(m_estimators); classes_in_data = MatrixExtend::Unique(y); //Find the target variables in the class ulong m = x.Rows(), n = x.Cols(); vector weights(m); weights = weights.Fill(1.0) / m; //Initialize instance weights vector preds(m); vector misclassified(m); //--- matrix data = MatrixExtend::concatenate(x, y); matrix temp_data; matrix x_subset; vector y_subset; double error = 0; for (uint i=0; i<m_estimators; i++) { temp_data = data; MatrixExtend::Randomize(temp_data, this.m_random_state, this.m_boostrapping); if (!MatrixExtend::XandYSplitMatrices(temp_data, x_subset, y_subset)) //Get randomized subsets { ArrayRemove(weak_learners,i,1); //Delete the invalid weak_learner printf("%s %d Failed to split data",__FUNCTION__,__LINE__); continue; } //--- weak_learner = new CDecisionTreeClassifier(this.m_min_split, m_max_depth); weak_learner.fit(x_subset, y_subset); //fitting the randomized data to the i-th weak_learner preds = weak_learner.predict(x_subset); //making predictions for the i-th weak_learner //printf("[%d] Accuracy %.3f ",i,Metrics::accuracy_score(y_subset, preds)); for (ulong j=0; j<m; j++) misclassified[j] = (preds[j] != y_subset[j]); error = (misclassified * weights).Sum() / (double)weights.Sum(); //--- Calculate the weight of a weak learner in the final weak_learner double alpha = 0.5 * log((1-error) / (error + 1e-10)); //--- Update instance weights weights *= exp(-alpha * y_subset * preds); weights /= weights.Sum(); //--- save a weak learner and its weight this.m_alphas[i] = alpha; this.weak_learners[i] = weak_learner; } }O construtor da classe também teve que ser alterado:
class AdaBoost { protected: vector m_alphas; vector classes_in_data; int m_random_state; bool m_boostrapping; uint m_min_split, m_max_depth; CDecisionTreeClassifier *weak_learners[]; //store weak_learner pointers for memory allocation tracking CDecisionTreeClassifier *weak_learner; uint m_estimators; public: AdaBoost(uint min_split, uint max_depth, uint n_estimators=50, int random_state=42, bool bootstrapping=true); ~AdaBoost(void); void fit(matrix &x, vector &y); int predict(vector &x); vector predict(matrix &x); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ AdaBoost::AdaBoost(uint min_split, uint max_depth, uint n_estimators=50, int random_state=42, bool bootstrapping=true) :m_estimators(n_estimators), m_random_state(random_state), m_boostrapping(bootstrapping), m_min_split(min_split), m_max_depth(max_depth) { ArrayResize(weak_learners, n_estimators); //Resizing the array to retain the number of base weak_learners }
Obtendo as Previsões da Maioria
Usando os pesos treinados, o classificador Adaboost determina a classe com o máximo de votos, significando que ela tem mais probabilidade de aparecer do que as outras.
int AdaBoost::predict(vector &x) { // Combine weak learners using weighted sum vector weak_preds(m_estimators), final_preds(m_estimators); for (uint i=0; i<this.m_estimators; i++) weak_preds[i] = this.weak_learners[i].predict(x); return (int)weak_preds[(this.m_alphas*weak_preds).ArgMax()]; //Majority decision class }
Agora vamos ver como podemos usar o modelo dentro de um Expert Advisor:
#include <MALE5\Ensemble\AdaBoost.mqh> DecisionTree::AdaBoost *ada_boost_tree; LogisticRegression::AdaBoost *ada_boost_logit; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- string headers; matrix data = MatrixExtend::ReadCsv("iris.csv",headers); matrix x; vector y; MatrixExtend::XandYSplitMatrices(data,x,y); ada_boost_tree = new DecisionTree::AdaBoost(2,1,10,42); ada_boost_tree.fit(x,y); vector predictions = ada_boost_tree.predict(x); printf("Adaboost acc = %.3f",Metrics::accuracy_score(y, predictions)); //--- return(INIT_SUCCEEDED); }
Usando o dataset iris.csv apenas para construir o modelo e para fins de depuração. Isso resultou em:
2024.01.17 17:52:27.914 AdaBoost Test (EURUSD,H1) Adaboost acc = 0.960
Parece que nosso modelo está indo bem até agora, com valores de precisão em torno de 90%, depois que defini o random_state para -1, o que fará com que o GetTickCount seja usado como uma semente aleatória cada vez que o EA é executado, para que eu possa avaliar o modelo em um ambiente muito mais aleatório.
QK 0 17:52:27.914 AdaBoost Test (EURUSD,H1) Adaboost acc = 0.960 LL 0 17:52:35.436 AdaBoost Test (EURUSD,H1) Adaboost acc = 0.947 JD 0 17:52:42.806 AdaBoost Test (EURUSD,H1) Adaboost acc = 0.960 IL 0 17:52:50.071 AdaBoost Test (EURUSD,H1) Adaboost acc = 0.933 MD 0 17:52:57.822 AdaBoost Test (EURUSD,H1) Adaboost acc = 0.967
Os mesmos padrões e estruturas de codificação podem ser seguidos para outros weak learners presentes em nossa biblioteca. Veja quando a regressão logística foi usada como um weak learner:
A única diferença em toda a classe é encontrada na função fit, onde o tipo de modelo implementado como weak learner é Regressão Logística:
void AdaBoost::fit(matrix &x,vector &y) { m_alphas.Resize(m_estimators); classes_in_data = MatrixExtend::Unique(y); //Find the target variables in the class ulong m = x.Rows(), n = x.Cols(); vector weights(m); weights = weights.Fill(1.0) / m; //Initialize instance weights vector preds(m); vector misclassified(m); //--- matrix data = MatrixExtend::concatenate(x, y); matrix temp_data; matrix x_subset; vector y_subset; double error = 0; for (uint i=0; i<m_estimators; i++) { temp_data = data; MatrixExtend::Randomize(temp_data, this.m_random_state, this.m_boostrapping); if (!MatrixExtend::XandYSplitMatrices(temp_data, x_subset, y_subset)) //Get randomized subsets { ArrayRemove(weak_learners,i,1); //Delete the invalid weak_learner printf("%s %d Failed to split data",__FUNCTION__,__LINE__); continue; } //--- weak_learner = new CLogisticRegression(); weak_learner.fit(x_subset, y_subset); //fitting the randomized data to the i-th weak_learner preds = weak_learner.predict(x_subset); //making predictions for the i-th weak_learner for (ulong j=0; j<m; j++) misclassified[j] = (preds[j] != y_subset[j]); error = (misclassified * weights).Sum() / (double)weights.Sum(); //--- Calculate the weight of a weak learner in the final weak_learner double alpha = 0.5 * log((1-error) / (error + 1e-10)); //--- Update instance weights weights *= exp(-alpha * y_subset * preds); weights /= weights.Sum(); //--- save a weak learner and its weight this.m_alphas[i] = alpha; this.weak_learners[i] = weak_learner; } }
Modelos de IA com AdaBoost no Testador de Estratégias
Ao usar o indicador de banda de Bollinger aplicado ao preço de abertura, estamos tentando treinar nossos modelos para aprender a prever o próximo fechamento de candle, seja ele altista, baixista ou nenhum dos dois (MANTER).
Vamos construir um Expert Advisor para testar nossos modelos no ambiente de negociação, começando com o código para coletar os dados de treinamento:
Coletando os Dados de Treinamento:
//--- Data Collection for training the model //--- x variables Bollinger band only matrix dataset; indicator_v.CopyIndicatorBuffer(bb_handle,0,0,train_bars); //Main LINE dataset = MatrixExtend::concatenate(dataset, indicator_v); indicator_v.CopyIndicatorBuffer(bb_handle,1,0,train_bars); //UPPER BB dataset = MatrixExtend::concatenate(dataset, indicator_v); indicator_v.CopyIndicatorBuffer(bb_handle,2,0,train_bars); //LOWER BB dataset = MatrixExtend::concatenate(dataset, indicator_v); //--- Target Variable int size = CopyRates(Symbol(),PERIOD_CURRENT,0,train_bars,rates); vector y(size); switch(model) { case DECISION_TREE: { for (ulong i=0; i<y.Size(); i++) { if (rates[i].close > rates[i].open) y[i] = 1; //buy signal else if (rates[i].close < rates[i].open) y[i] = 2; //sell signal else y[i] = 0; //Hold signal } } break; case LOGISTIC_REGRESSION: for (ulong i=0; i<indicator_v.Size(); i++) { y[i] = (rates[i].close > rates[i].open); //if close > open buy else sell } break; } dataset = MatrixExtend::concatenate(dataset, y); //Add the target variable to the dataset if (MQLInfoInteger(MQL_DEBUG)) { Print("Data Head"); MatrixExtend::PrintShort(dataset); }
Notou a mudança na criação da variável alvo? Como a árvore de decisão é versátil e pode lidar bem com múltiplas classes na variável alvo, ela tem a capacidade de classificar três padrões no mercado, COMPRAR, VENDER e MANTER. Ao contrário do modelo de regressão logística que tem a função sigmoide em seu núcleo e que classifica bem duas classes, 0 e 1, a melhor coisa é preparar a condição da variável alvo para ser COMPRAR ou VENDER.
Treinamento e Teste do Modelo Treinado:
Um Elefante na sala:
MatrixExtend::TrainTestSplitMatrices(dataset,train_x,train_y,test_x,test_y,0.7,_random_state);
Esta função divide os dados em amostras de treinamento e teste, dado um estado aleatório para embaralhamento, 70% dos dados para a amostra de teste, enquanto os outros 30% para teste.
Mas antes que possamos usar os dados recém-coletados, A Normalização ainda é crucial para o desempenho do modelo.
//--- Training and testing the trained model matrix train_x, test_x; vector train_y, test_y; MatrixExtend::TrainTestSplitMatrices(dataset,train_x,train_y,test_x,test_y,0.7,_random_state); //Train test split data | This function splits the data into training and testing sample given a random state and 70% of data to test while the rest 30% for testing train_x = scaler.fit_transform(train_x); //Standardize the training data test_x = scaler.transform(test_x); //Do the same for the test data Print("-----> ",EnumToString(model)); vector preds; switch(model) { case DECISION_TREE: ada_boost_tree = new DecisionTree::AdaBoost(tree_min_split, tree_max_depth, _n_estimators, -1, _bootstrapping); //Building the //--- Training ada_boost_tree.fit(train_x, train_y); preds = ada_boost_tree.predict(train_x); printf("Train Accuracy %.3f",Metrics::accuracy_score(train_y, preds)); //--- Testing preds = ada_boost_tree.predict(test_x); printf("Test Accuracy %.3f",Metrics::accuracy_score(test_y, preds)); break; case LOGISTIC_REGRESSION: ada_boost_logit = new LogisticRegression::AdaBoost(_n_estimators,-1, _bootstrapping); //--- Training ada_boost_logit.fit(train_x, train_y); preds = ada_boost_logit.predict(train_x); printf("Train Accuracy %.3f",Metrics::accuracy_score(train_y, preds)); //--- Testing preds = ada_boost_logit.predict(test_x); printf("Test Accuracy %.3f",Metrics::accuracy_score(test_y, preds)); break; }
Saídas:
PO 0 22:59:11.807 AdaBoost Test (EURUSD,H1) -----> DECISION_TREE CI 0 22:59:20.204 AdaBoost Test (EURUSD,H1) Building Estimator [1/10] Accuracy Score 0.561 OD 0 22:59:27.883 AdaBoost Test (EURUSD,H1) Building Estimator [2/10] Accuracy Score 0.601 NP 0 22:59:38.316 AdaBoost Test (EURUSD,H1) Building Estimator [3/10] Accuracy Score 0.541 LO 0 22:59:48.327 AdaBoost Test (EURUSD,H1) Building Estimator [4/10] Accuracy Score 0.549 LK 0 22:59:56.813 AdaBoost Test (EURUSD,H1) Building Estimator [5/10] Accuracy Score 0.570 OF 0 23:00:09.552 AdaBoost Test (EURUSD,H1) Building Estimator [6/10] Accuracy Score 0.517 GR 0 23:00:18.322 AdaBoost Test (EURUSD,H1) Building Estimator [7/10] Accuracy Score 0.571 GI 0 23:00:29.254 AdaBoost Test (EURUSD,H1) Building Estimator [8/10] Accuracy Score 0.556 HE 0 23:00:37.632 AdaBoost Test (EURUSD,H1) Building Estimator [9/10] Accuracy Score 0.599 DS 0 23:00:47.522 AdaBoost Test (EURUSD,H1) Building Estimator [10/10] Accuracy Score 0.567 OP 0 23:00:47.524 AdaBoost Test (EURUSD,H1) Train Accuracy 0.590 OG 0 23:00:47.525 AdaBoost Test (EURUSD,H1) Test Accuracy 0.513 MK 0 23:24:06.573 AdaBoost Test (EURUSD,H1) Building Estimator [1/10] Accuracy Score 0.491 HK 0 23:24:06.575 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [1/10] mse 0.43700 QO 0 23:24:06.575 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [2/10] mse 0.43432 KP 0 23:24:06.576 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [3/10] mse 0.43168 MD 0 23:24:06.577 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [4/10] mse 0.42909 FI 0 23:24:06.578 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [5/10] mse 0.42652 QJ 0 23:24:06.579 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [6/10] mse 0.42400 IN 0 23:24:06.580 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [7/10] mse 0.42151 NS 0 23:24:06.581 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [8/10] mse 0.41906 GD 0 23:24:06.582 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [9/10] mse 0.41664 DK 0 23:24:06.582 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [10/10] mse 0.41425 IQ 0 23:24:06.585 AdaBoost Test (EURUSD,H1) Building Estimator [2/10] Accuracy Score 0.477 JP 0 23:24:06.586 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [1/10] mse 0.43700 DE 0 23:24:06.587 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [2/10] mse 0.43432 RF 0 23:24:06.588 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [3/10] mse 0.43168 KJ 0 23:24:06.588 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [4/10] mse 0.42909 FO 0 23:24:06.589 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [5/10] mse 0.42652 NP 0 23:24:06.590 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [6/10] mse 0.42400 CD 0 23:24:06.591 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [7/10] mse 0.42151 KI 0 23:24:06.591 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [8/10] mse 0.41906 NM 0 23:24:06.592 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [9/10] mse 0.41664 EM 0 23:24:06.592 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [10/10] mse 0.41425 EO 0 23:24:06.593 AdaBoost Test (EURUSD,H1) Building Estimator [3/10] Accuracy Score 0.477 KF 0 23:24:06.594 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [1/10] mse 0.41931 HK 0 23:24:06.594 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [2/10] mse 0.41690 RL 0 23:24:06.595 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [3/10] mse 0.41452 IP 0 23:24:06.596 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [4/10] mse 0.41217 KE 0 23:24:06.596 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [5/10] mse 0.40985 DI 0 23:24:06.597 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [6/10] mse 0.40757 IJ 0 23:24:06.597 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [7/10] mse 0.40533 MO 0 23:24:06.598 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [8/10] mse 0.40311 PS 0 23:24:06.599 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [9/10] mse 0.40093 CG 0 23:24:06.600 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [10/10] mse 0.39877 NE 0 23:24:06.601 AdaBoost Test (EURUSD,H1) Building Estimator [4/10] Accuracy Score 0.499 EL 0 23:24:06.602 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [1/10] mse 0.41931 MQ 0 23:24:06.603 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [2/10] mse 0.41690 PE 0 23:24:06.603 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [3/10] mse 0.41452 OF 0 23:24:06.604 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [4/10] mse 0.41217 JK 0 23:24:06.605 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [5/10] mse 0.40985 KO 0 23:24:06.606 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [6/10] mse 0.40757 FP 0 23:24:06.606 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [7/10] mse 0.40533 PE 0 23:24:06.607 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [8/10] mse 0.40311 CI 0 23:24:06.608 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [9/10] mse 0.40093 NI 0 23:24:06.609 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [10/10] mse 0.39877 KS 0 23:24:06.610 AdaBoost Test (EURUSD,H1) Building Estimator [5/10] Accuracy Score 0.499 QR 0 23:24:06.611 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [1/10] mse 0.42037 MG 0 23:24:06.611 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [2/10] mse 0.41794 LK 0 23:24:06.612 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [3/10] mse 0.41555 ML 0 23:24:06.613 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [4/10] mse 0.41318 PQ 0 23:24:06.614 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [5/10] mse 0.41085 FE 0 23:24:06.614 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [6/10] mse 0.40856 FF 0 23:24:06.615 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [7/10] mse 0.40630 FJ 0 23:24:06.616 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [8/10] mse 0.40407 KO 0 23:24:06.617 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [9/10] mse 0.40187 NS 0 23:24:06.618 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [10/10] mse 0.39970 EH 0 23:24:06.619 AdaBoost Test (EURUSD,H1) Building Estimator [6/10] Accuracy Score 0.497 FH 0 23:24:06.620 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [1/10] mse 0.41565 LM 0 23:24:06.621 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [2/10] mse 0.41329 IQ 0 23:24:06.622 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [3/10] mse 0.41096 KR 0 23:24:06.622 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [4/10] mse 0.40867 LF 0 23:24:06.623 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [5/10] mse 0.40640 NK 0 23:24:06.624 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [6/10] mse 0.40417 OL 0 23:24:06.625 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [7/10] mse 0.40197 RP 0 23:24:06.627 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [8/10] mse 0.39980 OE 0 23:24:06.628 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [9/10] mse 0.39767 EE 0 23:24:06.628 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [10/10] mse 0.39556 QF 0 23:24:06.629 AdaBoost Test (EURUSD,H1) Building Estimator [7/10] Accuracy Score 0.503 CN 0 23:24:06.630 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [1/10] mse 0.41565 IR 0 23:24:06.631 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [2/10] mse 0.41329 HG 0 23:24:06.632 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [3/10] mse 0.41096 RH 0 23:24:06.632 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [4/10] mse 0.40867 ML 0 23:24:06.633 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [5/10] mse 0.40640 FQ 0 23:24:06.633 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [6/10] mse 0.40417 QR 0 23:24:06.634 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [7/10] mse 0.40197 NF 0 23:24:06.634 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [8/10] mse 0.39980 EK 0 23:24:06.635 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [9/10] mse 0.39767 CL 0 23:24:06.635 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [10/10] mse 0.39556 LL 0 23:24:06.636 AdaBoost Test (EURUSD,H1) Building Estimator [8/10] Accuracy Score 0.503 HD 0 23:24:06.637 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [1/10] mse 0.44403 IH 0 23:24:06.638 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [2/10] mse 0.44125 CM 0 23:24:06.638 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [3/10] mse 0.43851 DN 0 23:24:06.639 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [4/10] mse 0.43580 DR 0 23:24:06.639 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [5/10] mse 0.43314 CG 0 23:24:06.640 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [6/10] mse 0.43051 EK 0 23:24:06.640 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [7/10] mse 0.42792 JL 0 23:24:06.641 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [8/10] mse 0.42537 EQ 0 23:24:06.641 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [9/10] mse 0.42285 OF 0 23:24:06.642 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [10/10] mse 0.42037 GJ 0 23:24:06.642 AdaBoost Test (EURUSD,H1) Building Estimator [9/10] Accuracy Score 0.469 GJ 0 23:24:06.643 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [1/10] mse 0.44403 ON 0 23:24:06.643 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [2/10] mse 0.44125 LS 0 23:24:06.644 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [3/10] mse 0.43851 HG 0 23:24:06.644 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [4/10] mse 0.43580 KH 0 23:24:06.645 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [5/10] mse 0.43314 FM 0 23:24:06.645 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [6/10] mse 0.43051 IQ 0 23:24:06.646 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [7/10] mse 0.42792 QR 0 23:24:06.646 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [8/10] mse 0.42537 IG 0 23:24:06.647 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [9/10] mse 0.42285 RH 0 23:24:06.647 AdaBoost Test (EURUSD,H1) ---> Logistic regression build epoch [10/10] mse 0.42037 KS 0 23:24:06.648 AdaBoost Test (EURUSD,H1) Building Estimator [10/10] Accuracy Score 0.469 NP 0 23:24:06.652 AdaBoost Test (EURUSD,H1) Train Accuracy 0.491 GG 0 23:24:06.654 AdaBoost Test (EURUSD,H1) Test Accuracy 0.447
Até agora, tudo bem! Vamos finalizar nosso Expert Advisor com as linhas de código capazes de executar negociações:
Obtendo os sinais de negociação:
void OnTick() { //--- x variables Bollinger band only | The current buffer only this time indicator_v.CopyIndicatorBuffer(bb_handle,0,0,1); //Main LINE x_inputs[0] = indicator_v[0]; indicator_v.CopyIndicatorBuffer(bb_handle,1,0,1); //UPPER BB x_inputs[1] = indicator_v[0]; indicator_v.CopyIndicatorBuffer(bb_handle,2,0,1); //LOWER BB x_inputs[2] = indicator_v[0]; //--- int signal = INT_MAX; switch(model) { case DECISION_TREE: x_inputs = scaler.transform(x_inputs); //New inputs data must be normalized the same way signal = ada_boost_tree.predict(x_inputs); break; case LOGISTIC_REGRESSION: x_inputs = scaler.transform(x_inputs); //New inputs data must be normalized the same way signal = ada_boost_logit.predict(x_inputs); break; } }
Lembre-se, 1 representa o sinal de compra para a árvore de decisão, 0 representa o sinal de compra para a regressão logística; 2 representa o sinal de venda para a árvore de decisão; 1 representa o sinal de venda para a regressão logística. Não nos importamos com o sinal 0 que representa manter para a árvore de decisão. Vamos unificar esses sinais para serem identificados como 0 e 1 para sinais de compra e venda, respectivamente.
case DECISION_TREE: x_inputs = scaler.transform(x_inputs); //New inputs data must be normalized the same way signal = ada_boost_tree.predict(x_inputs); if (signal == 1) //buy signal for decision tree signal = 0; else if (signal == 2) signal = 1; else signal = INT_MAX; //UNKNOWN NUMBER FOR HOLD break;
Uma estratégia simples feita a partir de nossos modelos:
SymbolInfoTick(Symbol(), ticks); if (isnewBar(PERIOD_CURRENT)) { if (signal == 0) //buy signal { if (!PosExists(MAGIC_NUMBER, POSITION_TYPE_BUY)) m_trade.Buy(lot_size, Symbol(), ticks.ask, ticks.ask-stop_loss*Point(), ticks.ask+take_profit*Point()); } if (signal == 1) { if (!PosExists(MAGIC_NUMBER, POSITION_TYPE_SELL)) m_trade.Sell(lot_size, Symbol(), ticks.bid, ticks.bid+stop_loss*Point(), ticks.bid-take_profit*Point()); } }
Resultados no testador de estratégias | de janeiro de 2020 a fevereiro de 2023 | Intervalo de tempo de 1 HORA:
Árvore de Decisão Adaboost:
Regressão Logística Adaboost:
Ambos os desempenhos no INTERVALO DE TEMPO DE UMA HORA estão muito longe de serem bons. Uma das principais razões para isso é que nossa estratégia é baseada nas barras atuais. Em minha experiência, esse tipo de estratégia é mais adequado para intervalos de tempo maiores, pois uma única barra representa um movimento significativo, ao contrário das pequenas barras que ocorrem 24 vezes por dia. Vamos tentar o INTERVALO DE TEMPO DE 12 HORAS.
Todos os parâmetros foram mantidos os mesmos, exceto pelo train_bars, que foi reduzido de 1000 para 100, pois intervalos de tempo maiores não têm muitas barras para solicitar o histórico de preços no passado.
Árvore de Decisão Adaboost:
Regressão Logística Adaboost:
Em conclusão:
AdaBoost emerge como um algoritmo potente capaz de melhorar significativamente o desempenho dos modelos de IA discutidos ao longo desta série de artigos. Embora venha com um custo computacional, o investimento se mostra válido quando implementado de forma judiciosa. AdaBoost tem encontrado aplicações em diversos setores e indústrias, incluindo finanças, entretenimento, educação, entre outros.
Ao concluirmos nossa exploração, é essencial reconhecer a versatilidade do algoritmo e sua capacidade de abordar desafios complexos de classificação, aproveitando a força coletiva dos aprendizes fracos. As Perguntas Frequentes (FAQs) abaixo visam oferecer clareza e insight, abordando questões comuns que podem surgir durante sua exploração do AdaBoost.
Perguntas Frequentes (FAQs) sobre Adaboost:
Pergunta: Como o AdaBoost funciona?
Resposta: O AdaBoost funciona treinando iterativamente aprendizes fracos (geralmente modelos simples como tocos de decisão) no conjunto de dados, ajustando os pesos das instâncias classificadas incorretamente a cada iteração. O modelo final é uma soma ponderada dos aprendizes fracos, com pesos maiores dados aos mais precisos.
Pergunta: O que são aprendizes fracos no AdaBoost?
Resposta: Aprendizes fracos são modelos simples que têm um desempenho ligeiramente melhor que o acaso. Tocos de decisão (árvores de decisão rasas) são comumente usados como aprendizes fracos no AdaBoost, mas outros algoritmos também podem servir a esse propósito.
Pergunta: Qual é o papel dos pesos das instâncias no AdaBoost?
Resposta: Os pesos das instâncias no AdaBoost controlam a importância de cada instância de treinamento durante o processo de aprendizado. Inicialmente, todos os pesos são definidos igualmente, e são ajustados a cada iteração para focar mais nas instâncias classificadas incorretamente, melhorando a capacidade do modelo de generalizar.
Pergunta: Como o AdaBoost lida com erros cometidos por aprendizes fracos?
Resposta: O AdaBoost atribui pesos maiores às instâncias classificadas incorretamente, forçando os aprendizes fracos subsequentes a focar mais na correção desses erros. O modelo final dá mais peso aos aprendizes fracos com taxas de erro mais baixas.
Pergunta: O AdaBoost é sensível a ruídos e outliers?
Resposta: O AdaBoost pode ser sensível a ruídos e outliers, pois tenta corrigir as classificações incorretas. Outliers podem receber pesos maiores, influenciando o modelo final. Aprendizes fracos robustos ou técnicas de pré-processamento de dados podem ser aplicados para mitigar essa sensibilidade.
Pergunta: O AdaBoost sofre de sobreajuste?
Resposta: O AdaBoost pode estar sujeito ao sobreajuste se os aprendizes fracos forem muito complexos ou se o conjunto de dados contiver ruídos. Usar aprendizes fracos mais simples e aplicar técnicas como validação cruzada pode ajudar a prevenir o sobreajuste.
Pergunta: O AdaBoost pode ser usado para problemas de regressão?
Resposta: O AdaBoost é projetado principalmente para tarefas de classificação, mas pode ser adaptado para regressão modificando o algoritmo para prever valores contínuos. Técnicas como AdaBoost.R2 existem para problemas de regressão.
Pergunta: Existem alternativas ao AdaBoost?
Resposta: Sim, existem outros métodos de aprendizado em conjunto, como Random Forest, Gradient Boosting e XGBoost. Cada método tem seus pontos fortes e fracos, e a escolha depende das características específicas dos dados e do problema em questão.
Pergunta: Em quais situações o AdaBoost é particularmente eficaz?
Resposta: O AdaBoost é eficaz ao lidar com uma variedade de aprendizes fracos e em cenários onde há necessidade de combinar múltiplos classificadores para criar um modelo robusto. Ele é frequentemente usado em detecção de faces, classificação de textos e outras aplicações do mundo real.
Para se manter atualizado sobre o progresso do desenvolvimento e correções de bugs deste algoritmo, bem como de muitos outros, por favor visite o repositório GitHub em https://github.com/MegaJoctan/MALE5.
Até mais.
Anexos:
Arquivo | Descrição|Uso |
---|---|
Adaboost.mqh | Contém classes de namespace Adaboost tanto para regressão logística quanto para a árvore de decisão. |
Logistic Regression.mqh | Contém a classe principal de regressão logística |
MatrixExtend.mqh | Contém funções adicionais de manipulação de matrizes |
metrics.mqh | Uma biblioteca contendo código para medir o desempenho de modelos de aprendizado de máquina |
preprocessing.mqh | Uma classe contendo funções para pré-processamento de dados para torná-los adequados para aprendizado de máquina |
tree.mqh | Biblioteca de árvore de decisão pode ser encontrada neste arquivo |
AdaBoost Test.mq5(EA) | O principal Expert Advisor de teste, todo o código explicado aqui é executado dentro deste arquivo |
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/14034
![Compreendendo os Paradigmas de Programação (Parte 2): Uma Abordagem Orientada a Objetos para Desenvolver um Expert Advisor de Ação de Preço](https://c.mql5.com/2/71/MQL5_Article-02_Artwork_thumbnail_WhiteBG.png)
![Inferência causal em problemas de classificação de séries temporais](https://c.mql5.com/2/66/Causal_inference_in_time_series_classification_problems___LOGO.png)
![Está chegando o novo MetaTrader 5 e MQL5](https://c.mql5.com/2/0/851_25.jpg)
![Indicador Customizado: Traçar os Pontos de Entradas Parciais em contas Netting](https://c.mql5.com/2/85/Tra7ar_os_Pontos_de_Entradas_Parciais_em_contas_Netting___LOGO.png)
![MQL5 - Linguagem para estratégias de negociação inseridas no terminal do cliente MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso