
Um algoritmo de seleção de características usando aprendizado baseado em energia em MQL5 puro
Introdução
No domínio da negociação algorítmica, o uso generalizado de aprendizado de máquina tem incentivado a adoção de técnicas de mineração de dados para descobrir padrões ocultos em dados financeiros. Nesse contexto, os praticantes frequentemente enfrentam o desafio de classificar inúmeras variáveis para identificar aquelas que são mais propensas a ser benéficas para alcançar objetivos específicos ou resolver problemas particulares. Neste artigo, exploramos a implementação de um algoritmo de seleção de características com o objetivo de avaliar a relevância de um conjunto de variáveis candidatas para uma tarefa de previsão específica.
Yun Li, Jennie Si, Guojing Zhou, Shasha Huang e Songcan Chen coautoraram um artigo de pesquisa intitulado "FREL: Um Algoritmo Estável de Seleção de Características." Este artigo introduz um algoritmo chamado Ponderação de Características como Aprendizado Baseado em Energia Regularizada (FREL), que serve como uma técnica de seleção ou ponderação de características projetada para oferecer precisão e estabilidade. Em nossa discussão, fornecemos uma visão geral dos fundamentos teóricos por trás do aprendizado baseado em energia regularizada e da ponderação de características. Além disso, ilustramos a eficácia da abordagem proposta por meio da implementação de um exemplo de programa MQL5, desenvolvido como um script, para destacar o potencial do método como uma ferramenta de seleção de características.
Classificação de vizinho mais próximo ponderado
O conceito por trás do FREL é inspirado em uma técnica conhecida como classificação de vizinho mais próximo ponderado, que utiliza as distâncias entre os pontos de um conjunto de dados para fazer previsões. Ao determinar os pesos adequados para cada característica, esse método melhora a precisão da previsão. A classificação de vizinho mais próximo ponderado representa uma variação do algoritmo k-nearest neighbor (k-NN), uma abordagem amplamente utilizada em aprendizado de máquina para tarefas de classificação. Na classificação k-NN padrão, o algoritmo examina os k pontos de dados mais próximos no conjunto de treinamento ao classificar um novo ponto de dados, atribuindo, por fim, a classe majoritária entre esses vizinhos ao novo ponto de dados.
Na classificação de vizinho mais próximo ponderado, no entanto, em vez de simplesmente contar os votos dos vizinhos mais próximos, cada voto de vizinho é ponderado de acordo com sua distância do novo ponto de dados. A justificativa é que vizinhos mais próximos devem exercer uma influência mais forte na decisão de classificação do que aqueles mais distantes. Esse processo de ponderação envolve o cálculo da distância entre o novo ponto de dados e cada ponto no conjunto de treinamento. Métricas de distância comuns utilizadas incluem distância euclidiana, distância de Manhattan ou similaridade cosseno, escolhidas com base nas características dos dados. Nesse contexto, utilizamos a distância de Manhattan, também referida como distância de bloco da cidade, entre os pontos de dados. A fórmula para calcular essa distância está mostrada abaixo. Onde, w, são os pesos e um caso de teste está sendo avaliado em relação a outros dados de treinamento, dado como caso de treinamento.
Entendendo modelos baseados em energia
Modelagem baseada em energia no aprendizado de máquina serve como uma estrutura versátil aplicável a tarefas de aprendizado supervisionado e não supervisionado. Ela opera com o princípio de atribuir valores de energia a várias configurações de dados e aprender um modelo capaz de distinguir entre configurações desejáveis e indesejáveis. Isso é alcançado minimizando a energia dos dados observados enquanto maximiza a energia das configurações de dados não observados ou indesejáveis.
No cerne dos modelos baseados em energia está a definição de uma função de energia, denotada como E(). Essa função recebe como entrada uma configuração de variáveis ou preditores, junto com um conjunto de parâmetros do modelo. A saída da função de energia fornece uma indicação da relevância da configuração das variáveis de entrada. Por exemplo, no contexto de avaliação de um modelo de regressão, a função de energia pode ser representada como o erro quadrático médio. Quando preditores relevantes são inseridos na equação do erro quadrático médio, o valor de saída tende a ser menor, refletindo maior relevância. Por outro lado, preditores ruins levam a valores maiores de erro quadrático médio. A função de energia atribui um valor escalar a cada configuração concebível de variáveis.
O objetivo do treinamento de um modelo baseado em energia é aprender os parâmetros da função de energia para que ela atribua baixas energias às variáveis de entrada relevantes e altas energias às irrelevantes. Isso implica definir uma função objetivo que penalize altas energias para variáveis corretas e baixas energias para variáveis incorretas. Para conseguir isso, o objetivo é identificar a configuração de variáveis incorretas que gera a menor energia, representando uma amostra que provavelmente causará previsões errôneas do modelo. A função abaixo representa a energia da configuração de entradas, x, e o parâmetro do modelo, w, que produz o valor incorreto, y, muito baixo para distinguir das configurações de variáveis de entrada que produzem previsões precisas.
Por fim, a função objetivo visa maximizar a discrepância entre a configuração incorreta com menor energia e a configuração correta mais próxima de variáveis. A energia de tal configuração é dada abaixo.
A função objetivo, conhecida como funcional de perda, compreende uma função de perda média por amostra. Dada abaixo como a perda logarítmica.
Vários critérios de perda podem servir como a função de perda por amostra, como perda hinge, perda logarítmica, perda quadrática e perda quadrático-exponencial, dependendo da aplicação.
Em resumo, esses são os conceitos fundamentais subjacentes ao FREL. A seção subsequente detalha as especificidades do próprio algoritmo.
O algoritmo FREL
Para aplicar efetivamente o algoritmo FREL, certas considerações fundamentais devem ser seguidas. Primeiramente, é crucial avaliar cuidadosamente os dados de treinamento. O FREL é idealmente adequado para conjuntos de dados que mapeiam um conjunto de variáveis candidatas para um único alvo. Igualmente importante é garantir que as variáveis sejam semelhantes em escala. Expor o FREL a preditores candidatos com escalas inconsistentes pode distorcer significativamente os resultados finais.
Em segundo lugar, dado que o FREL é um procedimento de aprendizado baseado em energia, ele exige a definição de uma função de energia que incorpore parâmetros de ponderação. Portanto, o modelo usado deve ser configurado para aceitar um conjunto de variáveis candidatas junto com as ponderações correspondentes. Portanto, o modelo usado deve ser configurado para aceitar um conjunto de variáveis candidatas junto com as ponderações correspondentes. Cada peso seria emparelhado com um preditor candidato.
Por fim, deve-se selecionar uma função de perda por amostra para determinar o funcional de perda. O funcional de perda, que incorpora os parâmetros de ponderação do modelo, é a função (de funções) minimizada para obter os pesos ideais.
Os passos principais do algoritmo FREL são os seguintes:
- Comece com um conjunto de dados de treinamento composto por n observações com d preditores candidatos correspondentes a n valores-alvo. O objetivo é determinar os preditores mais relevantes do conjunto de d candidatos para determinar os valores-alvo. Isso resulta na atribuição de pesos a cada um dos d preditores, indicando a importância da variável em relação aos outros. Um peso maior significa maior relevância na definição do valor-alvo.
- Inicialmente, atribua a todos os pesos o valor de 1.
- Aplique a classificação de vizinhos mais próximos ponderados a cada observação nos dados de treinamento para identificar a configuração de variáveis incorretas que geram a menor energia e a configuração mais próxima de variáveis corretas com alta energia. Utilize esses valores de energia para calcular a perda por amostra usando a função de perda selecionada.
- Por fim, minimize a função de perda objetivo, opcionalmente com regularização, usando um procedimento de otimização apropriado. Este constitui o algoritmo central do FREL.
Implementação do FREL em MQL5
A implementação do FREL mostrada neste texto utiliza o método de otimização de Powell. Embora o método de otimização específico usado não seja crítico, os resultados devem ser relativamente consistentes entre os métodos. Nesta implementação, o método de Powell é representado como a classe "PowellsMethod", definida em Powells.mqh. O algoritmo FREL está encapsulado na classe "FREL", uma descendente de "PowellsMethod", especificada em frel.mqh.
//+------------------------------------------------------------------+ //| constructor | //+------------------------------------------------------------------+ FREL(matrix &in_data,int numboot=1, int bootsize=0) { m_data = in_data; m_num_boot=(numboot>0)?numboot:1; m_bootsize=(bootsize>2 && bootsize<=int(m_data.Rows()) && m_num_boot>1)?bootsize:int(m_data.Rows()); if(ArrayResize(m_indices, int(m_data.Rows()))!=int(m_data.Rows()) || ArrayResize(m_target_bin, int(m_data.Rows()))!=int(m_data.Rows()) || ArrayResize(m_trial_weights, int(m_data.Cols()-1))!=int(m_data.Cols()-1) || ArrayResize(m_work_weights, int(m_data.Cols()-1))!=int(m_data.Cols()-1) ) { Print(__FUNCTION__, " error ", GetLastError()); m_memory_allocated = false; } else m_memory_allocated = true; }
Vamos nos aprofundar na descrição do construtor paramétrico. Ele é invocado com pelo menos um parâmetro: uma matriz de dados de treinamento. É crucial notar como os dados de treinamento devem ser estruturados na matriz. Cada linha representa uma observação ou uma amostra individual, enquanto as colunas representam as variáveis candidatas ou preditores a serem avaliados. O alvo é esperado na última coluna da matriz. Os parâmetros opcionais do construtor são explicados mais detalhadamente na tabela abaixo.
Nome do parâmetro | Tipo de dados | Valor Padrão | Descrição |
---|---|---|---|
numboot | inteiro | 1 | "numboot" define o número de bootstraps a serem realizados. |
bootsize | inteiro | 0 | "bootsize" define o tamanho de cada bootstrap. Tome cuidado ao definir esse parâmetro. Se for usado um valor maior do que o número de observações na matriz, "numboot" automaticamente volta para 1 e "bootsize" para o número de observações. |
Há apenas um método com o qual os usuários precisam se familiarizar para utilizar a classe "FREL": "WeighVars()."
//+-----------------------------------------------------------------------+ //| Find the most relevant variables from a dataset of candidate variables| //+-----------------------------------------------------------------------+ bool WeighVars(int num_bins_target, double reg_factor,int &index[],double &weights[]) { if(!m_memory_allocated) { Print(" INTERNAL ERROR "); return false; } if(num_bins_target<=1 || num_bins_target>int(m_data.Rows())) { Print(__FUNCTION__, " invalid function parameter: num_bins_target. Parameter should be >=2 "); return false; } int ret=0; double target[], target_thresholds[] ; double sum ; int n_cases = int(m_data.Rows()); m_reg_factor = MathAbs(reg_factor); m_loss = 0.0; if(ArrayResize(index,int(m_data.Cols()-1))!=int(m_data.Cols()-1) || !np::vecAsArray(m_data.Col(m_data.Cols()-1),target) ) { Print(__FUNCTION__, " error ", GetLastError()); return false; } int k = num_bins_target ; if(!bin_array(target, k, target_thresholds, m_target_bin)) return false; if(k<num_bins_target) { Print("error bins of target vector ", num_bins_target," : ", k); return false; } for(int i=0 ; i<n_cases ; i++) { if(m_target_bin[i] >= num_bins_target) { Print("error m_target_bin array at index ", i, " is ",m_target_bin[i], " should be less than ", num_bins_target); return false; } } ret = calc_wt(num_bins_target,m_loss,weights); if(ret<0) return false; sum = 0.0 ; for(ulong var=0 ; var<m_data.Cols()-1 ; var++) { weights[var] = m_data.Col(var).Std() * exp(weights[var]); sum += weights[var] ; } for(ulong var=0 ; var<m_data.Cols()-1 ; var++) { weights[var] *= 100.0 / sum ; index[var] = int(var) ; } MathQuickSortDescending(weights,index,0,int(weights.Size()-1)) ; return true; }
Este método avalia os dados de treinamento especificados no construtor. Ele retorna um valor booleano, com "false" indicando que o procedimento falhou em ser concluído. Os parâmetros deste método são os seguintes:
- "num_bins_target": Um número inteiro que define o número de intervalos em que os valores-alvo serão particionados. Esse parâmetro deve ser definido para qualquer número inteiro >= 2, mas <= o número de observações nos dados de treinamento.
- "reg_factor": Um valor de ponto flutuante positivo que controla o grau de regularização. Um valor de 0 desativa a regularização.
- "index[]": Um array de inteiros para o qual parte dos resultados da operação será escrita. Ele contém os índices das colunas originais, conforme fornecido ao construtor, organizados em ordem decrescente de relevância para o alvo.
- "weights[]": Um array de ponto flutuante contendo as ponderações ótimas, organizadas em ordem decrescente.
Quando "WeighVars()" é invocado, os valores-alvo são extraídos da matriz e colocados em um array em preparação para uma chamada ao método privado "bin_array()". Esse método segmenta o array em categorias aproximadamente de mesmo tamanho, retornando dois arrays após a conclusão bem-sucedida. "upperbound_thresholds[]" é um array de limites superiores para cada segmento, enquanto o array de inteiros "categories[]" contém valores de índice representando o segmento ao qual cada valor-alvo correspondente pertence. Cada um desses valores é verificado para garantir que todos os valores-alvo foram corretamente classificados.
//+------------------------------------------------------------------+ //| calculates the optimal weights of candidate variables | //+------------------------------------------------------------------+ int calc_wt(int num_bins_target,double &loss_value, double &w[]) { int ret,rand_error, class_count[] ; ret = 0; if(ArrayResize(class_count,num_bins_target)!=num_bins_target || (w.Size()!=uint(m_data.Cols()-1) && ArrayResize(w,int(m_data.Cols()-1))!=int(m_data.Cols()-1))) { Print(__FUNCTION__, " error ", GetLastError()); return -1; } ArrayInitialize(w,0.0); loss_value = 0.0 ; for(ulong i=0 ; i<m_data.Rows() ; i++) m_indices[i] = int(i) ; for(int ibootstrap=0 ; ibootstrap<m_num_boot; ibootstrap++) { Comment(" Bootstrap iteration ", ibootstrap+1); ArrayInitialize(class_count,0); int ii, j, k, m; ii = int (m_data.Rows()) ; while(ii > 1) { m = int (m_data.Rows()) - ii ; if(m >= m_bootsize) break ; j = (int)(MathRandomUniform(0.0,1.0,rand_error) * ii) ; if(j >= ii) j = ii - 1 ; k = m_indices[m] ; m_indices[m] = m_indices[m+j] ; m_indices[m+j] = k ; --ii ; ++class_count[m_target_bin[m_indices[m]]] ; } for(int i=0 ; i<num_bins_target ; i++) { if(class_count[i] < 2) Print(__FUNCTION__, " class at ", i, " has less than 2 members. Considere ajustar os parâmetros Frel. (number of partitions or bootstrap sample size)"); } ArrayInitialize(m_trial_weights,0.0); ret += Optimize(m_trial_weights); loss_value += PowellsMethod::GetFret() ; for(ulong i=0 ; i<m_data.Cols()-1 ; i++) w[i] += m_trial_weights[i] ; } for(ulong i=0 ; i<m_data.Cols()-1; i++) w[i] /= double(m_num_boot) ; return ret ; }
A estimativa de pesos começa com uma chamada para "calc_wt()". Aqui, a amostragem bootstrap é realizada, embaralhando os dados antes de os pesos iniciais serem otimizados. A otimização é realizada pelo método da classe pai "Optimize()". Os pesos ótimos para cada bootstrap são somados em "w[]", para serem promediados antes de sair de "calc_wt()".
//+------------------------------------------------------------------+ //| function minimized by Powells optimization method | //+------------------------------------------------------------------+ virtual double func(const double& p[]) { double pen = 0.0 ; for(ulong i=0 ; i<m_data.Cols()-1 ; i++) { if(p[i] > 4.0) { m_work_weights[i] = exp(4.0) + p[i] - 4.0 ; pen += (p[i] - 4.0) * (p[i] - 4.0) ; } else if(p[i] < -3.0) { m_work_weights[i] = exp(-3.0) + p[i] + 3.0 ; pen += (p[i] + 3.0) * (p[i] + 3.0) ; } else m_work_weights[i] = exp(p[i]) ; } return (loss(m_work_weights) + pen) ; }
Lembre-se de que a função que está sendo minimizada é o funcional de perda, representado por um método sobrescrito da classe pai chamado "func()". — ¶ —————————————————————
//+------------------------------------------------------------------+ //| calculates the loss function | //+------------------------------------------------------------------+ double loss(double &w[]) { double totaloss = total_loss(w); totaloss/=double(m_data.Rows()); if(m_reg_factor>0.0) { for(ulong i=0; i<m_data.Cols()-1;i++) totaloss+=m_reg_factor*pow(w[i],2.0); } return totaloss; }
Dentro de "func()", o método "loss()" é acionado, desencadeando o cálculo da função de perda por amostra implementada como o método privado "total_loss()".
//+------------------------------------------------------------------+ //| loss over all data | //+------------------------------------------------------------------+ double total_loss(double &w[]) { int category,first, other ; double distance, top, bottom, loss ; loss = 0.0 ; for(int i=0; i<m_bootsize; i++) { other = m_indices[i] ; category = m_target_bin[other] ; top = bottom = DBL_MAX ; for(int iother=0 ; iother<m_bootsize; iother++) { first = m_indices[iother] ; if(first == other) continue ; distance = 0.0 ; for(ulong v=0 ; v<m_data.Cols()-1; v++) { distance += w[v] * fabs(m_data[other][v] - m_data[first][v]) ; } if(m_target_bin[first] == category) { if(distance < top) top = distance ; } else { if(distance < bottom) bottom = distance ; } } distance = top - bottom ; if(distance > 30.0) loss += distance ; else loss += log(1.0 + exp(distance)); } return loss ; }
Após a conclusão de todos os bootstraps, os pesos ótimos médios são escritos no array "weights[]" fornecido pelo usuário. Antes de ordenar em ordem decrescente, os pesos são transformados de modo que somem coletivamente 100, melhorando a interpretabilidade.
Um exemplo de seleção de características usando FREL
Para demonstrar o algoritmo FREL, fornecemos o script "FrelExample.mq5". Este script utiliza o FREL para analisar um conjunto de dados gerado aleatoriamente, composto por variáveis candidatas e um alvo, para identificar os melhores preditores. Os usuários podem ajustar todos os parâmetros do algoritmo FREL e certas características do conjunto de dados sintético. Isso inclui o número total de observações (num_observations) e o número de preditores candidatos (num_candidate_predictors). Abaixo está um trecho ilustrando as entradas ajustáveis pelo usuário no script:
//---user adjustable input parameters input int number_of_partitions = 8; //Number of partitions input double regularization_factor = 0.0; //Regularization factor input int number_of_bootstraps = 1; input int bootstrap_size = 0; input ulong num_observations = 2000;// Sample size of random dataset input ulong num_candidate_predictors = 10;// Maximum number of candidate predictors in dataset
O script gera uma matriz de números aleatórios com num_observations linhas e num_candidate_predictors + 1 colunas. A última coluna é sobrescrita com a soma das colunas nos índices 1, 3, 5 e 7, que serve como a variável alvo do conjunto de dados.
//+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { srand(126); //---check user input parameters if(number_of_partitions<2 || num_observations<10 || num_candidate_predictors<8) { Print("Invalid input parameters"); return; } //---the data matrix dataset; //---initialize size of random dataset dataset.Init(num_observations,num_candidate_predictors+1); //---fill dataset with random data dataset.Random(1.0,10.0); //---set the target variable in the last column if(!dataset.Col(dataset.Col(1) + dataset.Col(3) + dataset.Col(5) + dataset.Col(7),num_candidate_predictors)) { Print("error ", GetLastError()); return; } //---initialize Frel object FREL frel(dataset,number_of_bootstraps,bootstrap_size); //---declare containers to recieve output from Frel operation double optimal_weights[]; int index[]; //--- ulong timeIT = GetTickCount64(); //---find the most relevant predictors if(!frel.WeighVars(number_of_partitions,regularization_factor,index,optimal_weights)) return; //---calculate runtime Print("Runtime of FREL ", GetTickCount64() - timeIT, " ms"); //---display results for(uint i = 0; i<optimal_weights.Size(); i++) Print("Predictor at Column index ", index[i], " weight ", optimal_weights[i]); } //+------------------------------------------------------------------+
O objetivo é observar se o FREL pode ponderar adequadamente as variáveis, designando as colunas 1, 3, 5 e 7 como tendo o relacionamento mais forte com o alvo. Inicialmente, executamos o script com os parâmetros padrão, observando que a regularização está desativada e apenas um bootstrap foi especificado.
Saída:
ON 0 18:12:30.906 FrelExample (BTCUSD,D1) Runtime of FREL 273375 ms GD 0 18:12:30.906 FrelExample (BTCUSD,D1) Predictor at Column index 7 weight 24.46987538756267 IH 0 18:12:30.906 FrelExample (BTCUSD,D1) Predictor at Column index 3 weight 24.22319404776024 EL 0 18:12:30.906 FrelExample (BTCUSD,D1) Predictor at Column index 5 weight 22.26820806768701 LP 0 18:12:30.906 FrelExample (BTCUSD,D1) Predictor at Column index 1 weight 22.13748732798876 DD 0 18:12:30.906 FrelExample (BTCUSD,D1) Predictor at Column index 0 weight 1.162036446785271 KK 0 18:12:30.906 FrelExample (BTCUSD,D1) Predictor at Column index 8 weight 1.1532145209345603 RO 0 18:12:30.906 FrelExample (BTCUSD,D1) Predictor at Column index 4 weight 1.1496286906955606 RS 0 18:12:30.906 FrelExample (BTCUSD,D1) Predictor at Column index 2 weight 1.1472521997561425 NG 0 18:12:30.906 FrelExample (BTCUSD,D1) Predictor at Column index 6 weight 1.14561384476096 DK 0 18:12:30.906 FrelExample (BTCUSD,D1) Predictor at Column index 9 weight 1.14348946606884
Em seguida, investigamos o impacto da regularização nos pesos estimados testando com graus de regularização de 0,1 e 1,0.
Saída:
MQ 0 18:19:03.951 FrelExample (BTCUSD,D1) Runtime of FREL 331296 ms QD 0 18:19:03.951 FrelExample (BTCUSD,D1) Predictor at Column index 3 weight 19.63442784832085 PK 0 18:19:03.951 FrelExample (BTCUSD,D1) Predictor at Column index 5 weight 19.009699240770477 GO 0 18:19:03.951 FrelExample (BTCUSD,D1) Predictor at Column index 7 weight 18.823288529399388 GQ 0 18:19:03.951 FrelExample (BTCUSD,D1) Predictor at Column index 1 weight 18.18026689510982 NE 0 18:19:03.951 FrelExample (BTCUSD,D1) Predictor at Column index 0 weight 4.106428447842871 KI 0 18:19:03.951 FrelExample (BTCUSD,D1) Predictor at Column index 8 weight 4.075425288243113 OM 0 18:19:03.951 FrelExample (BTCUSD,D1) Predictor at Column index 2 weight 4.070169243578418 MQ 0 18:19:03.951 FrelExample (BTCUSD,D1) Predictor at Column index 6 weight 4.051103060690134 FE 0 18:19:03.951 FrelExample (BTCUSD,D1) Predictor at Column index 9 weight 4.025271426001863 FJ 0 18:19:03.951 FrelExample (BTCUSD,D1) Predictor at Column index 4 weight 4.0239200200430805
Saída:
HP 0 18:25:43.421 FrelExample (BTCUSD,D1) Runtime of FREL 362984 ms FF 0 18:25:43.421 FrelExample (BTCUSD,D1) Predictor at Column index 3 weight 10.353013480731704 JJ 0 18:25:43.421 FrelExample (BTCUSD,D1) Predictor at Column index 7 weight 10.227015183302557 IM 0 18:25:43.421 FrelExample (BTCUSD,D1) Predictor at Column index 5 weight 10.213781888319609 KQ 0 18:25:43.421 FrelExample (BTCUSD,D1) Predictor at Column index 1 weight 10.079770794877978 PF 0 18:25:43.421 FrelExample (BTCUSD,D1) Predictor at Column index 0 weight 9.948300319843046 QJ 0 18:25:43.421 FrelExample (BTCUSD,D1) Predictor at Column index 8 weight 9.938367489770178 KN 0 18:25:43.421 FrelExample (BTCUSD,D1) Predictor at Column index 2 weight 9.897336276433514 DQ 0 18:25:43.421 FrelExample (BTCUSD,D1) Predictor at Column index 6 weight 9.79559491756489 EF 0 18:25:43.421 FrelExample (BTCUSD,D1) Predictor at Column index 9 weight 9.774541742551756 CI 0 18:25:43.421 FrelExample (BTCUSD,D1) Predictor at Column index 4 weight 9.77227790660475
Os resultados dos testes de regularização indicam que os pesos se espalham por outras variáveis, divergindo das variáveis corretas. É provável que especificar um grau maior de regularização leve a pesos menos distintos, dificultando a diferenciação entre variáveis úteis e irrelevantes.
Ao examinar os resultados de execução dos nossos testes, é evidente que o FREL opera relativamente devagar. O gargalo provavelmente está relacionado à função "total_loss()", que precisa iterar por todo o conjunto de dados várias vezes conforme o otimizador é executado. Para melhorar a eficiência de execução, realizamos vários bootstraps com um tamanho de amostra menor. Os seguintes resultados são obtidos a partir de uma execução com 100 bootstraps de 40 amostras.
Saída:
IN 0 18:30:55.441 FrelExample (BTCUSD,D1) Runtime of FREL 22985 ms OK 0 18:30:55.441 FrelExample (BTCUSD,D1) Predictor at Column index 3 weight 18.706272752181135 OL 0 18:30:55.441 FrelExample (BTCUSD,D1) Predictor at Column index 1 weight 18.32079620338284 RS 0 18:30:55.441 FrelExample (BTCUSD,D1) Predictor at Column index 5 weight 18.194009676469012 HG 0 18:30:55.441 FrelExample (BTCUSD,D1) Predictor at Column index 7 weight 16.298306686632337 MI 0 18:30:55.441 FrelExample (BTCUSD,D1) Predictor at Column index 4 weight 5.838867272535404 LM 0 18:30:55.441 FrelExample (BTCUSD,D1) Predictor at Column index 9 weight 5.249285089162589 FQ 0 18:30:55.441 FrelExample (BTCUSD,D1) Predictor at Column index 8 weight 4.791606631149278 DE 0 18:30:55.441 FrelExample (BTCUSD,D1) Predictor at Column index 6 weight 4.770223641360407 KI 0 18:30:55.441 FrelExample (BTCUSD,D1) Predictor at Column index 0 weight 3.974977300216029 KM 0 18:30:55.441 FrelExample (BTCUSD,D1) Predictor at Column index 2 weight 3.855654746910961
Conclusão
Neste artigo, introduzimos uma implementação em MQL5 da ponderação de características usando modelagem baseada em energia regularizada. Fornecemos uma breve visão geral dos fundamentos teóricos do algoritmo e demonstramos sua eficácia em um conjunto de dados sintético. Embora os resultados fossem promissores, observamos que o algoritmo incorreu em custos computacionais significativos, levando a uma análise lenta. Para lidar com esse problema, propusemos a utilização de múltiplos bootstraps com tamanhos de amostra menores, o que melhorou significativamente a velocidade de execução geral do algoritmo. No entanto, nossa implementação ainda poderia se beneficiar grandemente de multithreading ou aceleração por GPU. Mesmo assim, encorajamos os interessados no método a personalizar o código de acordo com suas necessidades. O artigo inclui todo o código discutido, com cada arquivo-fonte detalhado na tabela abaixo.
Arquivo-fonte | Descrição |
---|---|
Mql5\include\np.mqh | Um arquivo de cabeçalho com várias ferramentas de manipulação de vetores e matrizes.
|
Mql5\include\Powells.mqh | Contém a definição da classe PowellsMethod, que implementa o método de minimização de funções de Powell. |
Mql5\include\frel.mqh | Contém a definição da classe FREL, que representa a ponderação de características como um algoritmo de aprendizado baseado em energia regularizada. |
Mql5\script\FrelExample.mq5 | Um script demonstrando o uso da classe FREL |
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/14865
Aviso: Todos os direitos sobre esses materiais pertencem à MetaQuotes Ltd. É proibida a reimpressão total ou parcial.
Esse artigo foi escrito por um usuário do site e reflete seu ponto de vista pessoal. A MetaQuotes Ltd. não se responsabiliza pela precisão das informações apresentadas nem pelas possíveis consequências decorrentes do uso das soluções, estratégias ou recomendações descritas.





- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso