
Un algoritmo de selección de características que utiliza aprendizaje basado en energía en MQL5 puro
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.
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.
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.
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.
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:
- 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.
- Inicialmente, asigne a todos los pesos un valor de 1.
- 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.
- 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.
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.
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.
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
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.
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





- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso