English Español Deutsch 日本語 Português
preview
Алгоритм выбора признаков с использованием энергетического обучения на чистом MQL5

Алгоритм выбора признаков с использованием энергетического обучения на чистом MQL5

MetaTrader 5Примеры | 19 сентября 2024, 11:06
338 0
Francis Dube
Francis Dube

Введение

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

Юн Ли, Дженни Си, Гоцзин Чжоу, Шаша Хуан и Сонгкан Чен стали соавторами исследовательской работы под названием "FREL: Стабильный алгоритм выбора признаков" (FREL: A Stable Feature Selection Algorithm). В работе представлен алгоритм под названием "Взвешивание признаков как регуляризованное обучение на основе энергии" (Feature Weighting as Regularized Energy-Based Learning, FREL), который служит в качестве метода отбора признаков или взвешивания, призванного обеспечить как точность, так и стабильность. Мы дадим обзор теоретических основ регуляризованного обучения на основе энергии и взвешивания признаков. Кроме того, мы проиллюстрируем эффективность предлагаемого подхода, реализовав пример MQL5-программы, созданной в виде скрипта, чтобы подчеркнуть потенциал метода как инструмента для выбора признаков.


Взвешенная классификация метода ближайших соседей

Концепция FREL черпает вдохновение из метода, известного как взвешенная классификация ближайших соседей (weighted nearest-neighbour classification), который использует расстояния между точками в наборе данных для составления прогнозов. Определяя соответствующие веса для каждого признака, метод повышает точность прогнозирования. Взвешенная классификация ближайших соседей представляет собой разновидность алгоритма k ближайшего соседа (k-NN) - широко используемого подхода в машинном обучении для задач классификации. В стандартной классификации k-NN алгоритм проверяет k ближайших точек данных в обучающем наборе при классификации новой точки данных, в конечном итоге присваивая новой точке данных класс большинства среди этих соседей.

Однако при взвешенной классификации ближайших соседей вместо простого подсчета голосов ближайших соседей голос каждого соседа взвешивается в соответствии с его расстоянием от новой точки данных. Обоснование заключается в том, что более близкие соседи должны оказывать более сильное влияние на решение о классификации, чем более далекие. Процесс взвешивания включает в себя расчет расстояния между новой точкой данных и каждой точкой в обучающем наборе. Обычно используемые метрики расстояния включают евклидово расстояние, манхэттенское расстояние или косинусный коэффициент, выбранные на основе характеристик данных. В этом контексте мы используем манхэттенское расстояние, также называемое расстоянием между городскими кварталами, между точками данных. Формула расчета расстояния приведена ниже. Здесь w - это веса, а testcase - это тестовый случай, который оценивается относительно других обучающих данных, заданных как обучающий случай (trainingcase)

Формула взвешенного расстояния ближайших соседей


Энергетические модели

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

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

Цель обучения энергетической модели — изучить параметры энергетической функции таким образом, чтобы она присваивала низкие значения энергии релевантным входным переменным, а высокие значения — нерелевантным. Это влечет за собой определение целевой функции, которая штрафует высокие значения энергии при правильных переменных и низкие значения - при неправильных. Для достижения этой цели необходимо определить конфигурацию неверных переменных, которая обеспечивает наименьшую энергию, представляя собой выборку, которая с большой вероятностью может привести к ошибочным прогнозам модели. Функция ниже представляет энергию конфигурации входных параметров, x, и параметра модели, w, который выводит ошибочное значение, y, чтобы отличить их от конфигураций входных переменных, которые дают точные прогнозы. 

Формула энергии для неправильной конфигурации с самой низкой энергией

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

Формула энергии для ближайшей правильной конфигурации переменных

Целевая функция, известная как функционал потерь (loss functional), представляет собой усредненную по выборке функцию потерь. Ниже приведен логарифм потерь.

Функция средних потерь на выборку (логарифм потерь)

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

Это основные концепции, лежащие в основе FREL. В следующем разделе подробно рассматриваются особенности самого алгоритма.


Алгоритм FREL

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

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

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

