English Русский 中文 Español Deutsch 日本語
preview
Experimentos com redes neurais (Parte 5): Normalização de parâmetros de entrada para alimentar a rede neural

Experimentos com redes neurais (Parte 5): Normalização de parâmetros de entrada para alimentar a rede neural

MetaTrader 5Sistemas de negociação | 28 julho 2023, 09:30
376 0
Roman Poshtar
Roman Poshtar

Introdução

Boa tarde, caros usuários da comunidade MQL5. Após uma pequena reflexão sobre os resultados de nossos experimentos anteriores, surgiu a tarefa de melhorar o treinamento e, por fim, a lucratividade dos Expert Advisors que desenvolvemos anteriormente.

Hoje falaremos sobre a importância do sinal, especialmente sobre como alimentar uma rede neural com dados para análise e previsão de resultados futuros. Lembre-se de que esse é um componente muito importante de uma rede neural. Ou melhor, o mais importante de todos. Quero transmitir aos meus leitores a importância de compreender os sinais para evitar mal-entendidos infelizes, como "usei a biblioteca mais recente e ela não funciona". Nos artigos anteriores, aplicamos alguns métodos interessantes, hoje tentaremos passar os dados do indicador normalizando seus valores.

Como sempre, darei a você uma explicação detalhada e não muito rebuscada. Acredito que todos poderão entendê-la.


A importância da normalizar os parâmetros de entrada para alimentar a rede neural

A normalização dos parâmetros de entrada é uma etapa importante no processo de preparação de dados para o treinamento de redes neurais. Esse processo ajusta os dados de entrada a um determinado intervalo de valores, o que ajuda a melhorar a estabilidade e a taxa de convergência do treinamento.

Neste artigo, veremos por que a normalização é uma etapa importante no treinamento de redes neurais e quais métodos de normalização podem ser usados.

O que implica a normalização dos parâmetros de entrada?

A normalização dos parâmetros de entrada consiste em transformar os dados de entrada para que tenham um determinado intervalo de valores. Para conseguir isso, costumam ser usados dois métodos principais de normalização: normalização por média e desvio padrão (normalização z) e normalização por mínimo e máximo (normalização min-max).

A normalização Z usa a média e o desvio padrão para centralizar e dimensionar os dados. Quando se faz isso, cada valor é subtraído da média e dividido pelo desvio padrão. Já a normalização mín-máx usa os valores mínimo e máximo para dimensionar os dados em um determinado intervalo.

Por que a normalização dos parâmetros de entrada é importante?

A normalização dos parâmetros de entrada é importante para melhorar a estabilidade e a taxa de convergência do aprendizado. Se os dados de entrada não forem normalizados, alguns parâmetros poderão variar muito em termos de valores, o que pode causar problemas no treinamento da rede neural. Por exemplo, os gradientes podem se tornar muito grandes ou muito pequenos, resultando em problemas de otimização e baixa precisão da previsão.

A normalização também permite acelerar o processo de aprendizado, uma vez que a convergência do algoritmo de otimização pode ser melhorada. Além disso, dados devidamente normalizados podem ajudar a evitar o problema de sobreajuste (overfitting) que pode ocorrer se os dados de entrada não forem representativos o suficiente.

Quais métodos de normalização podem ser usados?

Métodos de normalização podem variar de acordo com o tipo de dados e a tarefa que estamos tentando resolver. Por exemplo, para imagens, são frequentemente utilizados métodos de normalização como a normalização pela média e desvio padrão (normalização z) e a normalização pelo mínimo e máximo (normalização min-max). No entanto, para outros tipos de dados, como sinais de áudio ou dados de texto, pode ser mais eficiente utilizar outros métodos de normalização.

Para sinais de áudio, por exemplo, é comum usar a normalização de amplitude máxima, onde todos os valores do sinal são escalados para o intervalo de -1 a 1. Para dados de texto, pode ser útil normalizar com base no número de palavras ou caracteres em uma frase.

Além disso, em alguns casos, pode ser útil normalizar não apenas os dados de entrada, mas também as variáveis alvo. Por exemplo, em tarefas de regressão, onde a variável alvo possui uma ampla faixa de valores, a normalização da variável alvo pode ser útil para melhorar a estabilidade do treinamento e a precisão das previsões.

A normalização dos parâmetros de entrada é uma etapa importante no processo de preparação de dados para o treinamento de redes neurais. Esse processo ajusta os dados de entrada a um determinado intervalo de valores, o que ajuda a melhorar a estabilidade e a taxa de convergência do treinamento. Dependendo do tipo de dados e do problema que estamos tentando resolver, podem ser usados diferentes métodos de normalização. Além disso, em alguns casos, pode ser útil normalizar não apenas os dados de entrada, mas também as variáveis alvo.


Métodos de normalização

Normalização min-max

No aprendizado de máquina, a normalização é uma etapa crucial no pré-processamento dos dados que melhora a estabilidade e a velocidade de convergência do treinamento. Um dos métodos de normalização mais comuns é a normalização min-max, que permite ajustar valores de dados no intervalo de 0 a 1. Neste artigo, veremos como a normalização min-max pode ser utilizada com séries temporais.

As séries temporais são uma sequência de valores medidos em diferentes pontos no tempo. Alguns exemplos de séries temporais incluem dados sobre temperatura, preços de ações ou número de vendas de mercadorias. As séries temporais podem ser empregadas para prever valores futuros, analisar tendências e padrões, ou detectar anomalias.

As séries temporais podem ter uma variedade de valores e as mudanças ao longo do tempo podem não ser uniformes. Por exemplo, os preços das ações podem variar amplamente e flutuar com base na sazonalidade, notícias e outros fatores. Para uma análise e previsão efetiva de séries temporais, é necessário ajustar os valores em um determinado intervalo.

