English Deutsch 日本語
preview
Машинное обучение и Data Science (Часть 19): Совершенствуем AI-модели с помощью AdaBoost

Машинное обучение и Data Science (Часть 19): Совершенствуем AI-модели с помощью AdaBoost

MetaTrader 5Трейдинг | 10 июня 2024, 13:26
527 0
Omega J Msigwa
Omega J Msigwa

Что такое AdaBoost?

AdaBoost (сокращение от Adaptive Boosting - адаптивный бустинг) представляет собой модель ансамблевого машинного обучения, которая пытается создать сильный классификатор из слабых классификаторов.


Как он работает?

  • Алгоритм присваивает веса экземплярам на основе их правильной или неправильной классификации.
  • Он объединяет слабые экземпляры с помощью взвешенной суммы.
  • Последняя сильная модель представляет собой линейную комбинацию слабых, веса которых определяются в процессе обучения.

Adaboost в mql5


Для чего использовать методику Adaboost?

Adaboost предоставляет ряд преимуществ, в том числе:

  • Улучшение точности — бустинг может повысить общую точность модели за счет объединения нескольких слабых прогнозов модели, усреднения прогнозов, сделанных всеми моделями регрессии, или голосования по ним для классификации. Все это повышает точность итоговой модели. 
  • Устойчивость к переобучению — бустинг может снизить риск переобучения за счет присвоения весов неправильно классифицированным входным данным.
  • Улучшенная обработка несбалансированных данных — бустинг позволяет справиться с несбалансированными данными, уделяя больше внимания точкам данных, которые неправильно классифицированы.
  • Лучшая интерпретируемость — бустинг может повысить интерпретируемость модели за счет разбиения процесса принятия решения модели на несколько процессов. 


Что такое "пень решений"?

"Пень решений" (Decision Stump) — это простая модель машинного обучения, используемая в качестве слабого ученика в ансамблевых методах, таких как Adaboost. По сути, это модель машинного обучения, упрощенная для принятия решений на основе одной функции и порогового значения. Цель использования такого пня в качестве слабого ученика — уловить базовую закономерность в данных, которая может способствовать улучшению общей модели ансамбля.

Ниже приводится краткое объяснение теории, лежащей в основе пня решений, с использованием классификатора Древа решений в качестве примера:

1. Структура:

- Пень решений принимает двоичное решение на основе одного признака и порогового значения.

- Данные разбиваются на две группы: со значениями признаков ниже порогового значения и со значениями выше.

- Что используется в конструкторе большинства наших классификаторов в этой Библиотеке:

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

2. Обучение:

- Во время обучения пень решений определяет функцию и порог, который минимизирует определенный критерий, обычно это взвешенная ошибка классификации.

- Ошибка классификации рассчитывается для каждого возможного разделения и выбирается тот, у которого ошибка наименьшая.

- Все обучение происходит в функции fit:

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

3. Прогноз:

- Для определения прогноза точка данных классифицируется на основе того, находится ли ее значение признака выше или ниже выбранного порога.

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

Что обычно используется в качестве слабых ученики в ансамблевых методах, в том числе в AdaBoost:

1.Пни решений/дерева решений:

- Как описано выше, пни решений или неглубокие деревья решений обычно выбираются из-за их простоты.

2. Линейные модели:

- Линейные модели, такие как логистическая регрессия или линейные SVM, можно использовать в качестве слабых учеников.

3. Полиномиальные модели:

- Полиномиальные модели более высокой степени могут отражать более сложные взаимосвязи, а использование полиномов низкой степени может оказаться слабым учеником.

4. Нейронные сети (мелкие):

— Иногда используются мелкие нейронные сети с небольшим количеством слоев и нейронов.

5. Гауссовские модели:

- Гауссовские модели, такие как гауссовская наивная байесовская модель, тоже можно использовать в качестве слабых учеников.

Выбор слабого ученика зависит от конкретных характеристик данных и решаемой проблемы. На практике часто используются пни решений — они просты и достаточно эффективны в алгоритмах бустинга. Ансамблевый подход AdaBoost повышает производительность за счет объединения прогнозов слабых учеников.

Поскольку пень решения — это модель, нам нужно передать конструктору класса Adaboost аргументы параметров нашей слабой модели.

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