Основные этапы алгоритма FREL следующие:

Матрица обучающих данных

  1. Начнем с обучающего набора данных, включающего n наблюдений с d потенциальными предикторами, соответствующими n целевым значениям. Цель состоит в том, чтобы выявить наиболее релевантные предикторы из набора d кандидатов для определения целевых значений. Это приводит к присвоению весов каждому из d-предикторов, что указывает на важность переменной по отношению к другим. Больший вес означает большую значимость при определении целевого значения. 
  2. Первоначально присвоим всем весам значение 1.
  3.  Применим классификацию взвешенных ближайших соседей к каждому наблюдению в обучающих данных, чтобы определить конфигурацию неверных переменных, дающую самую низкую энергию, и ближайшую конфигурацию правильных переменных с высокой энергией. Применим эти значения энергии для расчета потерь на образец с использованием выбранной функции потерь.
  4.  Наконец, минимизируйте функцию потерь (опционально с помощью регуляризации), используя необходимую процедуру оптимизации. Это основа алгоритма FREL.
В своей исследовательской работе авторы также демонстрируют усовершенствование основного алгоритма путем применения бутстреппинга. Выборка должна проводиться без замены, а полученные весовые коэффициенты представляют собой усредненные значения из каждой выборки бутстрепа.


Реализация FREL на MQL5

Реализация FREL, представленная в этом тексте, использует метод оптимизации Пауэлла. Хотя конкретный используемый метод оптимизации не имеет решающего значения, результаты должны быть относительно единообразными при использовании разных методов. В этой реализации метод Пауэлла представлен как класс PowellsMethod, определенный в Powells.mqh. Алгоритм FREL инкапсулирован в классе FREL, потомке PowellsMethod, указанном в frel.mqh.

   //+------------------------------------------------------------------+
   //| constructor                                                      |
   //+------------------------------------------------------------------+

                     FREL(matrix &in_data,int numboot=1, int bootsize=0)
     {
      m_data = in_data;
      m_num_boot=(numboot>0)?numboot:1;
      m_bootsize=(bootsize>2 && bootsize<=int(m_data.Rows()) && m_num_boot>1)?bootsize:int(m_data.Rows());
      
      
      if(ArrayResize(m_indices, int(m_data.Rows()))!=int(m_data.Rows()) ||
         ArrayResize(m_target_bin, int(m_data.Rows()))!=int(m_data.Rows()) ||
         ArrayResize(m_trial_weights, int(m_data.Cols()-1))!=int(m_data.Cols()-1) ||
         ArrayResize(m_work_weights, int(m_data.Cols()-1))!=int(m_data.Cols()-1)
        )
        {
         Print(__FUNCTION__, " error ", GetLastError());
         m_memory_allocated = false;
        }
      else
         m_memory_allocated = true;
     }

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

 Название параметра
 Тип данных
Значение по умолчанию
 Описание
numboot
целое число
1
numboot устанавливает количество проводимых самозагрузок (bootstraps)
bootsize
целое число
0
bootsize определяет размер каждой самозагрузки. Будьте внимательны при настройке этого параметра. Если используется значение, превышающее количество наблюдений в матрице, numboot автоматически возвращается к 1, а bootsize — к количеству наблюдений.

