English Русский 中文 Deutsch 日本語 Português
preview
Experimentos con redes neuronales (Parte 5): Normalización de parámetros de entrada para su transmisión a una red neuronal

Experimentos con redes neuronales (Parte 5): Normalización de parámetros de entrada para su transmisión a una red neuronal

MetaTrader 5Sistemas comerciales | 8 agosto 2023, 10:06
304 0
Roman Poshtar
Roman Poshtar

Introducción

Buenas tardes, estimados usuarios de la comunidad MQL5. Después de una pequeña reflexión sobre los resultados de nuestros experimentos anteriores, me planteé la tarea de cómo mejorar el rendimiento del entrenamiento y, en consecuencia, la rentabilidad de los asesores expertos anteriormente desarrollados.

Hoy hablaremos de la importancia de la señal, a saber, de la transmisión de datos a la red neuronal para el análisis y la predicción de los resultados futuros. Recuerde que este es un componente muy importante de la red neuronal, e incluso el más importante de todos. Mi intención es transmitir a los lectores la importancia de comprender las señales para evitar molestos malentendidos, tales como "he utilizado la biblioteca más avanzada y no funciona". En artículos anteriores, aplicamos algunos métodos interesantes, hoy trataremos de transferir los datos del indicador normalizando sus valores.

Por mi parte, como siempre, fue una explicación detallada no muy comprensible. Creo que todos podrán aclararse.


La importancia de la normalización de los parámetros de entrada para la transmisión a una red neuronal

La normalización de los parámetros de entrada supone un paso importante en el proceso de preparación de los datos para el entrenamiento de redes neuronales. Este proceso permite llevar los datos de entrada a un determinado rango de valores, lo cual ayuda a mejorar la estabilidad y la velocidad de la convergencia del entrenamiento.

En este artículo, veremos por qué la normalización supone un paso importante en el entrenamiento de redes neuronales y qué métodos de normalización se pueden usar.

Normalización de los parámetros de entrada: ¿qué significa esto?

La normalización de los parámetros de entrada consiste en transformar los datos de entrada para que posean un cierto rango de valores. Con frecuencia se usan dos métodos principales de normalización: la normalización por la media y la desviación estándar (normalización z) y la normalización según el mínimo y máximo (normalización min-max).

La normalización Z usa la media y la desviación estándar para centrar y escalar los datos. Para hacer esto, cada valor se resta de la media y se divide por la desviación estándar. La normalización min-max usa los valores mínimo y máximo para escalar los datos a un rango determinado.

¿Por qué es tan importante la normalización de los parámetros de entrada?

La normalización de los parámetros de entrada es importante para mejorar la estabilidad y la tasa de convergencia del aprendizaje. Si los datos de entrada no están normalizados, algunos parámetros podrían tener un amplio rango de valores, lo cual puede provocar problemas a la hora de entrenar la red neuronal. Por ejemplo, los gradientes pueden volverse demasiado grandes o pequeños, lo que generará problemas de optimización y poca precisión de predicción.

La normalización también nos permite acelerar el proceso de aprendizaje, ya que se puede mejorar la convergencia del algoritmo de optimización. Los datos correctamente normalizados también ayudan a evitar el problema de sobreajuste que puede ocurrir si los datos de entrada no tienen la debida representatividad.

¿Qué métodos de normalización se pueden usar?

Los métodos de normalización pueden variar según el tipo de datos y el problema que estemos resolviendo. Por ejemplo, los métodos de normalización se usan a menudo para imágenes, como la normalización por la media y la desviación estándar (normalización z) y la normalización según el mínimo y máximo (normalización min-max). Sin embargo, para otros tipos de datos, como las señales de audio o los datos de texto, puede resultar más eficaz utilizar otros métodos de normalización.

Para señales de audio, por ejemplo, con frecuencia se usa la normalización de amplitud máxima, donde todos los valores de la señal se escalan entre -1 y 1. Para datos de texto, puede resultar útil normalizar por el número de palabras o caracteres en una oración.

Además, en algunos casos puede ser útil para normalizar no solo los datos de entrada, sino también las variables objetivo. Por ejemplo, en problemas de regresión donde la variable objetivo tiene un amplio rango de valores, puede resultar útil normalizar la variable objetivo para mejorar la estabilidad del entrenamiento y la precisión de la predicción.

La normalización de los parámetros de entrada supone un paso importante en el proceso de preparación de los datos para el entrenamiento de redes neuronales. Este proceso permite llevar los datos de entrada a un determinado rango de valores, lo cual ayuda a mejorar la estabilidad y la velocidad de la convergencia del entrenamiento. Dependiendo del tipo de datos y del problema que estemos tratando de resolver, se pueden utilizar diferentes métodos de normalización. Además, en algunos casos puede ser útil para normalizar no solo los datos de entrada, sino también las variables objetivo.


Métodos de normalización

Normalización Min-Max

En el aprendizaje automático, la normalización supone un paso importante del preprocesamiento de datos que mejora la estabilidad y la tasa de convergencia del entrenamiento. Uno de los métodos de normalización más comunes es la normalización Min-Max, que nos permite llevar los valores de los datos al rango de 0 a 1. En este artículo, veremos cómo podemos usar la normalización Min-Max para series temporales.

Las series temporales son una secuencia de valores medidos en diferentes puntos en el tiempo. Ejemplos de series temporales son los datos sobre la temperatura, los precios de las acciones o el número de ventas de bienes. Las series temporales se pueden usar para predecir valores futuros, analizar tendencias y patrones o detectar anomalías.

Las series temporales pueden tener un rango diferente de valores y los cambios a lo largo del tiempo pueden no resultar uniformes. Por ejemplo, los precios de las acciones pueden variar ampliamente y fluctuar según la estacionalidad, las noticias y otros factores. Para analizar y pronosticar las series temporales de forma efectiva, deberemos llevar los valores a un cierto rango.

El método de normalización Min-Max normaliza los valores en un rango de 0 a 1 escalando los valores según los valores mínimo y máximo. La fórmula para la normalización Min-Max es la que sigue:

