English Русский 中文 Deutsch 日本語 Português
preview
Un algoritmo de selección de características que utiliza aprendizaje basado en energía en MQL5 puro

Un algoritmo de selección de características que utiliza aprendizaje basado en energía en MQL5 puro

MetaTrader 5Ejemplos | 20 septiembre 2024, 10:13
271 0
Francis Dube
Francis Dube

Introducción

En el ámbito del comercio algorítmico, el uso generalizado del aprendizaje automático ha impulsado la adopción de técnicas de minería de datos para descubrir patrones ocultos en los datos financieros. En este panorama, los profesionales a menudo se enfrentan al desafío de clasificar numerosas variables para identificar aquellas que tienen más probabilidades de ser beneficiosas para lograr objetivos específicos o resolver problemas particulares. En este artículo, exploramos la implementación de un algoritmo de selección de características destinado a evaluar la relevancia de un conjunto de variables candidatas para una tarea de predicción determinada.

Yun Li, Jennie Si, Guojing Zhou, Shasha Huang y Songcan Chen fueron coautores de un artículo de investigación titulado"FREL: Un algoritmo de selección de características estable". En este artículo se presenta un algoritmo denominado "Ponderación de características como aprendizaje regularizado basado en energía" (Feature Weighting as Regularized Energy-Based Learning, FREL), que sirve como una técnica de selección o ponderación de características diseñada para ofrecer tanto precisión como estabilidad. En nuestro debate, ofrecemos una descripción general de los fundamentos teóricos del aprendizaje regularizado basado en energía y la ponderación de características. Además, ilustramos la eficacia del enfoque propuesto mediante la implementación de un programa MQL5 de ejemplo, elaborado como un script, para resaltar el potencial del método como herramienta para la selección de características.


Clasificación ponderada por vecino más próximo

El concepto en el que se basa FREL se inspira en una técnica conocida como clasificación ponderada del vecino más próximo, que aprovecha las distancias entre los puntos de un conjunto de datos para hacer predicciones. Al determinar las ponderaciones adecuadas para cada característica, este método mejora la precisión de la predicción. La clasificación ponderada del vecino más próximo representa una variación del algoritmo del vecino más próximo (k-NN), un enfoque muy utilizado en el aprendizaje automático para tareas de clasificación. En la clasificación k-NN estándar, el algoritmo examina los k puntos de datos más cercanos en el conjunto de entrenamiento al clasificar un nuevo punto de datos, asignando en última instancia la clase mayoritaria entre estos vecinos al nuevo punto de datos.

Sin embargo, en la clasificación ponderada por vecino más próximo, en lugar de limitarse a contar los votos de los vecinos más próximos, el voto de cada vecino se pondera en función de su distancia al nuevo punto de datos. El razonamiento es que los vecinos más cercanos deberían ejercer una mayor influencia en la decisión de clasificación que los más alejados. Este proceso de ponderación implica calcular la distancia entre el nuevo punto de datos y cada punto del conjunto de entrenamiento. Entre las métricas de distancia más utilizadas se encuentran la distancia euclidiana, la distancia Manhattan o la similitud coseno, seleccionadas en función de las características de los datos. En este contexto, utilizamos la distancia Manhattan, también denominada distancia ciudad-bloque, entre puntos de datos. La fórmula para calcular esta distancia se muestra a continuación. Donde, w , son las ponderaciones y un caso de prueba se está evaluando en relación con otros datos de entrenamiento, dados como caso de entrenamiento.

Fórmula de la distancia ponderada entre vecinos más próximos


Comprender los modelos basados en la energía

El modelado basado en la energía en el aprendizaje automático sirve como marco versátil aplicable tanto a tareas de aprendizaje supervisado como no supervisado. Funciona según el principio de asignar valores de energía a diversas configuraciones de datos y aprender un modelo capaz de distinguir entre configuraciones deseables e indeseables. Esto se logra minimizando la energía de los datos observados y maximizando la energía de las configuraciones de datos no observados o indeseables.

En el corazón de los modelos basados en energía se encuentra la definición de una función de energía, denotada como E(). Esta función toma como entrada una configuración de variables de entrada o predictores, junto con un conjunto de parámetros del modelo. La salida de la función de energía proporciona una indicación de la relevancia de la configuración de las variables de entrada. Por ejemplo, en el contexto de la evaluación de un modelo de regresión, la función de energía podría representarse como el error cuadrático medio. Cuando se introducen predictores relevantes en la ecuación del error cuadrático medio, el valor de salida tiende a ser menor, lo que refleja una mayor relevancia. Por el contrario, los predictores pobres conducen a valores de error cuadrático medio mayores. La función de energía asigna un valor escalar a cada configuración concebible de variables.

El objetivo de entrenar un modelo basado en energía es aprender los parámetros de la función de energía para que asigne energías bajas a las variables de entrada relevantes y energías altas a las irrelevantes. Esto implica definir una función objetivo que penalice las energías altas para las variables correctas y las energías bajas para las incorrectas. Para lograr esto, el objetivo es identificar la configuración de variables incorrectas que produce la energía más baja, lo que representa una muestra propensa a causar predicciones erróneas del modelo. La función que se muestra a continuación representa la energía de la configuración de las variables de entrada , x , y del parámetro del modelo, w , que produce el valor erróneo, y , demasiado bajo para distinguirlo de las configuraciones de las variables de entrada que producen predicciones precisas. 

Fórmula de energía para configuración incorrecta con energía más baja

En última instancia, la función objetivo pretende maximizar la discrepancia entre la configuración incorrecta con la energía más baja y la configuración correcta de variables más cercana. La energía de dicha configuración se detalla a continuación.

Fórmula de energía para la configuración correcta más cercana de variables

La función objetivo, conocida como función de pérdida, comprende una función de pérdida promedio por muestra. A continuación se muestra el registro de pérdida.

Función de pérdida promedio por muestra (pérdida logarítmica)

Varios criterios de pérdida pueden servir como función de pérdida por muestra, como la pérdida bisagra, la pérdida logarítmica, la pérdida cuadrática y la pérdida cuadrática-exponencial, dependiendo la elección de la aplicación.

En resumen, estos son los conceptos fundamentales en los que se basa FREL. La sección siguiente profundiza en las particularidades del propio algoritmo.


El algoritmo FREL

Para aplicar eficazmente el algoritmo FREL, deben seguirse ciertas consideraciones fundamentales. En primer lugar, es crucial evaluar cuidadosamente los datos de entrenamiento. FREL es ideal para conjuntos de datos que asignan un conjunto de variables candidatas a un único objetivo. Igualmente importante es asegurarse de que las variables sean similares en escala. Exponer FREL a predictores candidatos con una escala inconsistente puede distorsionar significativamente los resultados finales.

En segundo lugar, dado que el FREL es un procedimiento de aprendizaje basado en la energía, requiere la definición de una función de energía que incorpore parámetros de ponderación. Por lo tanto, el modelo utilizado debe estar configurado para aceptar un conjunto de variables candidatas junto con las ponderaciones correspondientes. Por ejemplo, considerando el error cuadrático medio como una función de energía, cuando el modelo es de regresión, la incorporación de parámetros de ponderación resulta relativamente sencilla. Cada peso se emparejaría con un predictor candidato.

Por último, debe seleccionarse una función de pérdida por muestra para determinar el funcional de pérdida. El funcional de pérdida, que incorpora los parámetros de ponderación del modelo, es la función (de funciones) minimizada para obtener las ponderaciones óptimas.

Los pasos fundamentales del algoritmo FREL son los siguientes:

Matriz de datos de entrenamiento

  1. Comience con un conjunto de datos de entrenamiento compuesto por n observaciones con d predictores candidatos correspondientes a n valores objetivo. El objetivo es determinar los predictores más relevantes del conjunto de d candidatos para determinar los valores objetivo. Esto da como resultado la asignación de pesos a cada uno de los predictores d, lo que indica la importancia de la variable en relación con otras. Un peso mayor significa mayor relevancia a la hora de definir el valor objetivo. 
  2. Inicialmente, asigne a todos los pesos un valor de 1.
  3.  Aplicar la clasificación de vecinos más cercanos ponderados a cada observación en los datos de entrenamiento para identificar la configuración de variables incorrectas que producen la energía más baja y la configuración más cercana de variables correctas con alta energía. Utilice estos valores de energía para calcular la pérdida por muestra utilizando la función de pérdida seleccionada.
  4.  Por último, minimice la función de pérdida objetivo, opcionalmente con regularización, utilizando un procedimiento de optimización adecuado. Esto constituye el núcleo del algoritmo FREL.
En su trabajo de investigación, los autores también demuestran una mejora del algoritmo central mediante el empleo de bootstrapping. La toma de muestras debe realizarse sin reemplazo, y los ponderaciones resultantes son los valores promedios de cada muestra bootstrap.


Implementación de FREL en MQL5

La implementación de FREL mostrada en este texto utiliza el método de optimización de Powell. Aunque el método específico de optimización utilizado no es crítico, los resultados deberían ser relativamente coherentes entre los distintos métodos. En esta implementación, el método de Powell se representa como la clase «PowellsMethod», definida en Powells.mqh. El algoritmo FREL está encapsulado en la clase «FREL», descendiente de «PowellsMethod», especificada en 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;
     }