Для использования класса FREL пользователям необходимо ознакомиться только с одним методом: WeighVars().

   //+-----------------------------------------------------------------------+
   //| Find the most relevant variables from a dataset of candidate variables|
   //+-----------------------------------------------------------------------+

   bool               WeighVars(int num_bins_target, double reg_factor,int &index[],double &weights[])
     {
      
      if(!m_memory_allocated)
        {
         Print(" INTERNAL ERROR ");
         return false;
        }
        
        
      if(num_bins_target<=1 || num_bins_target>int(m_data.Rows()))
       {
        Print(__FUNCTION__, " invalid function parameter: num_bins_target. Parameter should be >=2 ");
        return false;
       }  

      int ret=0;
      double target[], target_thresholds[] ;
      double sum ;

      int n_cases = int(m_data.Rows());
      m_reg_factor = MathAbs(reg_factor);
      m_loss = 0.0;


      if(ArrayResize(index,int(m_data.Cols()-1))!=int(m_data.Cols()-1) ||
         !np::vecAsArray(m_data.Col(m_data.Cols()-1),target)
        )
        {
         Print(__FUNCTION__, " error ", GetLastError());
         return false;
        }

      int k = num_bins_target ;
      if(!bin_array(target, k, target_thresholds, m_target_bin))
         return false;

      if(k<num_bins_target)
        {
         Print("error bins of target vector ", num_bins_target," : ", k);
         return false;
        }

      for(int i=0 ; i<n_cases ; i++)
        {
         if(m_target_bin[i] >= num_bins_target)
           {
            Print("error m_target_bin array at index ", i, " is ",m_target_bin[i], " should be less than ", num_bins_target);
            return false;
           }
        }

      ret = calc_wt(num_bins_target,m_loss,weights);

      if(ret<0)
         return false;

      sum = 0.0 ;
      for(ulong var=0 ; var<m_data.Cols()-1 ; var++)
        {
         weights[var] = m_data.Col(var).Std() * exp(weights[var]);
         sum += weights[var] ;
        }

      for(ulong var=0 ; var<m_data.Cols()-1 ; var++)
        {
         weights[var] *= 100.0 / sum ;
         index[var] = int(var) ;
        }

      MathQuickSortDescending(weights,index,0,int(weights.Size()-1)) ;

      return true;
     }

Этот метод оценивает обучающие данные, указанные в конструкторе. Возвращает логическое значение, где false указывает на то, что процедура не была завершена. Параметры этого метода следующие:

  • num_bins_target - целое число, определяющее количество ячеек, на которые будут разделены целевые значения. Параметр должен быть установлен на любое целое число >= 2, но <= количество наблюдений в обучающих данных.
  • reg_factor - положительное значение double, контролирующее степень регуляризации. Значение 0 отключает регуляризацию.
  • index[] - целочисленный массив, в который будет записана часть результатов операции. Он содержит исходные индексы столбцов, предоставленные конструктору, расположенные в порядке убывания релевантности цели.
  • weights[] - массив double, содержащий оптимальные веса, упорядоченные в порядке убывания.

При вызове WeighVars() целевые значения извлекаются из матрицы и помещаются в массив для подготовки к вызову закрытого метода bin_array(). Этот метод сегментирует массив на приблизительно равные по размеру категории, выводя два массива после успешного завершения. upperbound_thresholds[] — это массив верхних порогов для каждого сегмента, тогда как целочисленный массив categories[] содержит значения индекса, представляющие сегмент, к которому принадлежит каждое соответствующее целевое значение. Каждое из этих значений проверяется, чтобы убедиться, что все целевые значения были правильно распределены.

   //+------------------------------------------------------------------+
   //| calculates the optimal weights of candidate variables            |
   //+------------------------------------------------------------------+

   int               calc_wt(int num_bins_target,double &loss_value, double &w[])
     {
      int ret,rand_error, class_count[] ;

      ret = 0;

      if(ArrayResize(class_count,num_bins_target)!=num_bins_target || (w.Size()!=uint(m_data.Cols()-1) && ArrayResize(w,int(m_data.Cols()-1))!=int(m_data.Cols()-1)))
        {
         Print(__FUNCTION__, " error ", GetLastError());
         return -1;
        }

      ArrayInitialize(w,0.0);
      loss_value = 0.0 ;

      for(ulong i=0 ; i<m_data.Rows() ; i++)
         m_indices[i] = int(i) ;
     
      for(int ibootstrap=0 ; ibootstrap<m_num_boot; ibootstrap++)
        { 
         Comment(" Bootstrap iteration ", ibootstrap+1);
           
         ArrayInitialize(class_count,0);

         int ii, j, k, m;

         ii = int (m_data.Rows()) ;
         while(ii > 1)
           {
            m = int (m_data.Rows()) - ii ;
            if(m >= m_bootsize)
               break ;
            j = (int)(MathRandomUniform(0.0,1.0,rand_error) * ii) ;
            if(j >= ii)
               j = ii - 1 ;
            k = m_indices[m] ;
            m_indices[m] = m_indices[m+j] ;
            m_indices[m+j] = k ;
            --ii ;
            ++class_count[m_target_bin[m_indices[m]]] ;
           }
           

         for(int i=0 ; i<num_bins_target ; i++)
           {
            if(class_count[i] < 2)
               Print(__FUNCTION__, "  class at ", i, " has less than 2 members. Consider adjusting Frel parameters. (number of partitions or bootstrap sample size)");
           }
            
         ArrayInitialize(m_trial_weights,0.0);

         ret += Optimize(m_trial_weights);
         loss_value += PowellsMethod::GetFret() ;

         for(ulong i=0 ; i<m_data.Cols()-1 ; i++)
            w[i] += m_trial_weights[i] ; 

        }

      for(ulong i=0 ; i<m_data.Cols()-1; i++)
        w[i] /= double(m_num_boot) ;

      return ret ;

     }