x_norm = (x - x_min) / (x_max - x_min)

donde x es el valor de los datos, x_min es el valor mínimo en todo el conjunto de datos, x_max es el valor máximo en todo el conjunto de datos, y x_norm es el valor normalizado.

La aplicación de la normalización Min-Max a las series temporales puede ayudarnos a llevar los datos a un rango común de valores y simplificar el análisis. Por ejemplo, si tenemos datos de temperatura que oscilan entre -30 y +30 grados, podemos aplicar la normalización Min-Max para llevar los valores al rango que va de 0 a 1. Esto nos permitirá comparar valores en diferentes periodos de tiempo e identificar tendencias y anomalías.

Sin embargo, al aplicar la normalización Min-Max a las series temporales, debemos tener en cuenta las características de este método y su impacto en los datos. Primero, el uso de la normalización Min-Max puede provocar una pérdida de información sobre la distribución de valores dentro del rango. Por ejemplo, si tenemos valores atípicos o extremos en el conjunto de datos, se convertirán en 0 o 1 y se perderán en el análisis. En este caso, podemos utilizar métodos de normalización alternativos, como la normalización de Z-score.

En segundo lugar, al utilizar la normalización Min-Max, debemos considerar la dinámica de cambio de los datos. Si los datos tienen una dinámica de cambio desigual, la normalización podría generar distorsiones en los patrones de tiempo, así como anomalías. En este caso, podemos aplicar la normalización local, donde se determinan los valores mínimos y máximos para cada grupo de datos dentro de un periodo de tiempo determinado.

En tercer lugar, al usar la normalización Min-Max, debemos tener en cuenta la influencia de la muestra en los resultados del análisis. Si la muestra de observaciones no está equilibrada o contiene valores atípicos, la normalización podría llevarnos a conclusiones erróneas. En este caso, podemos utilizar métodos alternativos de procesamiento de datos, como la eliminación de valores atípicos o el suavizado de datos.

En conclusión, el método de normalización Min-Max es uno de los métodos de normalización más comunes en el aprendizaje automático y se puede aplicar de forma efectiva a las series temporales para llevar los valores a un rango común. No obstante, al utilizar este método, debemos considerar las características de los datos y aplicar métodos de procesamiento adicionales para evitar distorsiones en el análisis y el pronóstico de series temporales.

Ejemplo

int OnInit()
  {

// declare and initialize the array
double data_array[] = {1.2, 2.3, 3.4, 4.5, 5.6};

// find the minimum and maximum value in the array
double min_value = ArrayMinimum(data_array, 0, ArraySize(data_array)-1);
double max_value = ArrayMaximum(data_array, 0, ArraySize(data_array)-1);

// create an array to store the normalization result
double norm_array[ArraySize(data_array)];

// normalize the array
for(int i = 0; i < ArraySize(data_array); i++) {
    norm_array[i] = (data_array[i] - min_value) / (max_value - min_value);
}

// display the result
for(int i = 0; i < ArraySize(data_array)-1; i++) {
Print("Source array: ", data_array[i]);
Print("Min-Max normalization result: ", norm_array[i]);
}

return(INIT_SUCCEEDED);
}

Este código crea un array data_array que contiene cinco números de coma flotante. Luego encuentra los valores mínimo y máximo en el array usando las funciones ArrayMinimum() y ArrayMaximum(), crea un nuevo array norm_array para almacenar el resultado de la normalización y lo rellena realizando los cálculos para cada elemento (data_array[i] - min_value) / (max_value - min_value) . Finalmente, el resultado se muestra en la pantalla con la ayuda de la función Print() .

Resultado:

2023.04.07 13:22:32.937 11111111111111 (EURUSD,H1)      Source array: 1.2
2023.04.07 13:22:32.937 11111111111111 (EURUSD,H1)      Min-Max normalization result: 0.39999999999999997
2023.04.07 13:22:32.937 11111111111111 (EURUSD,H1)      Source array: 2.3
2023.04.07 13:22:32.937 11111111111111 (EURUSD,H1)      Min-Max normalization result: 0.7666666666666666
2023.04.07 13:22:32.937 11111111111111 (EURUSD,H1)      Source array: 3.4
2023.04.07 13:22:32.937 11111111111111 (EURUSD,H1)      Min-Max normalization result: 1.1333333333333333
2023.04.07 13:22:32.937 11111111111111 (EURUSD,H1)      Source array: 4.5
2023.04.07 13:22:32.937 11111111111111 (EURUSD,H1)      Min-Max normalization result: 1.5


Normalización Z

Las series de tiempo son una herramienta importante en el análisis de datos, especialmente en economía, finanzas, meteorología, ciencia de materiales y otros campos del saber. Uno de los principales métodos de preprocesamiento de series temporales es la normalización Z, que puede ayudar a mejorar la calidad del análisis de datos.

La normalización Z es un método para centrar y escalar series temporales que consiste en transformar la serie temporal de tal forma que el valor medio de la serie temporal sea igual a cero y la desviación estándar sea igual a uno. Esto puede resultar útil para comparar series temporales entre sí, así como para eliminar la influencia de la estacionalidad y las tendencias.

El proceso de normalización Z de series temporales comprende los siguientes pasos:

  1. Calculamos la media de la serie temporal.
  2. Calculamos la desviación estándar de la serie temporal.
  3. Para cada elemento de la serie temporal, calculamos la diferencia entre su valor y el valor medio de la serie temporal.
  4. Dividimos cada diferencia por la desviación estándar.

Los valores resultantes tendrán una media de cero y una desviación estándar de uno.

Ventajas de la normalización Z:

  1. Mejora la calidad del análisis de datos. La normalización Z puede ayudar a eliminar los efectos de la estacionalidad y las tendencias, lo cual puede mejorar la calidad de nuestro análisis de datos.
  2. Facilidad de uso. La normalización Z es fácil de utilizar y se puede aplicar a diferentes tipos de series temporales.
  3. Resulta útil al comparar series temporales. La normalización Z permite comparar series temporales entre sí, ya que elimina la influencia de diferentes escalas y unidades de medida.