O método de normalização min-max normaliza valores para um intervalo de 0 a 1 escalando os valores de acordo com os valores mínimo e máximo. A fórmula para a normalização min-max é a seguinte:

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

onde x é o valor dos dados, x_min é o valor mínimo em todo o conjunto de dados, x_max é o valor máximo em todo o conjunto de dados, x_norm é o valor normalizado.

A aplicação da normalização min-max a uma série temporal pode ajudar a fazer com que os dados fiquem em um intervalo comum de valores e, assim, simplificar a análise. Por exemplo, se tivermos dados de temperatura que variam de -30 a +30 graus Celsius, podemos aplicar a normalização min-max para fazer com que os valores fiquem em um intervalo de 0 a 1. Isso nos permitirá comparar os valores ao longo do tempo e identificar tendências e anomalias.

No entanto, ao aplicar a normalização min-max às séries temporais, é necessário levar em consideração seus características e impacto nos dados. Primeiro, seu uso pode levar à perda de informações sobre a distribuição de valores dentro do intervalo. Por exemplo, se houver valores atípicos ou valores extremos no conjunto de dados, eles serão convertidos em 0 ou 1 e perdidos na análise. Nesse caso, métodos alternativos de normalização podem ser usados, como a normalização Z-score.

Em segundo lugar, ao usar a normalização min-max, é necessário levar em consideração a dinâmica de dados. Se os dados tiverem uma dinâmica variável, a normalização pode distorcer os padrões e gerar anomalias temporais. Nesse caso, pode-se aplicar a normalização local, onde são determinados os valores mínimo e máximo para cada grupo de dados dentro de um determinado período de tempo.

Em terceiro lugar, ao usar a normalização min-max, é necessário levar em consideração a influência da amostra nos resultados da análise. Se a amostra de observações não estiver ajustada ou contiver valores atípicos, a normalização poderá conduzir a conclusões errôneas. Nesse caso, é possível usar métodos alternativos de processamento de dados, como remoção de valores atípicos ou suavização de dados.

Em conclusão, o método de normalização min-max é um dos métodos de normalização mais comuns em aprendizado de máquina e pode ser aplicado efetivamente a séries temporais para ajustar valores em um intervalo comum. Entretanto, ao usar esse método, é necessário levar em conta as características dos dados e aplicar métodos de processamento adicionais para evitar distorções na análise e previsão de séries temporais.

Exemplo:

int OnInit()
  {

// объявляем и инициализируем массив
double data_array[] = {1.2, 2.3, 3.4, 4.5, 5.6};

// находим минимальное и максимальное значение в массиве
double min_value = ArrayMinimum(data_array, 0, ArraySize(data_array)-1);
double max_value = ArrayMaximum(data_array, 0, ArraySize(data_array)-1);

// создаем массив для хранения результата нормализации
double norm_array[ArraySize(data_array)];

// нормализуем массив
for(int i = 0; i < ArraySize(data_array); i++) {
    norm_array[i] = (data_array[i] - min_value) / (max_value - min_value);
}

// выводим результат
for(int i = 0; i < ArraySize(data_array)-1; i++) {
Print("Исходный массив: ", data_array[i]);
Print("Результат Min-Max нормализации: ", norm_array[i]);
}

return(INIT_SUCCEEDED);
}

Este código cria o array data_array, que contém cinco números com ponto flutuante. Em seguida, encontra os valores mínimo e máximo no array usando as funções ArrayMinimum() e ArrayMaximum() , cria um novo array norm_array para armazenar o resultado da normalização e o preenche calculando para cada elemento (data_array[i] - min_value) / (max_value - min_value). Finalmente, o resultado é exibido na tela usando a função Imprimir().

Resultado:

2023.04.07 13:22:32.937 11111111111111 (EURUSD,H1)      Исходный массив: 1.2
2023.04.07 13:22:32.937 11111111111111 (EURUSD,H1)      Результат Min-Max нормализации: 0.39999999999999997
2023.04.07 13:22:32.937 11111111111111 (EURUSD,H1)      Исходный массив: 2.3
2023.04.07 13:22:32.937 11111111111111 (EURUSD,H1)      Результат Min-Max нормализации: 0.7666666666666666
2023.04.07 13:22:32.937 11111111111111 (EURUSD,H1)      Исходный массив: 3.4
2023.04.07 13:22:32.937 11111111111111 (EURUSD,H1)      Результат Min-Max нормализации: 1.1333333333333333
2023.04.07 13:22:32.937 11111111111111 (EURUSD,H1)      Исходный массив: 4.5
2023.04.07 13:22:32.937 11111111111111 (EURUSD,H1)      Результат Min-Max нормализации: 1.5


Normalização Z

As séries temporais são uma ferramenta importante na análise de dados, especialmente em economia, finanças, meteorologia, ciência dos materiais e outros campos. Um dos principais métodos de pré-processamento de séries temporais é a normalização Z, que pode ajudar a melhorar a qualidade da análise de dados.

A normalização Z é um método para centralizar e dimensionar séries temporais. Consiste em transformar a série temporal de forma que o valor médio da série temporal seja igual a zero e o desvio padrão igual a um. Isso pode ser útil para comparar séries temporais, além de remover os efeitos de sazonalidade e tendências.

O processo de normalização Z de séries temporais inclui as seguintes etapas:

  1. Cálculo da média da série temporal.
  2. Cálculo do desvio padrão da série temporal.
  3. Para cada elemento da série temporal, cálculo da diferença entre seu valor e o valor médio da série temporal.
  4. Divisão de cada diferença pelo desvio padrão.