В этом примере используется дерево решений, но можно развернуть любую классификационную модель машинного обучения.


Создадим класс AdaBoost:

Термин количество оценщиков относится к количеству слабых учеников (базовых моделей или пней решений), которые объединяются для создания итогового сильного ученика в алгоритме ансамблевого обучения. В контексте таких алгоритмов, как AdaBoost или градиент-бустинг, этот параметр часто обозначается как 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
 }

В защищенном разделе класса находится вектор m_alphas. Также мы в этой статье будем говорить о весовых коэффициентах. Ниже приведены пояснения этих моментов:


Альфа-значения:

Значения альфа представляют собой вклад или весовой коэффициент, присвоенный каждому слабому ученику в ансамбле. Эти значения рассчитываются на основе результатов каждого слабого ученика во время обучения.

Более высокие значения альфа присваиваются слабым ученикам, которые хорошо справляются с уменьшением ошибок обучения.

Альфа обычно рассчитывается по такой формуле:

Альфа-формула adaboost

Где:

 – это взвешенная ошибка t-го слабого ученика.

Реализация:

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


Весовые коэффициенты:

Векторы весовых коэффициентов отражают важность каждого экземпляра обучения на каждой итерации.

Во время обучения веса неправильно классифицированных экземпляров увеличиваются, чтобы сосредоточиться на примерах, которые трудно классифицировать на следующей итерации.

Формула обновления весовых коэффициентов:

Весовые коэффициенты в adaboost

 — весовой коэффициент экземпляра i на итерации 

 — весовой коэффициент, присвоенный t-ному слабому ученику.

 — истинная метка экземпляра 

 — предсказание t-го слабого ученика в экземпляре 

 — коэффициент нормализации, гарантирующий, что сумма весов равна 1.

Реализация:

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


Обучение модели Adaboost

Как и в случае с другими ансамблевыми методами, n моделей (m_estimators в функции ниже) используются для прогнозирования на основе одних и тех же данных. Для определения наилучшего возможного результата можно использовать большинство голосов или другие методы.

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

Как и в любой другой ансамблевой технике, здесь важную роль играет бутстрэппинг. Без нее все модели и данные будут просто одинаковыми, и это может привести к тому, что производительность всех моделей станет неотличимой друг от друга. Поэтому проводим бутстрэп:

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); //fiting 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;
    }
 }
Конструктор класса также пришлось изменить:
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
 }

Получение прогнозов большинства

Используя обученные веса, классификатор Adaboost определяет класс, набравший максимальное количество голосов. То есть вероятность появления этого класса выше, чем других.

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
 }

Теперь давайте посмотрим, как эту модель можно использовать в советнике:

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

Для построения модели используем набор данных из файла iris.csv. Получаем такие результаты:

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

Пока кажется, что модель работает хорошо — ее точность составляет около 90 процентов. Теперь установим random_state в значение -1. Тогда при каждом запуске советника в качестве случайного начального числа будет использоваться GetTickCount. Это позволит оценить модель в гораздо более случайной среде.

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

Те же шаблоны и структуру можно использовать и для других слабых учащихся, присутствующих в нашей библиотеке. В другом примере в качестве слабого ученика использовалась логистическая регрессия.

Единственное отличие в классе — функция fit: тип модели, используемой в качестве слабого ученика теперь Логистическая регрессия:

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


Adaboosted AI-модели в тестере стратегий.

Мы используем индикатор Bollinger Bands к ценам открытия и попытаемся научить наши модели прогнозировать следующую свечу закрытия, независимо от того, будет ли это бычья, медвежья свеча или ни та, ни другая (удерживаем HOLD).

Создадим советник для тестирования наших моделей в торговой среде. Начнем со сбора обучающих данных:

Сбор данных для обучения:

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

Обратили внимание на изменение в создании целевой переменной? Поскольку дерево решений является универсальным и может хорошо обрабатывать множество классов целевой переменной, оно позволяет классифицировать три модели рынка: BUY, SELL и HOLD. В основе модели логистической регрессии лежит сигмовидная функция, хорошо классифицирующая два класса 0 и 1. Для нас лучше сделать так, чтобы условием целевой переменной было либо BUY, либо SELL.