No obstante lo dicho, la normalización Z también tiene algunas limitaciones:

  1. No es apta para series temporales con valores extremos. Si la serie temporal contiene valores extremos, la normalización Z podría dar lugar a resultados sesgados.
  2. No es apta para series temporales no estacionarias. Si la serie temporal no es estacionaria (es decir, tiene una tendencia o estacionalidad), la normalización Z puede eliminar estas características, lo cual puede conducir a un análisis de datos incorrecto.
  3. No garantiza una distribución normal. La normalización Z puede ayudar a normalizar la distribución de la serie temporal, pero no garantiza que la distribución resulte exactamente normal.

A pesar de estas limitaciones, la normalización Z es una importante técnica de preprocesamiento de series temporales que puede ayudarnos a mejorar la calidad del análisis de datos. Se puede usar en varios campos, incluidos la economía, las finanzas, la meteorología y la ciencia de materiales.

Por ejemplo, en economía y finanzas, la normalización Z se puede usar para comparar el rendimiento de diferentes activos o portafolios y para analizar el riesgo y la volatilidad.

En meteorología, la normalización Z puede ayudar a eliminar la influencia de la estacionalidad y las tendencias del análisis de datos meteorológicos, como la temperatura o la precipitación.

En la ciencia de materiales, la normalización Z se puede utilizar para analizar series temporales de propiedades de los materiales, como la expansión térmica o las propiedades magnéticas.

En conclusión, la normalización Z es una importante técnica de preprocesamiento de series temporales que puede ayudar a mejorar la calidad del análisis de datos en varias áreas. A pesar de poseer algunas limitaciones, la normalización Z es fácil de usar y se puede aplicar a diferentes tipos de series temporales.

Ejemplo

int OnInit()
  {

// declare and initialize the array
double data_array[] = {1.2, 2.3, 3.4, 4.5, 5.6};

// find the mean and standard deviation in the array
double mean_value = ArrayAverage(data_array, 0, ArraySize(data_array)-1);
double std_value = ArrayStdDev(data_array, 0, ArraySize(data_array)-1);

// create an array to store the normalization result
double norm_array[ArraySize(data_array)];

// normalize the array
for(int i = 0; i < ArraySize(data_array); i++) {
    norm_array[i] = (data_array[i] - mean_value) / std_value;
}

// display the result
for(int i = 0; i < ArraySize(data_array)-1; i++) {
Print("Source array: ", data_array[i]);
Print("Z-normalization result: ", norm_array[i]);
}

return(INIT_SUCCEEDED);
}

double ArrayAverage(double &array[], int start_pos=0, int count=-1)
{
    double sum = 0.0;
    int size = ArraySize(array);

    // Determine the last element index
    int end_pos = count < 0 ? size - 1 : start_pos + count - 1;
    end_pos = end_pos >= size ? size - 1 : end_pos;

    // Calculate the sum of elements
    for(int i = start_pos; i <= end_pos; i++) {
        sum += array[i];
    }

    // Calculate the average value
    double avg = sum / (end_pos - start_pos + 1);
    return (avg);
}

double ArrayStdDev(double &array[], int start_pos=0, int count=-1)
{
    double mean = ArrayAverage(array, start_pos, count);
    double sum = 0.0;
    int size = ArraySize(array);

    // Determine the last element index
    int end_pos = count < 0 ? size - 1 : start_pos + count - 1;
    end_pos = end_pos >= size ? size - 1 : end_pos;

    // Calculate the sum of squared deviations from the mean
    for(int i = start_pos; i <= end_pos; i++) {
        sum += MathPow(array[i] - mean, 2);
    }

    // Calculation of standard deviation
    double std_dev = MathSqrt(sum / (end_pos - start_pos + 1));
    return (std_dev);
}

Este código crea un array data_array que contiene cinco números de coma flotante. Luego encuentra la media y la desviación estándar en el array usando las funciones ArrayAverage() y ArrayStdDev() , crea un nuevo array norm_array para almacenar el resultado de la normalización y lo rellena calculando para cada elemento (data_array[i] - mean_value) / std_value . Finalmente, el resultado se muestra en la pantalla con la ayuda de la función Print() .

Resultado:

2023.04.07 13:51:57.501 11111111111111 (EURUSD,H1)      Source array: 1.2
2023.04.07 13:51:57.501 11111111111111 (EURUSD,H1)      Z-normalization result: -1.3416407864998738
2023.04.07 13:51:57.501 11111111111111 (EURUSD,H1)      Source array: 2.3
2023.04.07 13:51:57.501 11111111111111 (EURUSD,H1)      Z-normalization result: -0.4472135954999581
2023.04.07 13:51:57.501 11111111111111 (EURUSD,H1)      Source array: 3.4
2023.04.07 13:51:57.501 11111111111111 (EURUSD,H1)      Z-normalization result: 0.44721359549995776
2023.04.07 13:51:57.501 11111111111111 (EURUSD,H1)      Source array: 4.5
2023.04.07 13:51:57.501 11111111111111 (EURUSD,H1)      Z-normalization result: 1.3416407864998736


Diferenciación

La diferenciación de series temporales supone un importante método de análisis de datos que nos permite eliminar la tendencia y/o la estacionalidad de la serie, haciéndola más estacionaria. En este artículo, veremos qué es la diferenciación, cómo aplicarla y qué beneficios puede ofrecernos.

¿Qué es la diferenciación de series temporales?

La diferenciación supone el proceso de búsqueda de diferencias entre valores sucesivos en una serie temporal. El número de diferencias que necesitamos encontrar dependerá del grado de estacionariedad que deseemos lograr. Por lo general, una o dos diferencias resultan suficientes para eliminar la tendencia o la estacionalidad. Un paso de diferencia se ve así:

y'(t) = y(t) - y(t-1)

donde y'(t) es la diferencia entre el valor actual de la serie y el valor anterior.

Si la serie no es estacionaria, después de la diferenciación, sus valores se volverán más aleatorios, sin tendencias visibles ni estacionalidad. Esto puede ayudarnos a resaltar las características más obvias de la serie temporal, como los ciclos o la volatilidad.

¿Cómo aplicar la diferenciación de series temporales?

Para diferenciar una serie temporal, debemos seguir estos pasos:

  1. Determinamos si la serie es no estacionaria. Si hay una tendencia o estacionalidad en la serie, no será estacionaria.
  2. Determinamos cuántas diferencias se necesitan para obtener la estacionariedad. Si deseamos eliminar solo la tendencia, entonces una diferencia será suficiente. Si deseamos eliminar la estacionalidad, es posible que se requieran dos o más diferencias.
  3. Aplicamos una transformación de diferencia a la serie. Usaremos la fórmula y'(t) = y(t) - y(t-1) para encontrar la primera diferencia. Si necesitamos encontrar la segunda diferencia, aplicaremos la fórmula a y'(t).
  4. Comprobamos si la serie es estacionaria. Para ello, podemos utilizar pruebas estadísticas de estacionariedad, como la prueba de Dickey-Fuller.
  5. Si la serie no es estacionaria, repetiremos el proceso de diferenciación hasta que la serie se vuelva estacionaria.

¿Cuáles son las ventajas de diferenciar series temporales?

La diferenciación de series temporales puede ofrecernos varias ventajas:

  1. Mejora del pronóstico: Cuando una serie temporal es estacionaria, el pronóstico se vuelve más fácil porque las propiedades estadísticas de la serie no cambian con el tiempo.
  2. Eliminación de la tendencia: Al diferenciar la serie, se elimina la tendencia lineal, lo cual hace que la serie sea más estacionaria y mejore su análisis.
  3. Eliminación de la estacionalidad: Usando múltiples pasos de diferencia, podemos eliminar la estacionalidad de una serie temporal, haciéndola más estacionaria.
  4. Eliminación del ruido: Al diferenciar la serie, se eliminan los componentes de baja frecuencia (tendencia y estacionalidad), lo cual puede ayudar a eliminar el ruido que introducen estos componentes.
  5. Mejora de la interpretación: Cuando la serie es estacionaria, se puede analizar usando métodos estadísticos clásicos, lo que hace que la interpretación de los datos resulte más fácil y comprensible.

Sin embargo, la diferenciación también puede conllevar desventajas. Por ejemplo, si diferenciamos una serie demasiadas veces, podemos perder señales importantes, lo que lleva a conclusiones incorrectas. Además, la diferenciación podría introducir ruido adicional en la serie.

La diferenciación de series temporales es una técnica útil de análisis de datos que elimina la tendencia y/o la estacionalidad de una serie, haciéndola más estacionaria: esto mejora la predicción, elimina el ruido y mejora la interpretación de los datos. No obstante, la diferenciación también puede tener desventajas, por lo que debe usarse con precaución y en combinación con otros métodos de análisis de datos.

Ejemplo

int OnInit()
  {

// declare and initialize the array
double data_array[] = {1.2, 2.3, 3.4, 4.5, 5.6};

// create an array to store the result of differentiation
double diff_array[ArraySize(data_array)];

// differentiate the array
for(int i = 0; i < ArraySize(data_array)-1; i++) {
    diff_array[i] = data_array[i+1] - data_array[i];
}

// display the result
for(int i = 0; i < ArraySize(data_array)-1; i++) {
Print("Source array: ", data_array[i]);
Print("Differentiation result: ", diff_array[i]);
}

return(INIT_SUCCEEDED);
}

Este código crea un array data_array que contiene cinco números de coma flotante. Luego crea un nuevo array diff_array para almacenar el resultado de la diferenciación y lo rellena restando cada elemento i+1 del elemento i en data_array . Finalmente, el resultado se muestra en la pantalla con la ayuda de la función Print() .

Resultado:

2023.04.07 13:13:50.650 11111111111111 (EURUSD,H1)      Source array: 1.2
2023.04.07 13:13:50.650 11111111111111 (EURUSD,H1)      Differentiation result: 1.0999999999999999
2023.04.07 13:13:50.650 11111111111111 (EURUSD,H1)      Source array: 2.3
2023.04.07 13:13:50.650 11111111111111 (EURUSD,H1)      Differentiation result: 1.1
2023.04.07 13:13:50.650 11111111111111 (EURUSD,H1)      Source array: 3.4
2023.04.07 13:13:50.650 11111111111111 (EURUSD,H1)      Differentiation result: 1.1
2023.04.07 13:13:50.650 11111111111111 (EURUSD,H1)      Source array: 4.5
2023.04.07 13:13:50.650 11111111111111 (EURUSD,H1)      Differentiation result: 1.0999999999999996


Transformación logarítmica

La transformación de registros de series temporales es una técnica de transformación de datos que se usa para mejorar las propiedades de una serie antes del análisis y el modelado. Este método resulta especialmente útil cuando los datos tienen una alta variabilidad o los valores originales se encuentran en un amplio rango.

¿Qué es una transformación logarítmica?

La transformación logarítmica supone un proceso en el que se aplica una función logarítmica a cada valor en una serie temporal. La función logarítmica se utiliza para comprimir los valores de una serie, especialmente si se hallan en un rango amplio. El uso del logaritmo reduce la variabilidad de la serie, pues suaviza los picos y valles de los datos, haciéndolos menos pronunciados.

¿Cuándo resulta útil la transformación logarítmica?

La transformación logarítmica puede sernos de utilidad en las siguientes situaciones:

  1. Cuando los datos tienen alta variabilidad: Si los datos tienen una gran variabilidad, la transformación logarítmica puede suavizarlos y hacerlos más predecibles.
  2. Cuando los datos se encuentran en un rango amplio: Si los datos están en un amplio rango, entonces la transformación logarítmica puede comprimirlos y mejorar su interpretación.
  3. Cuando los datos poseen una tendencia exponencial: Si los datos tienen una tendencia exponencial, la transformación logarítmica puede convertirlos en lineales, lo cual facilita su análisis y modelado.
  4. Cuando los datos no se distribuyen normalmente: Si los datos no se distribuyen normalmente, la transformación logarítmica puede hacerlos más normales.