Os valores resultantes terão uma média igual a zero e um desvio padrão igual a um.

Vantagens da normalização Z:

  1. Aprimoramento da qualidade da análise de dados. A normalização Z pode ajudar a remover a influência da sazonalidade e das tendências, o que pode melhorar a qualidade da análise de dados.
  2. Facilidade de uso. A normalização Z é fácil de usar e pode ser aplicada a diferentes tipos de séries temporais.
  3. Utilidade para comparação de séries temporais. A normalização Z permite que as séries temporais sejam comparadas entre si, removendo a influência das diferentes escalas e unidades de medida.

Porém, a normalização Z também tem algumas limitações:

  1. Não é adequado para séries temporais com valores extremos. Se a série temporal contiver valores extremos, a normalização Z pode resultar em resultados distorcidos.
  2. Não é adequado para séries temporais não estacionárias. Se a série temporal for não estacionária (ou seja, com tendências ou sazonal), a normalização Z pode eliminar essas características, o que pode resultar em uma análise incorreta dos dados.
  3. Ela não garante a normalidade da distribuição. A normalização Z pode ajudar a normalizar a distribuição de uma série temporal, mas não garante que a distribuição seja normal.

Apesar dessas limitações, a normalização Z é uma importante técnica de pré-processamento de séries temporais que pode ajudar a melhorar a qualidade da análise de dados. Ela pode ser usada em vários campos, incluindo economia, finanças, meteorologia e ciência dos materiais.

Por exemplo, em economia e finanças, a normalização Z pode ser usada para comparar o desempenho de diferentes ativos ou carteiras e para analisar risco e volatilidade.

Na meteorologia, a normalização Z pode ajudar a remover a influência da sazonalidade e das tendências da análise de dados meteorológicos, como temperatura ou precipitação.

Na ciência dos materiais, a normalização Z pode ser usada para análise de séries temporais de propriedades de materiais, como expansão térmica ou propriedades magnéticas.

Em conclusão, a normalização Z é um importante método de pré-processamento de séries temporais que pode ajudar a melhorar a qualidade da análise de dados em vários campos. Apesar de algumas limitações, a normalização Z é fácil de usar e pode ser aplicada a diferentes tipos de séries temporais.

Exemplo:

int OnInit()
  {

// объявляем и инициализируем массив
double data_array[] = {1.2, 2.3, 3.4, 4.5, 5.6};

// находим среднее значение и стандартное отклонение в массиве
double mean_value = ArrayAverage(data_array, 0, ArraySize(data_array)-1);
double std_value = ArrayStdDev(data_array, 0, ArraySize(data_array)-1);

// создаем массив для хранения результата нормализации
double norm_array[ArraySize(data_array)];

// нормализуем массив
for(int i = 0; i < ArraySize(data_array); i++) {
    norm_array[i] = (data_array[i] - mean_value) / std_value;
}

// выводим результат
for(int i = 0; i < ArraySize(data_array)-1; i++) {
Print("Исходный массив: ", data_array[i]);
Print("Результат Z-нормализации: ", 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);

    // Определение индекса последнего элемента
    int end_pos = count < 0 ? size - 1 : start_pos + count - 1;
    end_pos = end_pos >= size ? size - 1 : end_pos;

    // Вычисление суммы элементов
    for(int i = start_pos; i <= end_pos; i++) {
        sum += array[i];
    }

    // Вычисление среднего значения
    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);

    // Определение индекса последнего элемента
    int end_pos = count < 0 ? size - 1 : start_pos + count - 1;
    end_pos = end_pos >= size ? size - 1 : end_pos;

    // Вычисление суммы квадратов отклонений от среднего
    for(int i = start_pos; i <= end_pos; i++) {
        sum += MathPow(array[i] - mean, 2);
    }

    // Вычисление стандартного отклонения
    double std_dev = MathSqrt(sum / (end_pos - start_pos + 1));
    return (std_dev);
}

Este código cria o array data_array, que contém cinco números com ponto flutuante. Em seguida, encontra a média e o desvio padrão no array usando as funções ArrayAverage() e ArrayStdDev(), cria um novo array norm_array para armazenar o resultado da normalização e o preenche calculando para cada elemento (data_array[i] - mean_value) / std_value. Finalmente, o resultado é exibido na tela usando a função Imprimir().

Resultado:

2023.04.07 13:51:57.501 11111111111111 (EURUSD,H1)      Исходный массив: 1.2
2023.04.07 13:51:57.501 11111111111111 (EURUSD,H1)      Результат Z-нормализации: -1.3416407864998738
2023.04.07 13:51:57.501 11111111111111 (EURUSD,H1)      Исходный массив: 2.3
2023.04.07 13:51:57.501 11111111111111 (EURUSD,H1)      Результат Z-нормализации: -0.4472135954999581
2023.04.07 13:51:57.501 11111111111111 (EURUSD,H1)      Исходный массив: 3.4
2023.04.07 13:51:57.501 11111111111111 (EURUSD,H1)      Результат Z-нормализации: 0.44721359549995776
2023.04.07 13:51:57.501 11111111111111 (EURUSD,H1)      Исходный массив: 4.5
2023.04.07 13:51:57.501 11111111111111 (EURUSD,H1)      Результат Z-нормализации: 1.3416407864998736


Diferenciação

A diferenciação de séries temporais é um método importante de análise de dados que permite remover a tendência e/ou a sazonalidade de uma série, tornando-a mais estacionária. Neste artigo, veremos o que é diferenciação, como aplicá-la e quais benefícios ela pode proporcionar.

