English Русский Deutsch 日本語 Português
preview
Aprendizaje automático y ciencia de datos (Parte 18): Potencie sus modelos de IA con AdaBoost

Aprendizaje automático y ciencia de datos (Parte 18): Potencie sus modelos de IA con AdaBoost

MetaTrader 5Trading | 29 julio 2024, 11:03
49 0
Omega J Msigwa
Omega J Msigwa

¿Qué es AdaBoost?

AdaBoost es un modelo de aprendizaje automático conjunto que intenta construir un clasificador fuerte a partir de clasificadores débiles.

¿Cómo funciona?

  • El algoritmo asigna pesos a las instancias en función de su clasificación correcta o incorrecta.
  • Combina los aprendices débiles mediante una suma ponderada.
  • El aprendiz fuerte final es una combinación lineal de aprendices débiles con pesos determinados durante el proceso de entrenamiento.

AdaBoost en MQL5


¿Por qué debería a alguien importarle usar Adaboost?

AdaBoost proporciona varios beneficios incluyendo:

  • Precisión mejorada - El refuerzo puede mejorar la precisión general del modelo combinando varias predicciones de modelos débiles. Promediar las predicciones realizadas por todos los modelos para la regresión o votar sobre ellos para la clasificación con el fin de aumentar la precisión del modelo final. 
  • Robustez al sobreajuste - El refuerzo puede reducir el riesgo de sobreajuste asignando los pesos a las entradas mal clasificadas.
  • Mejor manejo de datos desequilibrados - El refuerzo puede manejar los datos desequilibrados centrándose más en los puntos de datos que están mal clasificados.
  • Mejor Interpretabilidad - El refuerzo puede aumentar la interpretabilidad del modelo al dividir el proceso de decisión del modelo en múltiples procesos. 


¿Qué es un modelo de decisión simple?

Un modelo de decisión simple es un modelo de aprendizaje automático simple utilizado como un aprendiz débil en métodos de conjunto como AdaBoost. Es esencialmente un modelo de aprendizaje automático simplificado para tomar decisiones basadas en una sola característica y un umbral. El objetivo de usar un modelo de decisión simple como un aprendiz débil es capturar un patrón básico en los datos que pueda contribuir a mejorar el modelo de conjunto general.

A continuación se explica brevemente la teoría en la que se basa un modelo de decisión simple, utilizando como ejemplo el clasificador Árboles de decisión:

1. Estructura:

- Un modelo de decisión simple toma una decisión binaria basada en una única característica y un umbral.

- Divide los datos en dos grupos: los que tienen valores de características por debajo del umbral y los que tienen valores por encima.

- Esto se despliega comúnmente en el constructor de la mayoría de nuestros clasificadores en esta Biblioteca:

 CDecisionTreeClassifier(uint min_samples_split=2, uint max_depth=2, mode mode_=MODE_GINI);
~CDecisionTreeClassifier(void);

2. Entrenamiento:

- Durante el entrenamiento, el modelo de decisión simple identifica la característica y el umbral que minimizan un determinado criterio, a menudo el error de clasificación errónea ponderado.

- Se calcula el error de clasificación para cada división posible y se elige la que tenga el error más bajo.

- La(s) función(es) de ajuste es donde se realiza todo el entrenamiento:

void fit(matrix &x, vector &y);

3. Predicción:

- Para la predicción, un punto de datos se clasifica en función de si su valor de característica está por encima o por debajo del umbral elegido.

double predict(vector &x);
vector predict(matrix &x);

Los aprendices débiles comúnmente utilizados en métodos de conjunto como AdaBoost incluyen:


1.Modelo de decisión simple/Árboles de decisión:

- Como se ha descrito anteriormente, los árboles de decisión poco profundos se utilizan habitualmente debido a su simplicidad.

2. Modelos lineales:

- Los modelos lineales como la regresión logística o las SVM lineales pueden utilizarse como aprendices débiles.

3. Modelos polinómicos:

- Los modelos polinómicos de mayor grado pueden captar relaciones más complejas, y el uso de polinomios de bajo grado puede actuar como aprendices débiles.

4. Redes neuronales (poco profundas):

- A veces se utilizan redes neuronales poco profundas con un número reducido de capas y neuronas.

5. Modelos gaussianos:

- Los modelos gaussianos, como Gaussian Naive Bayes (GNB), que es un clasificador probabilístico basado en el teorema de Bayes y que asume que las características siguen una distribución normal (gaussiana), pueden ser empleados como aprendices débiles.

La elección de un aprendiz débil depende de las características específicas de los datos y del problema en cuestión. En la práctica, los modelos de decisión simple son populares por su sencillez y eficacia en los algoritmos de refuerzo. El enfoque de conjunto de AdaBoost mejora el rendimiento combinando las predicciones de estos aprendices débiles.

Dado que un modelo de decisión simple es un modelo, necesitamos proporcionar al constructor de la clase Adaboost los argumentos de los parámetros de nuestro modelo débil.

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);
  };

En este ejemplo se utiliza el Árbol de decisión, pero puede utilizarse cualquier modelo de aprendizaje automático de clasificación.


Construcción de la clase AdaBoost:

El término número de estimadores (n_estimators) se refiere al número de aprendices débiles (modelos base o de decisión simple) que se combinan para crear el aprendiz fuerte final en un algoritmo de aprendizaje ensemble. En el contexto de algoritmos como AdaBoost o 'Gradient boosting', este parámetro suele denominarse 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
 }

Desde la sección protegida de la clase, has visto el vector m_alphas, y también has escuchado el término weights varias veces en este artículo. A continuación, se ofrece una aclaración:


Valores alfa:

Los valores alfa representan la contribución o el peso asignado a cada aprendiz débil en el conjunto, estos valores se calculan en función del rendimiento de cada aprendiz débil durante el entrenamiento.

Los valores alfa más altos se asignan a los alumnos débiles que consiguen reducir los errores de formación.

La fórmula para calcular alfa suele venir dada por:

AdaBoost fórmula alfa

Donde:

 es el error ponderado del t-ésimo aprendiz débil.

Implementación:

double alpha = 0.5 * log((1-error) / (error + 1e-10));


Pesos:

Los vectores de pesos representan la importancia de cada instancia de entrenamiento en cada iteración.

Durante el entrenamiento, los pesos de las instancias mal clasificadas se incrementan para centrarse en los ejemplos difíciles de clasificar en la siguiente iteración.

La fórmula para actualizar los pesos de las instancias suele venir dada por:

Pesos AdaBoost

 es el peso de la instancia i en la iteración 

 ​es el peso asignado al t-ésimo aprendiz débil.

 ​es la verdadera etiqueta de la instancia 

 es la predicción del t-ésimo aprendiz débil sobre la instancia 

 es un factor de normalización para garantizar que los pesos suman 1.

Implementación:

 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();


Entrenamiento del modelo AdaBoost:

Al igual que otras técnicas de ensamble, se utilizan 'n' numero de modelos (referidos como m_estimators en la función a continuación) para hacer predicciones sobre los mismos datos. Se puede emplear la votación por mayoría u otras técnicas para determinar el mejor resultado posible.

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;
    }
 }

Al igual que cualquier otra técnica de ensamble, Bootstrapping es algo crucial también, sin él todos los modelos y los datos son simplemente iguales, y esto podría causar que el rendimiento de todos los modelos se vuelva indistinguible entre sí, es necesario desplegar el Bootstrapping:

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;
    }
 }
También hubo que cambiar el constructor de la clase:
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
 }

Obtener las predicciones mayoritarias

Utilizando las ponderaciones entrenadas, el clasificador AdaBoost determina la clase con el máximo de votos, lo que significa que es más probable que aparezca que las demás.

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
 }

Ahora vamos a ver cómo podemos utilizar el modelo dentro de un Asesor Experto:

#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);
  }

Utilizando el conjunto de datos iris.csv sólo para la construcción del modelo y fines de depuración. Esto dio lugar a:

2024.01.17 17:52:27.914 AdaBoost Test (EURUSD,H1)       Adaboost acc = 0.960

Parece que nuestro modelo está funcionando bien hasta ahora, con valores de precisión alrededor del 90 por ciento. Después configuré el random_state en -1, lo cual hará que GetTickCount se use como semilla aleatoria cada vez que se ejecute el EA, para que pueda evaluar el modelo en un entorno mucho más aleatorio.

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

Los mismos patrones de codificación y estructura pueden seguirse para otros aprendices débiles presentes en nuestra biblioteca, Véase cuando se utilizó la regresión logística como aprendiz débil:

La única diferencia en toda la clase se encuentra bajo la función fit el tipo de modelo desplegado como aprendiz débil es Regresión 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 con AdaBoost en el probador de estrategias.

Utilizando el indicador de las bandas de Bollinger aplicado al precio de apertura, estamos intentando entrenar a nuestros modelos para que aprendan a predecir la siguiente vela de cierre si es bullish, bearish o ninguna de las dos(HOLD).

Vamos a construir un Asesor Experto para probar nuestros modelos en el entorno de negociación, comenzando con el código para recoger los datos de entrenamiento:

Recopilación de los datos de entrenamiento:

//--- 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);
    }