Ejemplo de aplicación de la transformación logarítmica:

Digamos que tenemos una serie temporal que representa las ventas diarias de una tienda a lo largo de varios años. Como las ventas pueden ser muy variables e irregulares, podemos aplicar una transformación logarítmica para suavizar los datos y hacerlos más predecibles.

Continuando con nuestro ejemplo, podemos aplicar la transformación logarítmica a nuestra serie temporal de ventas. Para ello, aplicaremos una función logarítmica a cada valor de nuestra serie.

Por ejemplo, si tenemos una serie de ventas {100, 200, 300, 400}, podemos aplicar una transformación logarítmica para obtener {log(100), log(200), log(300), log(400)} o solo {2 , 2.3, 2.5, 2.6} usando el logaritmo natural.

Como podemos ver en el ejemplo, la transformación logarítmica ha comprimido los valores de la serie, haciéndola más adecuada para el análisis y el modelado. Esto nos permite comprender mejor las tendencias de ventas y realizar pronósticos más precisos.

Sin embargo, no debemos olvidar que la transformación logarítmica no es un método universal y no siempre resulta adecuada para todos los tipos de datos. Además, al aplicar la transformación logarítmica, deberemos tener cuidado de no olvidar volver a la escala de datos original si fuera necesario.

En conclusión, la transformación logarítmica es un método útil para transformar series temporales para mejorar sus propiedades antes del análisis y el modelado. Puede resultar especialmente útil para datos con alta variabilidad o un amplio rango. No obstante, al usarla, deberemos ser consciente de sus limitaciones e interpretar correctamente los resultados.

Ejemplo

int OnInit()
  {

// declare and initialize the array
double data_array[] = {1.2, 2.3, 3.4, 4.5, 5.6};

// create an array to store the normalization result
double norm_array[ArraySize(data_array)];

// normalize the array
LogTransform(data_array, norm_array);

// display the result
for(int i = 0; i < ArraySize(data_array)-1; i++) {
Print("Source array: ", data_array[i]);
Print("Logarithmic transformation result: ", norm_array[i]);
}

return(INIT_SUCCEEDED);
}

void LogTransform(double& array1[], double& array2[])
{
    int size = ArraySize(array1);

    for(int i = 0; i < size; i++) {
        array2[i] = MathLog10(array1[i]);
    }
}

La función LogTransform() se usa para la transformación logarítmica del array de datos array1 y almacenar el resultado en el array array2.

El algoritmo funciona de la forma siguiente: la función MathLog10() se usa para convertir cada elemento de array1 a un logaritmo de base 10, y el resultado se almacena en el elemento correspondiente de array2.

Tenga en cuenta que la función LogTransform() acepta arrays de datos por referencia (a través de & ), lo cual significa que los cambios realizados en array2 dentro de la función se reflejarán en el array original transmitido como argumento al llamar a la función.

Resultado:

2023.04.07 14:21:22.374 11111111111111 (EURUSD,H1)      Source array: 1.2
2023.04.07 14:21:22.374 11111111111111 (EURUSD,H1)      Logarithmic transformation result: 0.07918124604762482
2023.04.07 14:21:22.374 11111111111111 (EURUSD,H1)      Source array: 2.3
2023.04.07 14:21:22.374 11111111111111 (EURUSD,H1)      Logarithmic transformation result: 0.36172783601759284
2023.04.07 14:21:22.374 11111111111111 (EURUSD,H1)      Source array: 3.4
2023.04.07 14:21:22.374 11111111111111 (EURUSD,H1)      Logarithmic transformation result: 0.5314789170422551
2023.04.07 14:21:22.374 11111111111111 (EURUSD,H1)      Source array: 4.5
2023.04.07 14:21:22.374 11111111111111 (EURUSD,H1)      Logarithmic transformation result: 0.6532125137753437


Métodos de procesamiento adicionales para evitar distorsiones en el análisis y pronóstico de series temporales.

Las series temporales se usan ampliamente para el análisis y la realización de pronósticos en diversos campos, como la economía, las finanzas, la ciencia del clima, etc. Sin embargo, los datos del mundo real con frecuencia contienen distorsiones, como valores atípicos, valores ausentes o ruido que pueden influir en la precisión del análisis y la previsión de las series temporales. En este artículo, analizaremos varios métodos de procesamiento adicionales que ayudarán a evitar distorsiones en el análisis y el pronóstico de series temporales.

Eliminación de valores atípicos

Los valores atípicos son valores muy diferentes al resto de los valores de la serie. Pueden deberse a errores de medición, errores en los datos de entrada o eventos imprevistos como crisis o accidentes. Con la eliminación de los valores atípicos de la serie temporal podemos mejorar la calidad del análisis y la previsión.

El lenguaje MQL5 ofrece varias funciones para eliminar valores atípicos. Por ejemplo, la función iqr() se puede usar para determinar el rango intercuartílico y calcular los límites de los valores atípicos. La función MODE_OUTLIERS se puede usar para determinar loa valores atípicos según un valor de capa de decisión. Estas funciones se pueden utilizar en combinación con otras funciones para eliminar valores atípicos.

Ejemplo

void RemoveOutliers(double& array[])
{
    int size = ArraySize(array);
    double mean = ArrayAverage(array);
    double stddev = ArrayStdDev(array, mean);

    for(int i = 0; i < size; i++) {
        if(MathAbs(array[i] - mean) > 2 * stddev) {
            array[i] = mean;
        }
    }
}

double ArrayAverage(double &array[], int start_pos=0, int count=-1)
{
    double sum = 0.0;
    int size = ArraySize(array);

    // Determine the last element index
    int end_pos = count < 0 ? size - 1 : start_pos + count - 1;
    end_pos = end_pos >= size ? size - 1 : end_pos;

    // Calculate the sum of elements
    for(int i = start_pos; i <= end_pos; i++) {
        sum += array[i];
    }

    // Calculate the average value
    double avg = sum / (end_pos - start_pos + 1);
    return (avg);
}