Profundicemos en la descripción del constructor paramétrico. Se invoca con al menos un parámetro: una matriz de datos de entrenamiento. Es crucial tener en cuenta cómo deben estructurarse los datos de entrenamiento en la matriz. Cada fila representa una observación o una única muestra, mientras que las columnas representan las variables candidatas o los predictores que deben evaluarse. Se espera que el objetivo resida en la última columna de la matriz. Los parámetros opcionales del constructor se explican con más detalle en la tabla siguiente.

 Nombre del parámetro
 Tipo de datos
Valor por defecto
 Descripción
numboot
integer
1
«numboot» establece el número de bootstraps a realizar.
bootsize
integer
0
«bootsize» define el tamaño de cada bootstrap. Tenga cuidado al ajustar este parámetro. Si se utiliza un valor mayor que el número de observaciones de la matriz, «numboot» volverá automáticamente a 1 y «bootsize» al número de observaciones.

Sólo hay un método con el que los usuarios deben familiarizarse para utilizar la clase «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;
     }

Este método evalúa los datos de entrenamiento especificados en el constructor. Devuelve un valor booleano, en el que «false» indica que el procedimiento no se completó. Los parámetros de este método son los siguientes:

  • «num_bins_target": Un entero que define el número de bins en que se particionarán los valores objetivo. Este parámetro debe fijarse en cualquier número entero >= 2 pero <= el número de observaciones de los datos de entrenamiento.
  • «reg_factor": Un valor doble positivo que controla el grado de regularización. Un valor de 0 desactiva la regularización.
  • «index[]": Una matriz de enteros en la que se escribirá parte de los resultados de la operación. Contiene los índices de columna originales, tal y como se suministraron al constructor, ordenados en orden descendente de relevancia para el objetivo.
  • «weights[]": Una matriz doble que contiene las ponderaciones óptimas, ordenadas de forma descendente.

Cuando se invoca «WeighVars()», los valores objetivo se extraen de la matriz y se colocan en una matriz en preparación para una llamada al método privado «bin_array()». Este método segmenta la matriz en categorías de tamaño aproximadamente igual, dando como salida dos matrices al finalizar con éxito. «upperbound_thresholds[]» es una matriz de umbrales superiores para cada segmento, mientras que la matriz de enteros “categories[]” contiene valores índice que representan el segmento al que pertenece cada valor objetivo correspondiente. Cada uno de estos valores se comprueba para garantizar que todos los valores objetivo se han agrupado correctamente.

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

     }

La estimación de las ponderaciones comienza con una llamada a «calc_wt()». Aquí se realiza un muestreo bootstrap, barajando los datos antes de optimizar las ponderaciones iniciales. La optimización se realiza mediante el método de la clase padre «Optimize()». Los pesos óptimos para cada bootstrap se suman en «w[]», para ser promediados antes de salir de «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) ;
     }

Recuerde que la función que se está minimizando es la funcional de pérdida, representada por un método anulado de la clase padre llamado «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;
     }

Dentro de «func()», se activa el método «loss()», que desencadena el cálculo de la función de pérdida por muestra implementada como el método privado «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 ;
     }

Una vez completados todos los bootstraps, los pesos óptimos promediados se escriben en la matriz «weights[]» suministrada por el usuario. Antes de clasificarlas en orden descendente, las ponderaciones se transforman para que sumen colectivamente 100, lo que mejora su interpretabilidad.


Un ejemplo de selección de características mediante FREL<

Para demostrar el algoritmo FREL, proporcionamos el script «FrelExample.mq5». Este script utiliza FREL para analizar un conjunto de datos generado aleatoriamente que comprende variables candidatas y un objetivo para identificar los mejores predictores. Los usuarios pueden ajustar todos los parámetros del algoritmo FREL y ciertas características del conjunto de datos sintéticos. Esto incluye el número total de observaciones ( num_observations ) y el número de predictores candidatos ( num_candidate_predictors ). A continuación se muestra un fragmento que ilustra las entradas ajustables por el usuario del script:

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

El script genera una matriz de números aleatorios con num_observations filas y num_candidate_predictors + 1 columnas. La última columna se sobrescribe con la suma de las columnas en los índices 1, 3, 5 y 7, que sirve como variable objetivo del conjunto de datos.

//+------------------------------------------------------------------+
//| 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]);

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

El objetivo es observar si FREL puede ponderar adecuadamente las variables, designando las columnas 1, 3, 5 y 7 como las que tienen una relación más fuerte con el objetivo. Inicialmente, ejecutamos el script con los parámetros por defecto, observando que la regularización está desactivada y que sólo se especifica un bootstrap.

Configuración predeterminada del script Frel

Resultado:

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

A continuación, investigamos el impacto de la regularización en las ponderaciones estimadas realizando pruebas con grados de regularización de 0.1 y 1.0.