O que é diferenciação de séries temporais?

A diferenciação é o processo pelo qual são encontradas as diferenças entre valores sucessivos em uma série temporal. O número de diferenças a serem encontradas depende do grau de estacionariedade que se deseja alcançar. Normalmente, uma ou duas diferenças são suficientes para eliminar a tendência ou a sazonalidade. Uma etapa de diferença tem a seguinte aparência:

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

onde y'(t) é a diferença entre o valor atual da série e o valor anterior.

Se a série for não estacionária, então, após a diferenciação, seus valores se tornam mais aleatórios, sem tendências visíveis ou sazonalidade. Isso pode ajudar a destacar características mais óbvias da série temporal, como ciclos ou volatilidade.

Como aplicar a diferenciação de séries temporais?

Siga estas etapas para diferenciar a série temporal:

  1. Determine se a série é não estacionária. Se a série tiver uma tendência ou sazonalidade, ela é não estacionária.
  2. Determine o grau de diferenciação necessário para obter a estacionariedade. Se você quiser remover apenas a tendência, uma diferença é suficiente. Se quiser remover a sazonalidade, talvez sejam necessárias duas ou mais diferenças.
  3. Aplique uma transformação de diferença à série. Use a fórmula y'(t) = y(t) - y(t-1) para encontrar a primeira diferença. Se precisar encontrar a segunda diferença, aplique a fórmula para y'(t).
  4. Verifique se a série é estacionária. Para fazer isso, você pode usar testes estatísticos de estacionariedade, como o teste Dickey-Fuller.
  5. Se a série for não estacionária, repita o processo de diferenciação até que a série se torne estacionária.

Quais são os benefícios de diferenciar séries temporais?

A diferenciação de séries temporais pode oferecer várias vantagens:

  1. Melhoria da previsão: Quando uma série temporal é estacionária, a previsão se torna mais fácil porque as propriedades estatísticas da série não mudam com o tempo.
  2. Eliminação de tendências: Ao diferenciar as séries, a tendência linear é removida, o que torna a série mais estacionária e melhora sua análise.
  3. Eliminação da sazonalidade: Ao usar várias etapas de diferença, a sazonalidade pode ser removida da série temporal, tornando-a mais estacionária.
  4. Eliminação de ruído: A diferenciação da série remove os componentes de baixa frequência (tendência e sazonalidade), o que pode ajudar a remover o ruído introduzido por esses componentes.
  5. Melhoria da interpretação: Quando a série é estacionária, ela pode ser analisada por métodos estatísticos clássicos, o que torna a interpretação dos dados mais fácil e compreensível.

No entanto, a diferenciação também pode ter desvantagens. Por exemplo, se você diferenciar uma série muitas vezes, ela pode perder sinais importantes, levando a conclusões incorretas. Além disso, a diferenciação pode introduzir ruído adicional na série.

A diferenciação de séries temporais é uma técnica útil de análise de dados que remove tendência e/ou sazonalidade de uma série, tornando-a mais estacionária. Isso melhora a previsão, remove o ruído e melhora a interpretação dos dados. No entanto, a diferenciação também pode ter desvantagens, por isso deve ser usada com cautela e em combinação com outros métodos de análise de dados.

Exemplo:

int OnInit()
  {

// объявляем и инициализируем массив
double data_array[] = {1.2, 2.3, 3.4, 4.5, 5.6};

// создаем массив для хранения результата дифференцирования
double diff_array[ArraySize(data_array)];

// дифференцируем массив
for(int i = 0; i < ArraySize(data_array)-1; i++) {
    diff_array[i] = data_array[i+1] - data_array[i];
}

// выводим результат
for(int i = 0; i < ArraySize(data_array)-1; i++) {
Print("Исходный массив: ", data_array[i]);
Print("Результат дифференцирования: ", diff_array[i]);
}

return(INIT_SUCCEEDED);
}

Este código cria o array data_array, que contém cinco números com ponto flutuante. Em seguida, cria um novo array diff_array para armazenar o resultado da diferenciação e preenchê-lo subtraindo cada elemento i+1 do elemento i em data_array . Finalmente, o resultado é exibido na tela usando a função Imprimir().

Resultado:

2023.04.07 13:13:50.650 11111111111111 (EURUSD,H1)      Исходный массив: 1.2
2023.04.07 13:13:50.650 11111111111111 (EURUSD,H1)      Результат дифференцирования: 1.0999999999999999
2023.04.07 13:13:50.650 11111111111111 (EURUSD,H1)      Исходный массив: 2.3
2023.04.07 13:13:50.650 11111111111111 (EURUSD,H1)      Результат дифференцирования: 1.1
2023.04.07 13:13:50.650 11111111111111 (EURUSD,H1)      Исходный массив: 3.4
2023.04.07 13:13:50.650 11111111111111 (EURUSD,H1)      Результат дифференцирования: 1.1
2023.04.07 13:13:50.650 11111111111111 (EURUSD,H1)      Исходный массив: 4.5
2023.04.07 13:13:50.650 11111111111111 (EURUSD,H1)      Результат дифференцирования: 1.0999999999999996


Transformação logarítmica

A transformação logarítmica de série temporal é uma técnica de transformação de dados usada para melhorar as propriedades de uma série antes da análise e modelagem. Este método é especialmente útil quando os dados têm uma alta variabilidade ou os valores brutos estão em uma ampla faixa.

O que é uma transformação logarítmica?

Ela é o processo de aplicação de uma função logarítmica a cada valor em uma série temporal. A função logarítmica é usada para comprimir os valores de uma série, principalmente se estiverem em um intervalo amplo. O uso do logaritmo reduz a variabilidade da série porque suaviza os picos e as quedas nos dados, tornando-os menos pronunciados.

Quando a transformação logarítmica é útil?

A transformação logarítmica pode ser útil nas seguintes situações:

  1. Quando os dados têm alta variabilidade: Se os dados tiverem alta variabilidade, uma transformação logarítmica pode suavizá-los e torná-los mais previsíveis.
  2. Quando os dados estão em um intervalo amplo: Se os dados estiverem em uma ampla faixa, uma transformação logarítmica pode comprimi-los e melhorar sua interpretação.
  3. Quando os dados têm uma tendência exponencial: Se os dados tiverem uma tendência exponencial, uma transformação logarítmica pode torná-los lineares, o que os torna mais fáceis de analisar e modelar.
  4. Quando os dados não são normalmente distribuídos: Se os dados não forem normalmente distribuídos, uma transformação logarítmica pode torná-los mais normais.

Exemplo de aplicação da transformação logarítmica:

Digamos que temos uma série temporal que representa as vendas diárias de uma loja ao longo de vários anos. Como as vendas podem ser muito variáveis ​​e irregulares, podemos aplicar uma transformação de logarítmica para suavizar os dados e torná-los mais previsíveis.

Continuando com nosso exemplo, podemos aplicar uma transformação logarítmica à nossa série temporal de vendas. Para fazer isso, aplicaremos uma função logarítmica a cada valor de nossa série.

Por exemplo, se tivermos uma série de vendas {100, 200, 300, 400}, podemos aplicar uma transformação de logarítmica para obter {log(100), log(200), log(300), log(400)} ou apenas {2 , 2.3, 2.5, 2.6} usando o logaritmo natural.

Como podemos ver no exemplo, a transformação logarítmica comprimiu os valores da série, o que a tornou mais conveniente para análise e modelagem. Isso nos permite entender melhor as tendências de vendas e fazer previsões mais precisas.

No entanto, não se esqueça que a transformação logarítmica não é um método universal e nem sempre é adequado para todos os tipos de dados. Além disso, ao aplicar a transformação logarítmica, é preciso ter cuidado para não se esquecer de voltar à escala original dos dados, se necessário.

Em conclusão, a transformação logarítmica é um método útil para transformar séries temporais para melhorar suas propriedades antes da análise e modelagem. Pode ser especialmente útil para dados com alta variabilidade ou uma faixa ampla. No entanto, ao utilizá-lo, deve-se estar ciente de suas limitações e interpretar corretamente os resultados.

Exemplo:

int OnInit()
  {

// объявляем и инициализируем массив
double data_array[] = {1.2, 2.3, 3.4, 4.5, 5.6};

// создаем массив для хранения результата нормализации
double norm_array[ArraySize(data_array)];

// нормализуем массив
LogTransform(data_array, norm_array);

// выводим результат
for(int i = 0; i < ArraySize(data_array)-1; i++) {
Print("Исходный массив: ", data_array[i]);
Print("Результат логарифмического преобразования: ", 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]);
    }
}

A função LogTransform() é usada para transformar logaritmicamente o array de dados array1 e armazenar o resultado no array array2.

O algoritmo funciona da seguinte forma: a função MathLog10() é usada para converter cada elemento de array1 em um logaritmo de base 10, e o resultado é armazenado no elemento correspondente de array2 .

Observe que a função LogTransform() aceita arrays de dados por referência (via & ), o que significa que as alterações feitas no array2 dentro da função serão refletidas no array original passado como argumento quando a função for chamada.

Resultado:

2023.04.07 14:21:22.374 11111111111111 (EURUSD,H1)      Исходный массив: 1.2
2023.04.07 14:21:22.374 11111111111111 (EURUSD,H1)      Результат логарифмического преобразования: 0.07918124604762482
2023.04.07 14:21:22.374 11111111111111 (EURUSD,H1)      Исходный массив: 2.3
2023.04.07 14:21:22.374 11111111111111 (EURUSD,H1)      Результат логарифмического преобразования: 0.36172783601759284
2023.04.07 14:21:22.374 11111111111111 (EURUSD,H1)      Исходный массив: 3.4
2023.04.07 14:21:22.374 11111111111111 (EURUSD,H1)      Результат логарифмического преобразования: 0.5314789170422551
2023.04.07 14:21:22.374 11111111111111 (EURUSD,H1)      Исходный массив: 4.5
2023.04.07 14:21:22.374 11111111111111 (EURUSD,H1)      Результат логарифмического преобразования: 0.6532125137753437


Métodos de processamento adicionais para evitar distorções na análise e previsão de séries temporais

As séries temporais são amplamente utilizadas para análise e previsão em vários campos, como economia, finanças, ciência do clima, etc. No entanto, os dados do mundo real geralmente contêm distorções, como valores atípicos, valores ausentes ou ruídos que podem afetar a precisão da análise e previsão de séries temporais. Neste artigo, consideraremos métodos de processamento adicionais que ajudarão a evitar distorções na análise e previsão de séries temporais.

Removendo valores atípicos

Os valores atípicos (outliers) são valores muito diferentes do restante dos valores da série. Eles podem ser causados ​​por erros de medição, erros de entrada de dados ou eventos imprevistos, como crises ou acidentes. A remoção desses valores da série temporal pode melhorar a qualidade da análise e previsão.

A linguagem MQL5 fornece várias funções para remover valores atípicos. Por exemplo, a função iqr() determina o intervalo interquartílico e calcula os limites atípicos. A função MODE_OUTLIERS pode ser usada para determinar os valores atípicos com base em um valor de tomada de decisão. Essas funções podem ser usadas em combinação com outras para remover esses valores discrepantes.