double ArrayStdDev(double &array[], int start_pos=0, int count=-1)
{
    double mean = ArrayAverage(array, start_pos, count);
    double sum = 0.0;
    int size = ArraySize(array);

    // Determine the last element index
    int end_pos = count < 0 ? size - 1 : start_pos + count - 1;
    end_pos = end_pos >= size ? size - 1 : end_pos;

    // Calculate the sum of squared deviations from the mean
    for(int i = start_pos; i <= end_pos; i++) {
        sum += MathPow(array[i] - mean, 2);
    }

    // Calculation of standard deviation
    double std_dev = MathSqrt(sum / (end_pos - start_pos + 1));
    return (std_dev);
}

La función RemoveOutliers() usa la media y la desviación estándar para determinar los valores atípicos en un array. Si un elemento del array está fuera del rango de las dos desviaciones estándar de la media, se considerará un valor atípico y se reemplazará por la media.

Tenga en cuenta que la función RemoveOutliers() también aplica un array de datos por referencia (a través de & ), lo cual significa que los cambios realizados en el array dentro de la función se reflejarán en el array original transmitido como argumento al llamar a la función.


Suavizado de datos

El suavizado de datos es un proceso consistente en eliminar el ruido de una serie temporal. El ruido puede ser causado por fluctuaciones aleatorias o eventos imprevistos. El suavizado de datos le permite reducir la influencia del ruido en el análisis y la previsión de las series temporales.

El lenguaje MQL5 ofrece varias funciones para el suavizado de datos. Por ejemplo, la función iMA() se puede usar para calcular una media móvil. Esto nos permite suavizar los datos, reducir el ruido y detectar tendencias. La función iRSI() se puede usar para calcular la fuerza relativa de un índice, que también se puede usar para suavizar los datos e identificar tendencias.

Ejemplo

void SmoothData(double& array[], int period)
{
    int size = ArraySize(array);
    double smoothed[size];
    double weight = 1.0 / period;

    for(int i = 0; i < size; i++) {
        double sum = 0.0;
        for(int j = i - period + 1; j <= i; j++) {
            if(j >= 0 && j < size) {
                sum += array[j];
            }
        }
        smoothed[i] = sum * weight;
    }

    ArrayCopy(smoothed, array, 0, 0, size);
}

Esta función usa una media móvil simple para suavizar los datos en el array. La variable de periodo especifica el número de elementos usados para calcular el valor medio en cada punto.

Dentro de la función, se crea un nuevo array suavizado para almacenar los datos suavizados. Luego iteraremos sobre cada elemento del array y calcularemos el valor promedio para el periodo especificado por la variable period.

Finalmente, el array "smoothed" se copia nuevamente en el array "array" utilizando la función ArrayCopy(). Tenga en cuenta que la función SmoothData() también aplica un array de datos por referencia (a través de & ), lo cual significa que los cambios realizados en el array dentro de la función se reflejarán en el array original transmitido como argumento al llamar a la función.


Valores ausentes

Los valores ausentes son valores que faltan en la serie temporal. Pueden ser causados ​​por errores en los datos de entrada o problemas en el proceso de recopilación de datos. Los valores ausentes pueden tener un impacto significativo en el análisis y el pronóstico de series temporales. Al procesar valores faltantes, deberemos decidir cómo rellenarlos. El lenguaje MQL5 ofrece varias funciones para procesar los valores ausentes.

La función iBarShift() se puede usar para encontrar el índice de la barra correspondiente a una fecha específica. Si falta un valor de serie temporal para una fecha determinada, podemos usar el valor de la barra anterior o rellenarlo con el valor promedio de la serie temporal para un periodo de tiempo determinado.

Ejemplo

void FillMissingValues(double& array[])
{
    int size = ArraySize(array);
    double last_valid = 0.0;

    for(int i = 0; i < size; i++) {
        if(IsNaN(array[i])) {
            array[i] = last_valid;
        }
        else {
            last_valid = array[i];
        }
    }
}

Esta función usa el método de "rellenado": reemplaza los valores que faltan con el valor válido anterior en el array. Para hacer esto, creamos una variable last_valid que almacena el último valor válido en el array e iteramos cada elemento del array. Si falta el valor actual ( NaN ), lo reemplazaremos con last_valid . Si no falta el valor, lo almacenaremos en last_valid y seguiremos iterando.

Tenga en cuenta que la función FillMissingValues() también aplica un array de datos por referencia (a través de & ), lo cual significa que los cambios realizados en el array dentro de la función se reflejarán en el array original transmitido como argumento al llamar a la función.


Interpolación

La interpolación es un método que sirve para completar los valores ausentes y que asume que los valores ausentes entre dos valores conocidos se pueden calcular usando alguna función. En MQL5, podemos usar la función MathSpline() para interpolar valores.

Obviamente, existen otras técnicas de procesamiento de datos que pueden ayudar a mejorar el análisis y la previsión de series temporales. Por ejemplo, la descomposición de series temporales puede ayudarnos a resaltar tendencias, ciclos y componentes estacionales. El análisis de clústeres y el análisis factorial pueden servirnos para identificar los factores que influyen en las series temporales.

En conclusión, el uso de métodos adicionales de procesamiento de datos puede mejorar significativamente el análisis y la previsión de series temporales. El lenguaje MQL5 ofrece varias funciones de procesamiento de datos que se pueden usar para eliminar valores atípicos, suavizar datos y procesar valores ausentes. Además, existen otros métodos de procesamiento de datos que se pueden aplicar para mejorar el análisis y la previsión de series temporales.

Ejemplo

double Interpolate(double& array[], double x)
{
    int size = ArraySize(array);
    int i = 0;

    // Find the two closest elements in the array
    while(i < size && array[i] < x) {
        i++;
    }

    if(i == 0 || i == size) {
        // x is out of the array range
        return 0.0;
    }

    // Calculate weights for interpolation
    double x0 = array[i-1];
    double x1 = array[i];
    double w1 = (x - x0) / (x1 - x0);
    double w0 = 1.0 - w1;

    // Interpolate value
    return w0 * array[i-1] + w1 * array[i];
}