Обучение и тестирование обученной модели

Слон в комнате: 

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

Эта функция разделяет данные на обучающую и тестовую выборки с учетом случайного состояния для перемешивания: 70% данных для тестовой выборки, а остальные 30% для тестирования.

Но прежде, чем мы сможем использовать вновь собранные данные, все же нужно провести нормализацию, которая имеет решающее значение для производительности модели..

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

Результат

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

Пока все идет хорошо. Дополним наш советник кодом для совершения сделок:

Получение торговых сигналов:

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

Напомню, 1 используется для сигнала на покупку в дереве решений, 0 это сигнал на покупку в логистической регрессии; 2 служит сигналом на продажу в дереве решений; 1 — это сигнал на продажу в логистической регрессии. Нас не интересует сигнал 0, обозначающий удержание в древе решений. Объединим сигналы, чтобы они обозначались как 0 и 1 для сигналов покупки и продажи соответственно.

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;

Простая стратегия, созданная на основе наших моделей:

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

Результаты в тестере стратегий с января 2020 г. по февраль 2023 г. на часовом таймфрейме:

Дерево решений Adaboost:

Дерево решений Adaboost

Логистическая регрессия Adaboost:

Логистическая регрессия Adaboost на таймфрейме H1

Результаты обеих моделей на часовом таймфрейме очень далеки от приемлемых. Основная причина заключается в том, что наша стратегия основана на текущих барах. По моему опыту, стратегии такого типа в основном хорошо подходят для старших таймфреймов, поскольку один бар представляет собой значительное движение в отличие от маленьких баров, которые происходят 24 в день. Попробуем 12-часовой таймфрейм.

Все параметры остались прежними, кроме train_bars, значение которого теперь 100 вместо 1000, поскольку на старших таймфреймах не так много баров для запроса истории цен.

Дерево решений Adaboost:

Дерево решений Adaboost

Логистическая регрессия Adaboost:

Логистическая регрессия Adaboost на таймфрейме H12


Заключение

AdaBoost представляет собой мощный алгоритм, способный значительно повысить производительность ИИ-моделей, обсуждаемых в этой серии статей. Хотя он требует вычислительных затрат, инвестиции окупаются при разумной реализации. Метод AdaBoost нашел применение в различных секторах и отраслях, включая финансы, развлечения, образование и многое другое.

В завершении нашего исследования можно отметить универсальность алгоритма и его способность решать сложные задачи классификации, используя коллективную силу слабых учеников. Ниже представлены часто задаваемые вопросы (FAQ) приз, в них покрыты общие вопросы, которые могут возникнуть во время изучения AdaBoost.


FAQ, или часто задаваемые вопросы об AdaBoost:


Вопрос: Как работает алгоритм AdaBoost?

Ответ: AdaBoost работает путем итеративного обучения слабых учеников (обычно простых моделей, таких как пни решений) на выборке, корректируя веса неправильно классифицированных экземпляров на каждой итерации. Окончательная модель представляет собой взвешенную сумму слабых учеников, при этом более высокие веса присваиваются более точным.


Вопрос: Что такое слабые ученики в AdaBoost?

Ответ: Слабые ученики — это простые модели, которые работают немного лучше, чем случайные. Пни решений (неглубокие деревья решений) обычно используются в качестве слабых учеников в AdaBoost, но этой цели могут служить и другие алгоритмы.


Вопрос: Какова роль весов экземпляров в AdaBoost?

Ответь: Веса экземпляров в AdaBoost контролируют важность каждого обучающего экземпляра в процессе обучения. Первоначально всем весам устанавливаются одинаковые значение, затем они корректируются на каждой итерации, чтобы больше внимания удалить неправильно классифицированным экземплярам, улучшая способность модели к обобщению.


Вопрос: Как AdaBoost обрабатывает ошибки, допущенные слабыми учениками?

Ответ: AdaBoost присваивает более высокие веса неправильно классифицированным экземплярам, заставляя последующих слабых учеников больше концентрироваться на исправлении этих ошибок. Окончательная модель придает больший вес слабым ученикам с более низким уровнем ошибок.


Вопрос: Чувствителен ли AdaBoost к шуму и выбросам?

Ответ: AdaBoost может быть чувствителен к шуму и выбросам, поскольку пытается исправить ошибки классификации. Выбросам могут быть присвоены более высокие веса, что повлияет на окончательную модель. Для снижения этой чувствительности можно применять надежные слабые обучающиеся или методы предварительной обработки данных.


Вопрос: Страдает ли AdaBoost от переобучения?

Ответ: AdaBoost может быть склонен к переобучению, если слабые ученики слишком сложны или если набор данных содержит шум. Использование более простых слабых учеников и применение таких методов, как перекрестная проверка, может помочь предотвратить переобучение.


Вопрос: Можно ли использовать AdaBoost для решения проблем регрессии?

Ответ: AdaBoost в первую очередь предназначен для задач классификации, но его можно адаптировать для регрессии, изменив алгоритм для прогнозирования непрерывных значений. Для решения проблем регрессии существуют такие методы, как AdaBoost.R2.


Вопрос: Есть ли альтернативы AdaBoost?

Ответ: Да, существуют и другие методы ансамблевого обучения, например Случайный лес, Градиентный бустинг и XGBoost. Каждый метод имеет свои преимущества и недостатки, и выбор зависит от конкретных характеристик данных и решаемой проблемы.


Вопрос: В каких ситуациях AdaBoost особенно эффективен?

Ответ: AdaBoost эффективен при работе с различными слабыми учениками и в сценариях, когда необходимо объединить несколько классификаторов для создания надежной модели. Он часто используется для распознавания лиц, классификации текста и других реальных приложений.


Следите за ходом разработки и исправлением ошибок для этого и многих других алгоритмов в GitHub-репозитории по адресу https://github.com/MegaJoctan/MALE5.


Содержимое вложения:

Файл Описание/назначение
Adaboost.mqh Содержит классы пространства имен adaboost как для логистической регрессии, так и для дерева решений.
Logistic Regression .mqh Содержит основной класс логистической регрессии.
MatrixExtend.mqh Содержит дополнительную функцию манипулирования матрицей.
metrics.mqh Библиотека, содержащая код для измерения производительности моделей машинного обучения.
preprocessing.mqh Класс, содержащий функции для предварительной обработки данных и подготовки их для машинного обучения
tree.mqh Библиотеку деревьев решений можно найти в этом файле
AdaBoost Test.mq5(EA) Основной тестовый советник, весь описанный здесь код, выполняется внутри этого файла.

Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/14034

Прикрепленные файлы |
Как просматривать сделки прямо на графике и не утонуть в торговой истории Как просматривать сделки прямо на графике и не утонуть в торговой истории
В статье создадим простой инструмент для удобного просмотра позиций и сделок прямо на графике с навигацией клавишами. Это позволит трейдерам визуально изучать отдельные сделки и получать всю информацию о результатах торговли прямо по месту.
Элементы корреляционного анализа в MQL5: Критерий независимости хи-квадрат Пирсона и корреляционное отношение Элементы корреляционного анализа в MQL5: Критерий независимости хи-квадрат Пирсона и корреляционное отношение
В статье рассматриваются классические инструменты корреляционного анализа. Даются краткие теоретические основы, а также практическая реализация критерия независимости хи-квадрат Пирсона и коэффициента корреляционного отношения.
Нейросети — это просто (Часть 94): Оптимизация последовательности исходных данных Нейросети — это просто (Часть 94): Оптимизация последовательности исходных данных
При работе с временными рядами мы всегда используем исходные данные в их исторической последовательности. Но является ли это оптимальным вариантом? Существует мнение, что изменение последовательности исходных данных позволит повысить эффективность обучаемых моделей. В данной статье я предлагаю вам познакомиться с одним из таких методов.
Наиболее известные модификации алгоритма искусственного кооперативного поиска (Artificial Cooperative Search, ACSm) Наиболее известные модификации алгоритма искусственного кооперативного поиска (Artificial Cooperative Search, ACSm)
В данной статье рассмотрим эволюцию алгоритма ACS: три модификации в направлении улучшения характеристик сходимости и результативности алгоритма. Трансформация одного из ведущих алгоритмов оптимизации. От модификаций матриц до революционных подходов к формированию популяций.