Exemplo:

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

    // Определение индекса последнего элемента
    int end_pos = count < 0 ? size - 1 : start_pos + count - 1;
    end_pos = end_pos >= size ? size - 1 : end_pos;

    // Вычисление суммы элементов
    for(int i = start_pos; i <= end_pos; i++) {
        sum += array[i];
    }

    // Вычисление среднего значения
    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);

    // Определение индекса последнего элемента
    int end_pos = count < 0 ? size - 1 : start_pos + count - 1;
    end_pos = end_pos >= size ? size - 1 : end_pos;

    // Вычисление суммы квадратов отклонений от среднего
    for(int i = start_pos; i <= end_pos; i++) {
        sum += MathPow(array[i] - mean, 2);
    }

    // Вычисление стандартного отклонения
    double std_dev = MathSqrt(sum / (end_pos - start_pos + 1));
    return (std_dev);
}

A função RemoveOutliers() usa a média e o desvio padrão para determinar os valores atípicos no array . Se um elemento do array estiver fora do intervalo de dois desvios padrão em relação ao valor médio, ele será considerado um valor atípico e será substituído pelo valor médio.

Observe que a função RemoveOutliers() também aceita um array de dados por referência (via & ), o que significa que as alterações feitas no array dentro da função serão refletidas no array original passado como argumento quando a função for chamada.


Suavização de dados

A suavização de dados é o processo de remoção de ruído de uma série temporal. O ruído pode ser causado por flutuações aleatórias ou eventos imprevistos. A suavização de dados permite reduzir o impacto do ruído na análise e previsão de séries temporais.

A linguagem MQL5 fornece várias funções para suavização de dados. Por exemplo, a função iMA() pode ser usada para calcular uma média móvel. Isso permite suavizar os dados, reduzir o ruído e detectar tendências. A função iRSI() pode ser usada para calcular a força relativa de um índice, que também pode ser usada para suavizar dados e identificar tendências.

Exemplo:

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 função usa uma média móvel simples para suavizar os dados no array. A variável period especifica o número de elementos usados ​​para calcular o valor médio em cada ponto.

Um novo array smoothed é criado dentro da função, onde os dados suavizados são armazenados. Em seguida, iteramos cada elemento do array e calculamos o valor médio para o período especificado pela variável period .

Por fim, o array smoothed é copiado de volta para o array usando a função ArrayCopy(). Observe que a função SmoothData() também aceita um array de dados por referência (via & ), o que significa que as alterações feitas no array dentro da função serão refletidas no array original passado como argumento quando a função for chamada.


Valores ausentes

Valores ausentes são valores que estão faltando na série temporal. Eles podem ser causados ​​por erros de entrada de dados ou problemas no processo de coleta de dados. Valores ausentes podem ter um impacto significativo na análise e previsão de séries temporais. Ao manusear valores ausentes, é necessário decidir como preenchê-los. A linguagem MQL5 fornece várias funções para lidar com valores ausentes.

A função iBarShift() pode ser usada para encontrar o índice de barra correspondente a uma data específica. Se faltar um valor de série temporal para uma determinada data, você pode usar o valor da barra anterior ou preenchê-lo com o valor médio da série temporal para um determinado período de tempo.

Exemplo:

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 função usa o método "preenchimento", que substitui quaisquer valores ausentes pelo valor válido anterior no array. Para fazer isso, criamos uma variável last_valid que armazena o último valor válido no array e percorre cada elemento do array. Se o valor atual estiver faltando ( NaN ), nós o substituímos por last_valid. Se o valor não estiver faltando, nós o armazenamos em last_valid e continuamos iterando.

Observe que a função FillMissingValues() também aceita um array de dados por referência (via & ), o que significa que as alterações feitas no array dentro da função serão refletidas no array original passado como argumento quando a função for chamada.


Interpolação

A interpolação é um método de preenchimento de valores ausentes que assume que os valores ausentes entre dois valores conhecidos podem ser calculados usando alguma função. Em MQL5, você pode usar a função MathSpline() para interpolar valores.

Obviamente, existem outras técnicas de processamento de dados que podem ajudar a melhorar a análise e a previsão de séries temporais. Por exemplo, a decomposição de séries temporais pode ajudar a destacar tendências, ciclos e componentes sazonais. A análise de cluster e a análise fatorial podem ajudar a identificar os fatores que influenciam as séries temporais.

Em conclusão, o uso de métodos adicionais de processamento de dados pode melhorar significativamente a análise e previsão de séries temporais. A linguagem MQL5 fornece várias funções de processamento de dados que podem ser usadas para remover valores atípicos, suavizar dados e manusear valores ausentes. Além disso, existem outros métodos de processamento de dados que podem ser aplicados para melhorar a análise e previsão de séries temporais.

Exemplo:

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

    // Находим два ближайших элемента в массиве
    while(i < size && array[i] < x) {
        i++;
    }

    if(i == 0 || i == size) {
        // x находится за пределами диапазона массива
        return 0.0;
    }

    // Вычисляем веса для интерполяции
    double x0 = array[i-1];
    double x1 = array[i];
    double w1 = (x - x0) / (x1 - x0);
    double w0 = 1.0 - w1;

    // Интерполируем значение
    return w0 * array[i-1] + w1 * array[i];
}

A função Interpolar adota dois argumentos: uma referência a um array de números de ponto flutuante e um valor x a ser interpolado. O algoritmo de interpolação envolve encontrar os dois elementos mais próximos no array, calcular os pesos para interpolação e, em seguida, calcular o valor interpolado. Se o valor x estiver fora do intervalo do array, a função retornará 0.