Оценка веса начинается с вызова calc_wt(). Здесь выполняется бутстреп-выборка, перемешивающая данные перед оптимизацией начальных весов. Оптимизация выполняется методом родительского класса Optimize(). Оптимальные веса для каждого бутстрапа суммируются в w[] для усреднения перед выходом из calc_wt().

   //+------------------------------------------------------------------+
   //| function minimized by Powells optimization method                |
   //+------------------------------------------------------------------+
   virtual double          func(const double& p[])
     {
      double pen = 0.0 ;

      for(ulong i=0 ; i<m_data.Cols()-1 ; i++)
        {
         if(p[i] > 4.0)
           {
            m_work_weights[i] = exp(4.0) + p[i] - 4.0 ;
            pen += (p[i] - 4.0) * (p[i] - 4.0) ;
           }
         else
            if(p[i] < -3.0)
              {
               m_work_weights[i] = exp(-3.0) + p[i] + 3.0 ;
               pen += (p[i] + 3.0) * (p[i] + 3.0) ;
              }
            else
               m_work_weights[i] = exp(p[i]) ;
        }

      return (loss(m_work_weights) + pen) ;
     }

Помните, что минимизируемая функция — это функционал потерь, представленный переопределенным методом родительского класса под названием func().

   //+------------------------------------------------------------------+
   //| calculates the loss function                                     |
   //+------------------------------------------------------------------+
   double            loss(double &w[])
     {
      double totaloss = total_loss(w);

      totaloss/=double(m_data.Rows());

      if(m_reg_factor>0.0)
        {
         for(ulong i=0; i<m_data.Cols()-1;i++)
            totaloss+=m_reg_factor*pow(w[i],2.0);
        }

      return totaloss;
     }

В func() задействован метод loss(), запускающий вычисление функции потерь для каждой выборки, реализованной как закрытый метод total_loss().

   //+------------------------------------------------------------------+
   //|  loss over all data                                              |
   //+------------------------------------------------------------------+

   double            total_loss(double &w[])
     {
      int category,first, other ;
      double  distance, top, bottom, loss ;

      loss = 0.0 ;
      for(int i=0; i<m_bootsize; i++)
        {
         other = m_indices[i] ;
         category = m_target_bin[other] ;
         top = bottom = DBL_MAX ;

         for(int iother=0 ; iother<m_bootsize; iother++)
           {
            first = m_indices[iother] ;
            if(first == other)
               continue ;

            distance = 0.0 ;
            for(ulong v=0 ; v<m_data.Cols()-1; v++)
              {
               distance += w[v] * fabs(m_data[other][v] - m_data[first][v]) ;
              }

            if(m_target_bin[first] == category)
              {
               if(distance < top)
                  top = distance ;
              }
            else
              {
               if(distance < bottom)
                  bottom = distance ;
              }
           }

         distance = top - bottom ;
         if(distance > 30.0)
            loss += distance ;
         else
            loss += log(1.0 + exp(distance));
        }

      return loss ;
     }