Configuración de Frel con factor de regularización 0.1

Resultado:

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

Configuración de Frel con factor de regularización 1.0

Resultado:

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

Los resultados de las pruebas de regularización indican que los pesos se distribuyen entre otras variables y se apartan de las variables correctas. Es probable que especificar un mayor grado de regularización conduzca a pesos menos diferenciados, lo que dificultará la diferenciación de variables útiles de las irrelevantes.

Al examinar los resultados de tiempo de ejecución de nuestras pruebas, es evidente que FREL opera relativamente lento. Es probable que el cuello de botella se atribuya a la función "total_loss()", que debe iterar a través de todo el conjunto de datos varias veces mientras se ejecuta el optimizador. Para mejorar la eficiencia del tiempo de ejecución, realizamos numerosos bootstraps con un tamaño de muestra más pequeño. Los siguientes resultados se obtienen de una ejecución con 100 bootstraps de 40 muestras.

Configuración de Frel con BootStrapped

Resultado:

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


Conclusión

En este artículo, presentamos una implementación MQL5 de ponderación de características utilizando modelos regularizados basados en energía. Proporcionamos una breve descripción general de la base teórica del algoritmo y mostramos su eficacia en un conjunto de datos sintéticos. Si bien los resultados fueron prometedores, observamos que el algoritmo generaba costos computacionales significativos, lo que generaba un análisis lento. Para abordar este problema, propusimos la utilización de múltiples bootstraps con tamaños de muestra más pequeños, lo que mejoró notablemente la velocidad de ejecución general del algoritmo. Sin embargo, nuestra implementación aún podría beneficiarse en gran medida del multihilo o de la aceleración por GPU. No obstante, se anima a las personas interesadas en el método a que personalicen el código según sus necesidades.< El artículo incluye todo el código discutido, con cada archivo fuente detallado en la tabla siguiente.

Archivo fuente
Descripción
Mql5\include\np.mqh
Un archivo de encabezado de varias herramientas de manipulación de matrices y vectores.
Mql5\include\Powells.mqh
Contiene la definición de la clase PowellsMethod que implementa el método Powell de minimización de funciones.
Mql5\include\frel.mqh
Contiene la definición de la clase FREL que representa la ponderación de características como algoritmo de aprendizaje basado en energía regularizada.
Mql5\script\FrelExample.mq5
Un script que demuestra el uso de la clase FREL.


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

Archivos adjuntos |
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)
Red neural en la práctica: Pseudo inversa (I) Red neural en la práctica: Pseudo inversa (I)
Aquí, comenzaremos a ver cómo podemos implementar, utilizando MQL5 puro, el cálculo de la pseudo inversa. A pesar de que el código que veremos será considerablemente más complicado para los principiantes de lo que realmente me gustaría presentar, aún estoy pensando en cómo explicarlo de manera sencilla. Considera esto una oportunidad para estudiar un código poco común. Así que ve con calma. Sin prisa. Aunque no esté enfocado en ser eficiente o de rápida ejecución, el objetivo es ser lo más didáctico posible.
Desarrollamos un asesor experto multidivisa (Parte 6): Automatizamos la selección de un grupo de instancias Desarrollamos un asesor experto multidivisa (Parte 6): Automatizamos la selección de un grupo de instancias
Tras optimizar una estrategia comercial, obtendremos conjuntos de parámetros en base a los cuales podremos crear varias instancias (ejemplares) de estrategias comerciales combinadas en un asesor experto. Antes lo hacíamos manualmente, pero ahora trataremos de automatizar el proceso
MetaTrader 4 en macOS MetaTrader 4 en macOS
Hemos preparado un instalador especial de la plataforma comercial MetaTrader 4 para macOS: se trata de un asistente completo que permite instalar la aplicación como nativa, y que realiza todas las acciones necesarias: detecta su sistema, descarga e instala la última versión de Wine para él, lo configura, y luego instala MetaTrader dentro del mismo. Todo sucede en modo automático, solo hay que esperar a que se complete la instalación, después de lo cual se podrá empezar a trabajar inmediatamente con la plataforma.
Red neuronal en la práctica: Mínimos cuadrados Red neuronal en la práctica: Mínimos cuadrados
Aquí en este artículo, veremos algunas cosas, entre ellas: Cómo muchas veces las fórmulas matemáticas parecen más complicadas cuando las miramos, que cuando las implementamos en código. Además de este hecho, también se mostrará cómo puedes ajustar el cuadrante del gráfico, así como un problema curioso que puede suceder en tu código MQL5. Algo que sinceramente no sé cómo explicar, ya que no lo entendí. A pesar de eso, mostraré cómo corregirlo en el código.