Observe que a função Interpolar também aceita um array de dados por referência (via & ), o que significa que as alterações feitas no array dentro da função serão refletidas no array original passado como argumento quando a função for chamada.


Tipos de sinais preferidos para alimentar a rede neural

Os sinais são um elemento chave para a operação de redes neurais. Eles representam dados que são transmitidos à rede neural para processamento e análise. Escolher o tipo certo de sinal para alimentar uma rede neural pode afetar muito sua eficiência e precisão. Neste artigo, veremos os tipos de sinais preferidos para serem transmitidos à rede neural.

Sinais numéricos

Sinais numéricos são o tipo mais comum de sinais usados ​​em redes neurais. Eles representam valores numéricos que podem ser processados ​​e analisados ​​por uma rede neural. Os sinais numéricos podem ser discretos ou contínuos. Os sinais discretos têm um número finito de valores, enquanto os sinais contínuos têm um número infinito de valores.

Imagens

As imagens também são um tipo popular de sinal usado em redes neurais. Elas são imagens gráficas que podem ser processadas por uma rede neural. As imagens podem ser em preto e branco ou coloridas. Para transferir imagens para a rede neural, elas devem ser convertidas em um formato numérico.

Sinais de texto

Sinais de texto também podem ser usados ​​para enviar dados para uma rede neural. Eles são sequências de texto que podem ser processadas e analisadas por uma rede neural. Os sinais de texto podem estar em linguagens naturais e linguagens de programação especiais.

Sinais de áudio

Os sinais de áudio também podem ser usados ​​para alimentar uma rede neural com dados. Eles são sinais de áudio que podem ser processados ​​e analisados ​​por uma rede neural. Os sinais de áudio podem ser voz e música.

Sinais de vídeo

Os sinais de vídeo são uma sequência de imagens que podem ser processadas e analisadas por uma rede neural.

Sinais sensoriais

Os sinais sensoriais são um tipo importante de sinais que podem ser transmitidos à rede neural em tarefas de visão de máquina e robótica. Eles podem incluir dados de sensores como giroscópios, acelerômetros, sensores de distância e outros. Esses dados podem ser usados ​​para treinar a rede neural para que ela possa analisar e responder ao ambiente.

Sinais gráficos

Sinais gráficos são imagens vetoriais ou de bitmap que podem ser processadas e analisadas por uma rede neural. Eles podem ser usados ​​para tarefas relacionadas a gráficos e design, como reconhecimento de caracteres e formas, criação automática de desenhos, etc.

Séries temporais

As séries temporais são uma sequência de números que são medidos ao longo do tempo. Eles podem ser usados ​​para tarefas relacionadas à previsão, previsão de tendências e análise de dados temporais. As redes neurais podem ser usadas para processar séries temporais para revelar padrões ocultos e prever valores futuros.

Como escolher o tipo apropriado de sinal para alimentar a rede neural?

Essa escolha depende da tarefa específica e dos dados disponíveis. Algumas tarefas podem exigir o uso de vários tipos de sinal ao mesmo tempo. Por exemplo, uma tarefa de reconhecimento de fala pode envolver o uso de sinais de áudio e sinais de texto ao mesmo tempo.

Ao escolher o tipo de sinal a ser transmitido à rede neural, é necessário levar em consideração suas características, como tamanho, resolução, formato, etc. Além disso, é necessário fornecer um pré-processamento de dados adequado, como normalização, filtragem etc., para garantir a qualidade e a precisão ideais do processamento de dados pela rede neural.

Em conclusão, escolher o tipo apropriado de sinal a ser enviado à rede neural é um passo importante para alcançar os melhores resultados em tarefas de aprendizado de máquina. Quanto ao treinamento de redes neurais, podem ser usados diferentes tipos de sinais, dependendo da tarefa específica e dos dados disponíveis. A escolha certa do tipo de sinal e o pré-processamento de dados apropriado podem ajudar a garantir a precisão e o desempenho ideais da rede neural.

No entanto, também é preciso considerar as limitações em termos de capacidade computacional e disponibilidade de dados. Alguns tipos de sinais podem ser mais complexos quando processados por uma rede neural, o que pode exigir mais poder computacional e mais dados para treinamento. Por isso, é necessário equilibrar a qualidade e a disponibilidade dos dados ao selecionar o tipo de sinal para treinar a rede neural.

Em geral, escolher o tipo certo de sinal para alimentar uma rede neural é um passo importante para alcançar os melhores resultados em tarefas de aprendizado de máquina. As redes neurais podem processar vários tipos de sinais, como áudio, vídeo, texto, dados sensoriais, dados gráficos e séries temporais. A escolha certa do tipo de sinal e o pré-processamento de dados apropriado podem ajudar a garantir a precisão e o desempenho ideais da rede neural em uma tarefa específica.


Prática

Na prática, hoje vamos considerar vários Expert Advisors baseados em nosso perceptron favorito. Vamos transferir os valores do indicador Accelerator Oscillator. Vamos passar o valor do indicador em 4 velas e aplicar os métodos de normalização descritos acima. Para assegurar as condições do experimento, vamos comparar os resultados dos Expert Advisors com e sem transformação. No EA sem conversão, passaremos os valores do indicador diretamente. 