La función Interpolate toma dos argumentos: una referencia a un array de números de coma flotante y un valor de x para interpolar. El algoritmo de interpolación consiste en encontrar los dos elementos más cercanos en el array, calcular los pesos para la interpolación y luego calcular el valor interpolado. Si el valor de x está fuera del rango del array, la función retornará 0.

Tenga en cuenta que la función Interpolate también aplica un array de datos por referencia (a través de & ), lo cual significa que los cambios realizados en el array dentro de la función se reflejarán en el array original transmitido como argumento al llamar a la función.


Tipos de señales preferibles para la transmisión a la red neuronal

Las señales son un elemento clave para el funcionamiento de las redes neuronales, pues representan los datos transmitidos a la red neuronal para su procesamiento y análisis. La selección del tipo correcto de señal para transmitir a una red neuronal puede influir en gran medida en su eficiencia y precisión. En este artículo, analizaremos los tipos de señales preferibles para la transmisión a una red neuronal.

Señales numéricas

Las señales numéricas son el tipo más común de señales usadas en las redes neuronales. Son valores numéricos que pueden ser procesados ​​y analizados por una red neuronal. Las señales numéricas pueden ser discretas o continuas: las discretas tienen un número finito de valores, mientras que las continuas tienen un número infinito de valores.

Imágenes

Las imágenes también son un tipo popular de señal usado en las redes neuronales. Estas suponen imágenes gráficas que pueden ser procesadas por una red neuronal. Las imágenes pueden ser en blanco y negro o en color. Para transferir imágenes a la red neuronal, estas deben convertirse a un formato numérico.

Señales de texto

Las señales de texto también se pueden usar para enviar datos a una red neuronal. Son líneas de texto que pueden ser procesadas y analizadas por una red neuronal. Las señales de texto pueden darse tanto en lenguajes naturales como en lenguajes de programación especiales.

Señales de audio

Las señales de audio también se pueden usar para enviar datos a una red neuronal. Son señales de audio que pueden ser procesadas y analizadas por una red neuronal, y pueden ser tanto de voz como de música.

Señales de vídeo

Las señales de vídeo suponen una secuencia de imágenes que pueden ser procesadas y analizadas por una red neuronal.

Señales sensoriales

Las señales sensoriales son un tipo importante de señales para la transmisión a una red neuronal en problemas de robótica y visión artificial, y pueden incluir los datos de sensores como giroscopios, acelerómetros, sensores de distancia y otros. Los datos se pueden utilizar para entrenar la red neuronal y que esta pueda analizar y responder al entorno.

Señales gráficas

Las señales gráficas suponen imágenes vectoriales o de mapa de bits que pueden ser procesadas y analizadas por una red neuronal. Se pueden utilizar para tareas relacionadas con los gráficos y el diseño, como el reconocimiento de caracteres y formas, la creación automática de dibujos, etc.

Series temporales

Las series temporales son una secuencia de números medidos a lo largo del tiempo. Se pueden usar para tareas relacionadas con el pronóstico, la predicción de tendencias y el análisis de datos temporales. Las redes neuronales se pueden utilizar en el procesamiento de series temporales para revelar patrones ocultos y predecir valores futuros.

¿Cómo podemos elegir el tipo de señal adecuado para transmitir a la red neuronal?

La elección del tipo apropiado de señal para transmitir a la red neuronal dependerá de la tarea específica y de los datos disponibles. Algunas tareas pueden demandar el uso de varios tipos de señales al mismo tiempo. Por ejemplo, una tarea de reconocimiento de voz puede implicar el uso de señales de audio y señales de texto al mismo tiempo.

A la hora de elegir el tipo de señal transmitida a la red neuronal, debemos tener en cuenta sus características, como el tamaño, la resolución, el formato, etc. Además, debemos posibilitar un preprocesamiento de datos adecuado, como la normalización, el filtrado, etc., para garantizar una calidad y precisión óptimas del procesamiento de datos por parte de la red neuronal.

En conclusión, elegir el tipo de señal adecuado para enviar a la red neuronal es un paso esencial para lograr resultados óptimos en tareas de aprendizaje automático. Podemos usar diferentes tipos de señales para entrenar redes neuronales según la tarea específica y los datos disponibles. La elección correcta del tipo de señal y el preprocesamiento de datos adecuado pueden ayudar a garantizar una precisión y un rendimiento óptimos de la red neuronal,

sin embargo, también se deben tener en cuenta las limitaciones de potencia informática y disponibilidad de datos. Algunos tipos de señales pueden ser más difíciles de procesar para la red neuronal, lo cual puede requerir más potencia de procesamiento y más datos de entrenamiento. Por lo tanto, debemos equilibrar la calidad y la disponibilidad de los datos a la hora de elegir el tipo de señal para el entrenamiento de redes neuronales.

En general, elegir el tipo correcto de señal a enviar a una red neuronal es un paso importante para lograr resultados óptimos en tareas de aprendizaje automático. Las redes neuronales pueden procesar varios tipos de señales: audio, vídeo, texto, datos sensoriales, datos gráficos y series temporales. La elección correcta del tipo de señal y el preprocesamiento de datos adecuado pueden ayudar a garantizar una precisión y un rendimiento óptimos de la red neuronal en una tarea en particular.


Práctica

En la práctica, hoy analizaremos varios asesores expertos basados ​​en nuestro perceptrón favorito. Transmitiremos los valores del indicador Accelerator Oscillator. Transmitiremos el valor del indicador con 4 velas y aplicaremos los métodos de normalización descritos anteriormente. Para que el experimento resulte más puro, compararemos los resultados de los asesores expertos con y sin transformación. En el asesor sin transformación, transmitiremos los valores del indicador directamente. 