После завершения всех бутстрапов усредненные оптимальные веса записываются в предоставленный пользователем массив weights[]. Перед сортировкой по убыванию веса преобразуются таким образом, чтобы их общая сумма составляла 100, что повышает интерпретируемость.


Пример выбора признаков с использованием FREL

Для демонстрации алгоритма FREL мы предоставляем скрипт FrelExample.mq5. Этот скрипт использует FREL для анализа случайно сгенерированного набора данных, включающего в себя кандидаты в переменные и цель для выявления наилучших предикторов. Пользователи могут настраивать все параметры алгоритма FREL и определенные характеристики синтетического набора данных. Сюда входит общее количество наблюдений ( num_observations ) и количество кандидатов-предикторов ( num_candidate_predictors ). Ниже приведен фрагмент, иллюстрирующий настраиваемые пользователем входные данные скрипта:

//---user adjustable input parameters
input int number_of_partitions = 8; //Number of partitions
input double regularization_factor = 0.0; //Regularization factor
input int number_of_bootstraps = 1;
input int bootstrap_size = 0;
input ulong num_observations = 2000;// Sample size of random dataset
input ulong num_candidate_predictors = 10;// Maximum number of candidate predictors in dataset

Скрипт генерирует матрицу случайных чисел с num_observations строк и num_candidate_predictors + 1 столбцов. Последний столбец перезаписывается суммой столбцов с индексами 1, 3, 5 и 7, которая служит целевой переменной набора данных.

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   srand(126);
//---check user input parameters
   if(number_of_partitions<2 || num_observations<10 || num_candidate_predictors<8)
     {
      Print("Invalid input parameters");
      return;
     }
//---the data
   matrix dataset;
//---initialize size of random dataset
   dataset.Init(num_observations,num_candidate_predictors+1);
//---fill dataset with random data
   dataset.Random(1.0,10.0);
//---set the target variable in the last column
   if(!dataset.Col(dataset.Col(1) + dataset.Col(3) + dataset.Col(5) + dataset.Col(7),num_candidate_predictors))
     {
      Print("error ", GetLastError());
      return;
     }
//---initialize Frel object
   FREL frel(dataset,number_of_bootstraps,bootstrap_size);
//---declare containers to recieve output from Frel operation
   double optimal_weights[];
   int index[];
//---
   ulong timeIT = GetTickCount64();
//---find the most relevant predictors
   if(!frel.WeighVars(number_of_partitions,regularization_factor,index,optimal_weights))
      return;
//---calculate runtime
   Print("Runtime of FREL ", GetTickCount64() - timeIT, " ms");
//---display results
   for(uint i = 0; i<optimal_weights.Size(); i++)
      Print("Predictor at Column index ", index[i], " weight ", optimal_weights[i]);

  }
//+------------------------------------------------------------------+

Цель состоит в том, чтобы увидеть, может ли FREL надлежащим образом взвесить переменные, обозначив столбцы 1, 3, 5 и 7 как имеющие наиболее сильную связь с целью. Первоначально мы запускаем скрипт с параметрами по умолчанию, отметив, что регуляризация отключена и указана только одна самозагрузка.

Настройки скрипта Frel по умолчанию

Результаты.

ON      0       18:12:30.906    FrelExample (BTCUSD,D1) Runtime of FREL 273375 ms
GD      0       18:12:30.906    FrelExample (BTCUSD,D1) Predictor at Column index 7 weight 24.46987538756267
IH      0       18:12:30.906    FrelExample (BTCUSD,D1) Predictor at Column index 3 weight 24.22319404776024
EL      0       18:12:30.906    FrelExample (BTCUSD,D1) Predictor at Column index 5 weight 22.26820806768701
LP      0       18:12:30.906    FrelExample (BTCUSD,D1) Predictor at Column index 1 weight 22.13748732798876
DD      0       18:12:30.906    FrelExample (BTCUSD,D1) Predictor at Column index 0 weight 1.162036446785271
KK      0       18:12:30.906    FrelExample (BTCUSD,D1) Predictor at Column index 8 weight 1.1532145209345603
RO      0       18:12:30.906    FrelExample (BTCUSD,D1) Predictor at Column index 4 weight 1.1496286906955606
RS      0       18:12:30.906    FrelExample (BTCUSD,D1) Predictor at Column index 2 weight 1.1472521997561425
NG      0       18:12:30.906    FrelExample (BTCUSD,D1) Predictor at Column index 6 weight 1.14561384476096
DK      0       18:12:30.906    FrelExample (BTCUSD,D1) Predictor at Column index 9 weight 1.14348946606884