¿Notas el cambio en la elaboración de la variable objetivo? Dado que el árbol de decisión es versátil y puede manejar bien múltiples clases en la variable objetivo, tiene la capacidad de clasificar tres patrones en el mercado, BUY, SELL, y HOLD. A diferencia del modelo de regresión logística que tiene la función sigmoidea en su núcleo que clasifica bien dos clases 0 y 1, lo mejor es preparar la condición de la variable objetivo para que sea BUY o SELL.

Entrenamiento y prueba del modelo entrenado:

Un elefante en la habitación: 

MatrixExtend::TrainTestSplitMatrices(dataset,train_x,train_y,test_x,test_y,0.7,_random_state); 

Esta función divide los datos en muestras de entrenamiento y de prueba dado un estado aleatorio para barajar, el 70% de los datos para la muestra de prueba mientras que el 30% restante para la prueba.

Pero antes de poder utilizar los datos recién recogidos, la normalización sigue siendo crucial para el rendimiento del 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;
     }

Salidas:

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

Hasta ahora, todo bien. Terminemos nuestro Asesor Experto con las líneas de código capaces de ejecutar operaciones:

Obtención de las señales de trading:

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;
     }
  }

Recuerde, 1 representa la señal de compra para el árbol de decisión, 0 representa la señal de compra para la regresión logística; 2 representa la señal de venta para el árbol de decisión; 1 representa la señal de venta para la regresión logística. No nos importa la señal 0 que representa mantener para el árbol de decisión. Unifiquemos estas señales para que se identifiquen como 0 y 1 para señales de compra y venta 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;

Una estrategia sencilla a partir de nuestros 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 en el probador de estrategias | de enero 2020 - febrero 2023 | Timeframe 1 HORA:

Árbol de decisión AdaBoost:

Árbol de decisión AdaBoost

Regresión logística AdaBoost:

Regresión logística AdaBoost - Timeframe H1

Ambas actuaciones con UN TIMEFRAME DE UNA HORA están muy lejos de ser buenas. Una razón importante para esto es que nuestra estrategia se basa en las barras actuales, En mi experiencia, este tipo de estrategias se adaptan sobre todo bien en marcos de tiempo más altos como una sola barra representa un movimiento significativo a diferencia de las pequeñas barras que se producen 24 en un día, vamos a intentar un TIMEFRAME DE 12 HORAS.

Todos los parámetros se dejaron igual excepto el train_bars que se redujo a 100 desde 1000, ya que los marcos de tiempo más altos no tienen muchas barras para solicitar el historial de precios en el pasado.

Árbol de decisión AdaBoost:

Árbol de decisión AdaBoost

Regresión logística AdaBoost:

Regresión logística AdaBoost - Timeframe H12


En conclusión:

AdaBoost emerge como un potente algoritmo capaz de mejorar significativamente el rendimiento de los modelos de IA analizados a lo largo de esta serie de artículos. Aunque conlleva un coste computacional, la inversión merece la pena si se aplica con sensatez. AdaBoost ha encontrado aplicaciones en diversos sectores e industrias, como las finanzas, el entretenimiento y la educación, entre otros.

Para concluir nuestra exploración, es esencial reconocer la versatilidad del algoritmo y su capacidad para abordar retos de clasificación complejos aprovechando la fuerza colectiva de los aprendices débiles. Las preguntas más frecuentes (FAQs) que se ofrecen a continuación pretenden ofrecer claridad y comprensión, abordando las dudas más comunes que puedan surgir durante la exploración de AdaBoost.


Preguntas frecuentes (FAQs) sobre AdaBoost:


Pregunta: ¿Cómo funciona AdaBoost?

Respuesta: AdaBoost funciona entrenando iterativamente aprendices débiles (normalmente modelos simples de decisión) en el conjunto de datos, ajustando los pesos de las instancias mal clasificadas en cada iteración. El modelo final es una suma ponderada de los aprendices débiles, dando mayor peso a los más precisos.


Pregunta: ¿Qué son los aprendices débiles en AdaBoost?

Respuesta: Los aprendices débiles son modelos simples que funcionan ligeramente mejor que el azar. Los modelos simples de decisión (árboles de decisión poco profundos) se suelen utilizar como aprendices débiles en AdaBoost, pero otros algoritmos también pueden servir para este propósito.


Pregunta: ¿Cuál es el papel de los pesos de instancia en AdaBoost?

Respuesta: Los pesos de instancia en AdaBoost controlan la importancia de cada instancia de entrenamiento durante el proceso de aprendizaje. Inicialmente, todas las ponderaciones se fijan por igual, y se ajustan en cada iteración para centrarse más en los casos mal clasificados, mejorando la capacidad de generalización del modelo.


Pregunta: ¿Cómo gestiona AdaBoost los errores cometidos por los aprendices débiles?

Respuesta: AdaBoost asigna pesos más altos a las instancias mal clasificadas, forzando a los aprendices débiles posteriores a centrarse más en corregir estos errores. El modelo final da más peso a los aprendices débiles con índices de error más bajos.


Pregunta: ¿Es AdaBoost sensible al ruido y a los valores atípicos?

Respuesta: AdaBoost puede ser sensible al ruido y a los valores atípicos, ya que intenta corregir las clasificaciones erróneas. Los valores atípicos podrían recibir ponderaciones más altas, influyendo en el modelo final. Para mitigar esta sensibilidad pueden aplicarse aprendices débiles robustos o técnicas de preprocesamiento de datos.


Pregunta: ¿Sufre AdaBoost de sobreajuste?

Respuesta: AdaBoost puede ser propenso al sobreajuste si los aprendices débiles son demasiado complejos o si el conjunto de datos contiene ruido. Utilizar aprendices débiles más sencillos y aplicar técnicas como la validación cruzada puede ayudar a evitar el sobreajuste.


Pregunta: ¿Se puede utilizar AdaBoost para problemas de regresión?

Respuesta: AdaBoost está diseñado principalmente para tareas de clasificación, pero puede adaptarse para regresión modificando el algoritmo para predecir valores continuos. Existen técnicas como AdaBoost.R2 para los problemas de regresión.


Pregunta: ¿Existen alternativas a AdaBoost?

Respuesta: Sí, existen otros métodos de aprendizaje en conjunto, como Random Forest, Gradient Boosting y XGBoost. Cada método tiene sus puntos fuertes y débiles, y la elección depende de las características específicas de los datos y del problema en cuestión.


Pregunta: ¿En qué situaciones es AdaBoost especialmente eficaz?

Respuesta: AdaBoost es eficaz cuando se trata con una variedad de aprendices débiles y en escenarios donde hay una necesidad de combinar múltiples clasificadores para crear un modelo robusto. Se utiliza a menudo en la detección de rostros, la clasificación de textos y otras aplicaciones del mundo real.


Para mantenerse al día sobre el progreso del desarrollo y las correcciones de errores de este algoritmo, así como de muchos otros, visite el repositorio de GitHub en https://github.com/MegaJoctan/MALE5.


Paz.

Archivos adjuntos:

Archivo Descripción / Uso
Adaboost.mqh Contiene clases del espacio de nombres AdaBoost tanto para la regresión logística como para el árbol de decisión.
Logistic Regression.mqh Contiene la clase principal de regresión logística.
MatrixExtend.mqh Contiene una función adicional de manipulación de matrices.
metrics.mqh Una biblioteca que contiene código para medir el rendimiento de los modelos de aprendizaje automático.
preprocessing.mqh Clase que contiene funciones de preprocesamiento de datos para adaptarlos al aprendizaje automático.
tree.mqh La biblioteca del árbol de decisiones se encuentra en este archivo.
AdaBoost Test.mq5 (EA) El Asesor Experto de prueba principal, todo el código explicado aquí se ejecuta dentro de este archivo.

Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/14034

Archivos adjuntos |
Utilizando redes neuronales en MetaTrader Utilizando redes neuronales en MetaTrader
En el artículo se muestra la aplicación de las redes neuronales en los programas de MQL, usando la biblioteca de libre difusión FANN. Usando como ejemplo una estrategia que utiliza el indicador MACD se ha construido un experto que usa el filtrado con red neuronal de las operaciones. Dicho filtrado ha mejorado las características del sistema comercial.
Desarrollo de un sistema de repetición (Parte 55): Módulo de control Desarrollo de un sistema de repetición (Parte 55): Módulo de control
En este artículo, implementaremos el indicador de control de manera que pueda integrarse en el sistema de mensajes que está en desarrollo. Aunque no es algo muy complejo de hacer, es necesario entender algunos detalles sobre cómo inicializar este módulo. El contenido expuesto aquí tiene como objetivo, pura y simplemente, la didáctica. En ningún caso debe considerarse como una aplicación cuya finalidad no sea el aprendizaje y el estudio de los conceptos mostrados.
Particularidades del trabajo con números del tipo double en MQL4 Particularidades del trabajo con números del tipo double en MQL4
En estos apuntes hemos reunido consejos para resolver los errores más frecuentes al trabajar con números del tipo double en los programas en MQL4.
Desarrollo de un sistema de repetición (Parte 54): El nacimiento del primer módulo Desarrollo de un sistema de repetición (Parte 54): El nacimiento del primer módulo
En este artículo, veremos cómo construir el primero de los módulos, realmente funcional, para ser utilizado en el sistema de repetición/simulador. Además de tener como propósito general servir para otras cosas también. El módulo que se construirá aquí será el del indicador de mouse.