Aquí ofreceremos todos los parámetros para la optimización y las pruebas forward, para no repetirnos más en el texto:

  • Mercado Fórex;
  • Pareja de divisas EURUSD;
  • Periodo H1;
  • StopLoss 300 y TakeProfit 600;
  • Optimización y modo de prueba "Solo precios de apertura" y "Máximo del criterio complejo". Es muy importante usar el modo "Máximo del criterio complejo", ya que ha mostrado resultados más estables y rentables en comparación con "Rentabilidad Máxima";
  • Rango de optimización 3 años. Del 2019.04.06 al 2022.04.06 . 3 años no es ningún criterio determinado. Puede probar más o menos por su cuenta;
  • Rango de prueba forward de 1 año. Del 2022.04.06 al 2023.04.06. Comprobamos todo basándonos en el algoritmo descrito en el artículo (Experimentos con redes neuronales (Parte 3): Uso práctico). Es decir, el comercio simultáneo de varios de los mejores resultados de optimización;
  • Ahora realizaremos la optimización 40 veces. Asimismo, aumentaremos dos veces en comparación con las pruebas anteriores y veremos los resultados. 
  • En todas las pruebas forward hemos utilizado simultáneamente 40 resultados de optimización. El valor se multiplica por 2 con respecto a las pruebas anteriores de los artículos;
  • Optimización de asesores expertos con perceptrón «Rápida (algoritmo genético)»;
  • Depósito inicial de 10000 unidades;
  • Apalancamiento 1:500.

Para la optimización, utilizaremos un pequeño programa de clic automático que escribí en Delphi. No puedo publicarlo aquí, pero lo enviaré a quien lo necesite por mensaje privado si me manda su correo electrónico. Esto funciona así:

  1. Introducimos el número deseado de optimizaciones.
  2. Situamos el cursor del ratón sobre el botón «Iniciar» del simulador de estrategias.
  3. Nos ocupamos de nuestra tarea.

La optimización finalizará tras los ciclos indicados y el programa se cerrará. El autoclicker reaccionará al cambio de color del botón «Iniciar». A continuación mostramos una captura de pantalla del programa. 

Autoclicker

Asesor Perceptron AC 4 SL TP:

Transmitimos los datos de los indicadores directamente sin utilizar la normalización. 

Resultados de la optimización:

Optimización


Optimización

Resultados de las pruebas forward:

Pruebas


Asesor perceptron AC 4 (Differentiation) SL TP:

Transmitimos los datos de los indicadores utilizando la normalización Min-Max. 

Resultados de la optimización:

Optimización


Optimización

Resultados de las pruebas forward:

Pruebas



Conclusión

La lista de archivos adjuntos:

  1. perceptron AC 4 SL TP - opt - asesor de perceptrón para optimizar el indicador AC sin utilizar normalización;
  2. perceptron AC 4 SL TP - trade - asesor optimizado basado en un perceptrón usando como base el indicador AC sin utilizar normalización;
  3. perceptron AC 4 (Differentiation) SL TP - opt - asesor basado en un perceptrón para realizar la optimización usando como base el indicador AC utilizando la diferenciación para la normalización;
  4. perceptron AC 4 (Differentiation) SL TP - trade - asesor optimizado basado en un perceptrón sobre la base del indicador AC usando diferenciación para la normalización;

La normalización reduce la influencia de los valores atípicos en los datos, lo cual puede ayudar a evitar el sobreajuste del modelo. Los datos correctamente normalizados permiten que la red "comprenda" mejor las relaciones entre los parámetros, lo cual ayuda a realizar predicciones más precisas, mejorando la calidad del modelo.

En el artículo, hemos analizado varios métodos de normalización, pero estas no son las únicas formas de procesar datos para mejorar el entrenamiento de las redes neuronales. Cada caso específico requiere un enfoque individual, y el método de normalización debe seleccionarse según las características de los datos y la tarea específica.

En general, la normalización de los parámetros de entrada supone un paso importante en el proceso de formación de redes neuronales. Los datos procesados ​​incorrectamente pueden generar resultados deficientes e influir negativamente en el rendimiento del modelo. Los datos correctamente normalizados pueden mejorar la estabilidad y la tasa de convergencia del entrenamiento, además de generar predicciones más precisas y mejorar la calidad del modelo.

Gracias por su atención, amigos, ¡y hasta pronto!



Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/12459

Archivos adjuntos |
EA.zip (199.53 KB)
Aprendiendo de las compañías de Prop-Trading (Parte 1) - Introducción Aprendiendo de las compañías de Prop-Trading (Parte 1) - Introducción
En este artículo introductorio, compartiremos algunas de las lecciones que se pueden aprender de las pruebas realizadas en las empresas de prop-trading. Esto resulta especialmente actual para los principiantes y aquellos que luchan por encontrar su lugar en el mundo del trading. El siguiente artículo se centrará en la implementación del código.
Teoría de Categorías en MQL5 (Parte 6): Productos fibrados monomórficos y coproductos fibrados epimórficos Teoría de Categorías en MQL5 (Parte 6): Productos fibrados monomórficos y coproductos fibrados epimórficos
La teoría de categorías es un apartado diverso y en expansión de las matemáticas, que solo recientemente ha comenzado a ser trabajado por la comunidad MQL5. Esta serie de artículos tiene por objetivo repasar algunos de sus conceptos para crear una biblioteca abierta y seguir usando este maravilloso apartado en la creación de estrategias comerciales.
Experimentos con redes neuronales (Parte 6): El perceptrón como herramienta autosuficiente de predicción de precios Experimentos con redes neuronales (Parte 6): El perceptrón como herramienta autosuficiente de predicción de precios
Ejemplo de utilización de un perceptrón como herramienta autónoma de predicción de precios. En el artículo exploraremos los conceptos generales y veremos un sencillo asesor experto ya preparado, así como los resultados de su optimización.
Cómo conectar MetaTrader 5 a PostgreSQL Cómo conectar MetaTrader 5 a PostgreSQL
Este artículo describiremos cuatro métodos para conectar el código MQL5 a una base de datos de Postgres y ofreceremos una guía paso a paso para configurar un entorno de desarrollo para uno de ellos, la API REST, utilizando el Subsistema de Windows para Linux (WSL). Asimismo, mostraremos una aplicación demostrativa de la API con el código MQL5 correspondiente para insertar datos y consultas a las tablas correspondientes, así como un asesor demo para usar estos datos.