Далее мы исследуем влияние регуляризации на оценочные веса, проводя тестирование со степенями регуляризации 0,1 и 1,0.

Frel с настройками коэффициента регуляризации 0,1

Результаты.

MQ      0       18:19:03.951    FrelExample (BTCUSD,D1) Runtime of FREL 331296 ms
QD      0       18:19:03.951    FrelExample (BTCUSD,D1) Predictor at Column index 3 weight 19.63442784832085
PK      0       18:19:03.951    FrelExample (BTCUSD,D1) Predictor at Column index 5 weight 19.009699240770477
GO      0       18:19:03.951    FrelExample (BTCUSD,D1) Predictor at Column index 7 weight 18.823288529399388
GQ      0       18:19:03.951    FrelExample (BTCUSD,D1) Predictor at Column index 1 weight 18.18026689510982
NE      0       18:19:03.951    FrelExample (BTCUSD,D1) Predictor at Column index 0 weight 4.106428447842871
KI      0       18:19:03.951    FrelExample (BTCUSD,D1) Predictor at Column index 8 weight 4.075425288243113
OM      0       18:19:03.951    FrelExample (BTCUSD,D1) Predictor at Column index 2 weight 4.070169243578418
MQ      0       18:19:03.951    FrelExample (BTCUSD,D1) Predictor at Column index 6 weight 4.051103060690134
FE      0       18:19:03.951    FrelExample (BTCUSD,D1) Predictor at Column index 9 weight 4.025271426001863
FJ      0       18:19:03.951    FrelExample (BTCUSD,D1) Predictor at Column index 4 weight 4.0239200200430805

Frel с настройками коэффициента регуляризации 1.0

Результаты.

HP      0       18:25:43.421    FrelExample (BTCUSD,D1) Runtime of FREL 362984 ms
FF      0       18:25:43.421    FrelExample (BTCUSD,D1) Predictor at Column index 3 weight 10.353013480731704
JJ      0       18:25:43.421    FrelExample (BTCUSD,D1) Predictor at Column index 7 weight 10.227015183302557
IM      0       18:25:43.421    FrelExample (BTCUSD,D1) Predictor at Column index 5 weight 10.213781888319609
KQ      0       18:25:43.421    FrelExample (BTCUSD,D1) Predictor at Column index 1 weight 10.079770794877978
PF      0       18:25:43.421    FrelExample (BTCUSD,D1) Predictor at Column index 0 weight 9.948300319843046
QJ      0       18:25:43.421    FrelExample (BTCUSD,D1) Predictor at Column index 8 weight 9.938367489770178
KN      0       18:25:43.421    FrelExample (BTCUSD,D1) Predictor at Column index 2 weight 9.897336276433514
DQ      0       18:25:43.421    FrelExample (BTCUSD,D1) Predictor at Column index 6 weight 9.79559491756489
EF      0       18:25:43.421    FrelExample (BTCUSD,D1) Predictor at Column index 9 weight 9.774541742551756
CI      0       18:25:43.421    FrelExample (BTCUSD,D1) Predictor at Column index 4 weight 9.77227790660475

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

При изучении результатов наших тестов становится очевидным, что FREL работает относительно медленно. Узкое место, скорее всего, связано с функцией total_loss(), которая должна многократно проходить по всему набору данных во время работы оптимизатора. Для повышения эффективности выполнения мы проводим многочисленные самозагрузки с меньшим размером выборки. Следующие результаты получены в результате прогона со 100 самозагрузками из 40 выборок.

Настройки Frel с самозагрузками