Aqui vou dar todos os parâmetros para otimização e teste para que não se repitam no texto:

  • Mercado Forex;
  • Par de moedas EURUSD;
  • Período H1;
  • StopLoss 300 e TakeProfit 600;
  • Modo de otimização e teste "Somente preços de abertura" e "Máximo de critério complexo". É muito importante usar o modo "Máximo critério complexo", já que mostrou resultados mais estáveis e lucrativos em comparação com "Máxima lucratividade";
  • Faixa de otimização de 3 anos. De 2019.04.06 a2022.04.06 . 3 anos não é algum tipo de critério. Você pode tentar mais ou menos sozinho;
  • Intervalo de teste forward de 1 ano. De 2022.04.06 a 2023.04.06 . Verificamos tudo com base no algoritmo descrito no meu artigo (Experimentos com redes neurais (Parte 3): Uso pratico). Ou seja, negociação simultânea com vários melhores resultados de otimização;
  • Vamos agora realizar a otimização 40 vezes. Aumentamos em 2 vezes em comparação com os testes anteriores e vemos os resultados. 
  • 40 resultados de otimização foram usados ​​simultaneamente em todos os testes forward. Em relação aos testes anteriores em meus artigos, o valor é aumentado em um fator de 2;
  • Otimização de Expert Advisors com perceptron "(algoritmo genético) rápido";
  • Depósito inicial 10.000 unidades;
  • Alavancagem 1:500.

Para otimização, uso um pequeno programa autoclicker que escrevi em Delphi. Não posso publicá-lo aqui, mas enviarei a quem precisar em mensagens privadas se me escrever. Ele funciona assim:

  1. Inserimos o número necessário de otimizações.
  2. Movemos o cursor sobre o botão “Iniciar” no otimizador de estratégia.
  3. Tratamos dos nossos negócios.

A otimização termina após os ciclos especificados e o programa é fechado. O autoclicker responde à mudança na cor do botão “Iniciar”. Abaixo está uma captura de tela do programa. 

Autoclicker

EA Perceptron AC 4 SL TP:

Transferimos os dados do indicador diretamente sem usar a normalização. 

Resultados da otimização:

Otimização


Otimização

Resultados do teste forward:

Teste


EA perceptron AC 4 (Differentiation) SL TP:

Transferimos os dados do indicador usando a normalização min-max. 

Resultados da otimização:

Otimização


Otimização

Resultados do teste forward:

Teste



Considerações finais

Lista de arquivos anexados:

  1. perceptron AC 4 SL TP - opt - Expert Advisor perceptron para otimização no indicador AC sem usar normalização;
  2. perceptron AC 4 SL TP - trade - EA perceptron otimizado no indicador AC sem usar normalização;
  3. perceptron AC 4 (Differentiation) SL TP - opt - EA perceptron para otimização no indicador AC usando diferenciação para normalização;
  4. perceptron AC 4 (Differentiation) SL TP - trade -  EA perceptron otimizado no indicador AC usando a diferenciação para normalização;

A normalização reduz o impacto de valores atípicos nos dados, o que pode ajudar a evitar o sobreajuste do modelo. Dados devidamente normalizados permitem que a rede "entenda" melhor as relações entre os parâmetros, levando a previsões mais precisas e melhor qualidade do modelo.

No artigo, examinamos vários métodos de normalização, mas essas não são as únicas maneiras de processar dados para melhorar o treinamento de redes neurais. Cada caso específico requer uma abordagem individual, e o método de normalização deve ser escolhido dependendo das características dos dados e da tarefa específica.

Em geral, a normalização dos parâmetros de entrada é uma etapa importante no processo de treinamento de redes neurais. Dados processados incorretamente podem levar a resultados inadequados e afetar negativamente o desempenho do modelo. Dados devidamente normalizados podem melhorar a estabilidade e a taxa de convergência do treinamento, bem como levar a previsões mais precisas e melhorar a qualidade do modelo.

Obrigado pela atenção, amigos, e até breve!



Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/12459

Arquivos anexados |
EA.zip (199.53 KB)
Aprenda algumas lições com as Empresas de Prop Trading (Parte 1) — Uma introdução Aprenda algumas lições com as Empresas de Prop Trading (Parte 1) — Uma introdução
Neste artigo introdutório, discutirei algumas lições que podem ser aprendidas com os testes que as empresas de prop trading empregam. Isso é especialmente relevante para iniciantes e para aqueles que estão lutando para encontrar seu lugar no mundo do trading. O próximo artigo abordará a implementação do código.
Teoria das Categorias em MQL5 (Parte 6): produtos fibrados monomórficos e coprodutos fibrados epimórficos Teoria das Categorias em MQL5 (Parte 6): produtos fibrados monomórficos e coprodutos fibrados epimórficos
A teoria das categorias é um ramo diversificado e em expansão da matemática que só recentemente começou a ser abordado na comunidade MQL5. Esta série de artigos tem como objetivo analisar alguns de seus conceitos para criar uma biblioteca aberta e utilizar ainda mais essa maravilhosa seção na criação de estratégias de negociação.
Desenvolvendo um sistema de Replay - Simulação de mercado (Parte 22): FOREX (III) Desenvolvendo um sistema de Replay - Simulação de mercado (Parte 22): FOREX (III)
Para quem ainda não entendeu a diferença entre o mercado de bolsa e o de forex, apesar de este já ser o terceiro artigo em que estou abordando isto. Devo deixar claro, que a grande diferença, é o fato de que no forex não existe, ou melhor, não nos é informado algumas coisas a respeito do que aconteceu de fato na negociação.
Multibot no MetaTrader: lançando vários robôs a partir de um único gráfico Multibot no MetaTrader: lançando vários robôs a partir de um único gráfico
Neste artigo, veremos um modelo simples para a criação de um robô universal no MetaTrader que pode ser usado em vários gráficos, mas que é fixado em apenas um gráfico, sem a necessidade de configurar cada instância do robô em cada gráfico individual.