Результаты.

IN      0       18:30:55.441    FrelExample (BTCUSD,D1) Runtime of FREL 22985 ms
OK      0       18:30:55.441    FrelExample (BTCUSD,D1) Predictor at Column index 3 weight 18.706272752181135
OL      0       18:30:55.441    FrelExample (BTCUSD,D1) Predictor at Column index 1 weight 18.32079620338284
RS      0       18:30:55.441    FrelExample (BTCUSD,D1) Predictor at Column index 5 weight 18.194009676469012
HG      0       18:30:55.441    FrelExample (BTCUSD,D1) Predictor at Column index 7 weight 16.298306686632337
MI      0       18:30:55.441    FrelExample (BTCUSD,D1) Predictor at Column index 4 weight 5.838867272535404
LM      0       18:30:55.441    FrelExample (BTCUSD,D1) Predictor at Column index 9 weight 5.249285089162589
FQ      0       18:30:55.441    FrelExample (BTCUSD,D1) Predictor at Column index 8 weight 4.791606631149278
DE      0       18:30:55.441    FrelExample (BTCUSD,D1) Predictor at Column index 6 weight 4.770223641360407
KI      0       18:30:55.441    FrelExample (BTCUSD,D1) Predictor at Column index 0 weight 3.974977300216029
KM      0       18:30:55.441    FrelExample (BTCUSD,D1) Predictor at Column index 2 weight 3.855654746910961


Заключение

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

Исходный файл
Описание
Mql5\include\np.mqh
Заголовочный файл различных инструментов для работы с векторами и матрицами
Mql5\include\Powells.mqh
Определение класса PowellsMethod, реализующего метод минимизации функции Пауэллса
Mql5\include\frel.mqh
Определение класса FREL, представляющего взвешивание признаков как регуляризованный алгоритм обучения на основе энергии
Mql5\script\FrelExample.mq5
Скрипт, демонстрирующий использование класса FREL


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

Прикрепленные файлы |
frel.mqh (14.08 KB)
Powells.mqh (17.57 KB)
np.mqh (37.73 KB)
FrelExample.mq5 (2.52 KB)
Mql5.zip (12.76 KB)
Статистический арбитраж с прогнозами Статистический арбитраж с прогнозами
Мы рассмотрим статистический арбитраж, выполним поиск символов корреляции и коинтеграции с помощью Python, создадим индикатор для коэффициента Пирсона, а также советник для торговли статистическим арбитражем с прогнозами, сделанными с помощью Python и моделей ONNX.
Торговля на разрывах справедливой стоимости (FVG)/дисбалансах шаг за шагом: Подход Smart Money Торговля на разрывах справедливой стоимости (FVG)/дисбалансах шаг за шагом: Подход Smart Money
Пошаговое руководство по созданию и реализации автоматизированного торгового алгоритма на основе разрывов справедливой стоимости (Fair Value Gap, FVG) на языке MQL5. Подробное руководство может быть полезно как новичкам, так и опытным трейдерам.
Машинное обучение и Data Science (Часть 22): Автоэнкодеры для устранения шума и выявления сигналов в трейдинге Машинное обучение и Data Science (Часть 22): Автоэнкодеры для устранения шума и выявления сигналов в трейдинге
В динамичном мире финансовых рынков для успешно торговли важно уметь отделять значимые сигналы от шума. Используя сложную архитектуру нейронных сетей, автоэнкодеры успешно выявляют скрытые закономерности в рыночных данных и преобразуют нечеткие входные данные в полезные идеи. В этой статье мы рассмотрим, как такие нейросети могут помочь принимать торговые решения на современных динамичных рынках.
Построение модели ограничения тренда свечей (Часть 2): Объединение нативных индикаторов Построение модели ограничения тренда свечей (Часть 2): Объединение нативных индикаторов
В статье рассматривается использование встроенных индикаторов MetaTrader 5 для отсеивания нетрендовых сигналов. Продолжая предыдущую статью, мы рассмотрим, как это сделать с помощью кода MQL5, чтобы воплотить нашу идею в виде программы.