Discussão do artigo "Redes neurais de maneira fácil (Parte 57): Stochastic Marginal Actor-Critic (SMAC)"

 

Novo artigo Redes neurais de maneira fácil (Parte 57): Stochastic Marginal Actor-Critic (SMAC) foi publicado:

Apresentamos um algoritmo relativamente novo, o Stochastic Marginal Actor-Critic (SMAC), que permite a construção de políticas de variáveis latentes no contexto da maximização da entropia.

Quanto construímos um sistema de negociação automatizado, desenvolvemos algoritmos para uma tomada de decisão consistente. Os métodos de aprendizado por reforço procuram lidar com essas tarefas. Um dos principais problemas do aprendizado por reforço é o processo de exploração, quando o Agente aprende a interagir com o ambiente. Neste contexto, o princípio da máxima entropia é comumente usado para motivar o Agente a realizar ações com o mais alto grau de aleatoriedade. Entretanto, na prática, esses algoritmos treinam Agentes simples que só aprendem mudanças locais em torno de uma única ação. Isso se deve à necessidade de calcular a entropia da política do Agente e usá-la como parte do objetivo do aprendizado.

Paralelamente, um enfoque relativamente simples para aumentar a expressividade da política do Ator consiste em usar variáveis latentes, que oferecem ao Agente seu próprio procedimento de inferência para modelar a estocasticidade nas observações, no ambiente e nas recompensas desconhecidas.

A introdução de variáveis latentes na política do Agente permite abranger uma variedade maior de cenários compatíveis com o histórico de observações. É importante notar aqui que as políticas com variáveis latentes não admitem uma expressão simples para determinar sua entropia. A estimativa ingênua da entropia pode acarretar falhas catastróficas na otimização da política. Além disso, as atualizações estocásticas com alta variação para maximizar a entropia não distinguem imediatamente entre efeitos aleatórios locais e exploração multimodal.

Uma das soluções para essas limitações das políticas com variáveis latentes foi proposta no artigo "Latent State Marginalization as a Low-cost Approach for Improving Exploration". Nele, os autores propõem um algoritmo de otimização de política simples, mas eficaz, que é capaz de proporcionar uma exploração mais eficiente e estável tanto em ambientes totalmente observáveis quanto em ambientes parcialmente observáveis.

Autor: Dmitriy Gizlyk

 
Não compilado.
Arquivos anexados:
 
Também não estou compilando. É a mesma coisa.
 
star-ik #:
Não compilado.

O arquivo de arquivos do artigo foi atualizado.

 

Dmitry, obrigado por seu trabalho árduo. Tudo está funcionando.

Coletei exemplos com o Expert Advisor Research por 100 passagens, treinei o modelo com o Expert Advisor Study e testei com o Test. Em seguida, coleto 50 passagens novamente, treino por 10.000 iterações e testo novamente.

E assim por diante, até que o modelo aprenda. Exceto pelo fato de que, até o momento, o Test constantemente apresenta resultados diferentes após o ciclo e nem sempre positivos. Executei um ciclo, 2 a 3 testes e os resultados são diferentes.

Em que ciclo o resultado se tornará estável? Ou é um trabalho sem fim e o resultado sempre será diferente?

Muito obrigado!

 
Nikolai Fedotov exemplos com o Expert Advisor Research por 100 passagens, treinei o modelo com o Expert Advisor Study e testei com o Test. Em seguida, coleto 50 passagens novamente, treino por 10.000 iterações e testo novamente.

E assim por diante, até que o modelo aprenda. Exceto pelo fato de que, até o momento, o teste fornece constantemente resultados diferentes após o ciclo e nem sempre positivos. Ou seja, eu executo um ciclo, 2 ou 3 testes e os resultados são diferentes.

Em que ciclo o resultado se tornará estável? Ou é um trabalho sem fim e o resultado sempre será diferente?

Muito obrigado!

O Expert Advisor treina um modelo com uma política estocástica. Isso significa que o modelo aprende as probabilidades de maximizar as recompensas por tomar determinadas ações em determinados estados do sistema. À medida que ele interage com o ambiente, as ações são amostradas com as probabilidades aprendidas. No estágio inicial, as probabilidades de todas as ações são as mesmas e o modelo seleciona uma ação aleatoriamente. No processo de aprendizado, as probabilidades mudarão e a escolha das ações será mais consciente.

 

Dmitry, olá. Quantos ciclos foram necessários, como o Nikolay descreveu acima, para obter um resultado positivo estável?

E outra coisa interessante é que, se um Expert Advisor aprender para o período atual e se, por exemplo, em um mês ele precisar ser treinado novamente levando em conta os novos dados, ele será treinado novamente por completo ou antes de aprender? O processo de treinamento será comparável ao inicial ou muito mais curto e rápido? E também, se tivermos treinado um modelo em EURUSD, para trabalhar com GBPUSD ele será retreinado tanto quanto o inicial ou será mais rápido apenas antes do treinamento? Essa pergunta não se refere a esse seu artigo específico, mas a todos os seus Expert Advisors que trabalham com o princípio do aprendizado por reforço.

 

Bom dia.

Dimitri, obrigado por seu trabalho.

Gostaria de esclarecer a todos...

O que Dimitri está postando não é um "Graal".

É um exemplo clássico de um problema acadêmico, que implica a preparação para atividades de pesquisa científica de natureza teórica e metodológica.

E todo mundo quer ver um resultado positivo em sua conta, aqui e agora....

Dmitry nos ensina a resolver o (nosso/meu/seu/seu) problema por meio de todos os métodos apresentados por Dmitry.

A Popular AI (GPT) tem mais de 700 milhões de parâmetros!!!! Quanto custa essa IA?

Se você quiser obter um bom resultado, troque ideias (adicione parâmetros), forneça resultados de testes etc.

Crie uma sala de bate-papo separada e "obtenha" o resultado lá. Você pode se gabar aqui :-), mostrando assim a eficácia do trabalho de Dmitry...

 
Oleg_Filatov resultados de testes etc.

Crie uma sala de bate-papo separada e "obtenha" o resultado lá. Você pode se gabar aqui :-), mostrando assim a eficácia do trabalho de Dmitry...

Amigo, ninguém está esperando o graal aqui! Eu só gostaria de ver que o que Dmitriy apresenta realmente funciona. Não pelas palavras de Dmitry em seus artigos (todos os artigos dele têm resultados quase positivos), mas em meu computador. Baixei o Expert Advisor dele a partir deste artigo e já fiz 63 ciclos de treinamento (coleta de dados -> treinamento). E ele ainda está perdendo dinheiro. Durante todos os 63 ciclos, houve apenas algumas coletas de dados, quando, de 50 novos exemplos, havia de 5 a 6 positivos. Todo o resto é negativo. Como posso ver que ele realmente funciona?

Perguntei a Dmitriy na postagem acima e ele não respondeu nada. O mesmo problema em outros artigos - nenhum resultado, não importa o quanto você treine.....

Amigo, se você obteve um resultado estável, então escreva quantos ciclos fez antes do resultado estável, por exemplo, neste artigo? Se for necessário alterar, o que alterar para ver o resultado em seu computador, apenas no testador? Não é um graal, mas pelo menos para ver se funciona...?

 
Oleg_Filatov resultados de testes, etc.

Crie um CHAT separado e "obtenha" o resultado lá. Você pode se gabar aqui :-), mostrando assim a eficácia do trabalho de Dmitry...

Aproveite <3

Aqui estão os parâmetros: (com base em Dmitry e em algumas pesquisas.)
// Parâmetros de entrada para RSI
grupo de entrada "---- RSI ----"
input int RSIPeriod = 14; // Período
input ENUM_APPLIED_PRICE RSIPrice = PRICE_CLOSE; // Preço aplicado

// Parâmetros de entrada para CCI
grupo de entrada "---- CCI ----"
input int CCIPeriod = 14; // Período
input ENUM_APPLIED_PRICE CCIPrice = PRICE_TYPICAL; // Preço aplicado

// Parâmetros de entrada para ATR
grupo de entrada "---- ATR ----"
input int ATRPeriod = 14; // Período

// Parâmetros de entrada para MACD
grupo de entrada "---- MACD ----"
input int FastPeriod = 12; // Rápido
input int SlowPeriod = 26; // Lento
input int SignalPeriod = 9; // Sinal
input ENUM_APPLIED_PRICE MACDPrice = PRICE_CLOSE; // Preço aplicado

// Parâmetros de entrada para Momentum
grupo de entrada "---- Momentum ----"
input int MomentumPeriod = 14; // Período para o Momentum
input ENUM_APPLIED_PRICE AppliedPrice = PRICE_CLOSE; // Preço aplicado para o Momentum

// Parâmetros de entrada para SAR
grupo de entrada "---- SAR ----"
input float SARStep = 0.02f; // Passo do SAR
input float SARMaximum = 0,2f; // SAR máximo

// Parâmetros de entrada para bandas
grupo de entrada "---- Bands ----"
input int BandsPeriod = 20; // Período para Bands
input int BandsDeviation = 2,0; // Desvio das bandas
input int BandsShift = 0; // Deslocamento das bandas

#include "FQF.mqh"
//---
#define HistoryBars 72 //Profundidade do histórico
#define BarDescr 14 //Elementos para descrição de 1 barra
#define AccountDescr 12 //Descrição da conta
#define NActions 6 //Número de ações possíveis
#define NRewards 5 //Número de prêmios
#define EmbeddingSize 64
#define Buffer_Size 6500
#define DiscFactor 0.99f
#define FileName "zJimReaper_NNNM_Neural_Network_"
#define LatentLayer 11
#define LatentCount 2048
#definir SamplLatentStates 32
#definir MaxSL 1000
#definir MaxTP 1000
#definir MaxReplayBuffer 500
#definir StartTargetIteration 50000
#define fCAGrad_C 0.5f
#definir iCAGrad_Iters 15
#define KNN 32
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CreateDescriptions(CArrayObj *actor, CArrayObj *critic, CArrayObj *convolution)
{
//---
CLayerDescription *descr;
//---
if(!actor)
{
ator = new CArrayObj();
se(!ator)
return false;
}
if(!critic)
{
critic = new CArrayObj();
se(!crítico)
return false;
}
if(!convolution)
{
convolution = new CArrayObj();
se(!convolução)
return false;
}
//--- Ator
ator.Clear();
//--- Camada de entrada
Se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronBaseOCL;
int prev_count = descr.count = (HistoryBars * BarDescr);
descr.activation = None;
descr.optimisation = ADAM;
if(!actor.Add(descr))
{
excluir descr;
return false;
}
//--- camada 1
se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronBatchNormOCL;
descr.count = prev_count;
descr.batch = 1000;
descr.activation = None;
descr.otimização = ADAM;
se(!ator.Add(descr))
{
excluir descr;
return false;
}
//--- camada 2
se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronConvOCL;
prev_count = descr.count = BarDescr;
descr.window = HistoryBars;
descr.step = HistoryBars;
int prev_wout = descr.window_out = HistoryBars / 2;
descr.activation = LReLU;
descr.otimização = ADAM;
se(!ator.Add(descr))
{
excluir descr;
return false;
}
//--- camada 3
se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronConvOCL;
prev_count = descr.count = prev_count - 1;
descr.window = 7;
descr.step = 3;
descr.window_out = 32;
descr.activation = LReLU;
descr.otimização = ADAM;
se(!ator.Add(descr))
{
excluir descr;
return false;
}
//--- camada 4
se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronConvOCL;
prev_count = descr.count = prev_count - 1;
descr.window = 5;
descr.step = 2;
descr.window_out = 16;
descr.activation = LReLU;
descr.otimização = ADAM;
se(!ator.Add(descr))
{
excluir descr;
return false;
}

O tamanho da mensagem não deve exceder 64.000 caracteres

 


//--- camada 5
se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronConvOCL;
prev_count = descr.count = prev_count - 1;
descr.window = 3;
descr.step = 1;
descr.window_out = 8;
descr.activation = LReLU;
descr.otimização = ADAM;
se(!ator.Add(descr))
{
excluir descr;
return false;
}
//--- camada 6
se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronConvOCL;
prev_count = descr.count = BarDescr;
descr.window = HistoryBars;
descr.step = HistoryBars;
prev_wout = descr.window_out = HistoryBars / 2;
descr.activation = LReLU;
descr.otimização = ADAM;
se(!ator.Add(descr))
{
excluir descr;
return false;
}
//--- camada 7
se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronConvOCL;
prev_count = descr.count = prev_count;
descr.window = prev_wout;
descr.step = prev_wout;
descr.window_out = 32;
descr.activation = LReLU;
descr.otimização = ADAM;
se(!ator.Add(descr))
{
excluir descr;
return false;
}
//--- camada 8
se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronBaseOCL;
descr.count = 2 * LatentCount;
descr.optimisation = ADAM;
descr.activation = LReLU;
se(!ator.Add(descr))
{
excluir descr;
return false;
}
//--- camada 9
se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronBaseOCL;
prev_count = descr.count = LatentCount;
descr.activation = LReLU;
descr.otimização = ADAM;
se(!ator.Add(descr))
{
excluir descr;
return false;
}
//--- camada 10
se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronConcatenate;
descr.count = 4 * LatentCount;
descr.window = prev_count;
descr.step = AccountDescr;
descr.optimisation = ADAM;
descr.activation = SIGMOID;
se(!actor.Add(descr))
{
excluir descr;
return false;
}
//--- camada 11
se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronVAEOCL;
descr.count = 2 * LatentCount;
descr.optimise = ADAM;
se(!actor.Add(descr))
{
excluir descr;
return false;
}
//--- camada 12
se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronBaseOCL;
descr.count = 2 * LatentCount;
descr.activation = LReLU;
descr.optimisation = ADAM;
se(!ator.Add(descr))
{
excluir descr;
return false;
}
//--- camada 13
se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronBaseOCL;
descr.count = LatentCount;
descr.activation = LReLU;
descr.optimisation = ADAM;
se(!ator.Add(descr))
{
excluir descr;
return false;
}
//--- camada 14
se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronBaseOCL;
descr.count = LatentCount;
descr.activation = LReLU;
descr.optimisation = ADAM;
se(!ator.Add(descr))
{
excluir descr;
return false;
}
//--- camada 15
se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronBaseOCL;
descr.count = 2 * NActions;
descr.activation = SIGMOID;
descr.optimisation = ADAM;
se(!ator.Add(descr))
{
excluir descr;
return false;
}
//--- camada 16
se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronVAEOCL;
descr.count = NActions;
descr.optimise = ADAM;
se(!actor.Add(descr))
{
excluir descr;
return false;
}
//--- Crítico
critic.Clear();
//--- Camada de entrada
Se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronBaseOCL;
prev_count = descr.count = 2 * LatentCount;
descr.activation = None;
descr.optimisation = ADAM;
se(!critic.Add(descr))
{
excluir descr;
return false;
}
//--- camada 1
se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronConcatenate;
descr.count = 2 * LatentCount;
descr.window = prev_count;
descr.step = NActions;
descr.optimisation = ADAM;
descr.activation = LReLU;
se(!critic.Add(descr))
{
excluir descr;
return false;
}
//--- camada 2
se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronBaseOCL;
descr.count = 2 * LatentCount;
descr.activation = LReLU;
descr.optimisation = ADAM;
se(!critic.Add(descr))
{
excluir descr;
return false;
}
//--- camada 3
se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronBaseOCL;
descr.count = LatentCount;
descr.activation = LReLU;
descr.optimisation = ADAM;
if(!critic.Add(descr))
{
excluir descr;
return false;
}
//--- camada 4
se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronBaseOCL;
descr.count = LatentCount;
descr.activation = LReLU;
descr.optimisation = ADAM;
if(!critic.Add(descr))
{
excluir descr;
return false;
}
//--- camada 5
se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronBaseOCL;
descr.count = NRewards;
descr.optimisation = ADAM;
descr.activation = None;
se(!critic.Add(descr))
{
excluir descr;
return false;
}
//--- Convolução
// Definir parâmetros comuns
int input_size = (HistoryBars * BarDescr) + AccountDescr;
int num_actions = NActions;
int embedding_size = EmbeddingSize;
// Criar uma rede neural
convolution.Clear();
// Camada de entrada 0
Se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronBaseOCL;
descr.count = 4 * input_size;
descr.activation = None;
descr.optimisation = ADAM;
se (!convolution.Add(descr))
{
excluir descr;
return false;
}
// Camada 1
Se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronBaseOCL;
descr.count = 2 * LatentCount;
descr.window = 2 * input_size;
descr.step = 2 * num_actions;
descr.activation = SIGMOID;
descr.optimisation = ADAM;
se (!convolution.Add(descr))
{
excluir descr;
return false;
}
// Camada 2
Se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronBaseOCL;
descr.count = LatentCount;
descr.window = input_size;
descr.step = num_actions;
descr.activation = SIGMOID;
descr.optimisation = ADAM;
se (!convolution.Add(descr))
{
excluir descr;
return false;
}
// Camadas convolucionais
for (int i = 0; i < 6; i++)
{
se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronConvOCL;
descr.count = 2 * LatentCount / (1 << i); // Reduzir a contagem pela metade a cada camada
descr.window = 64;
descr.step = 64;
descr.window_out = 32 / (1 << i); // Reduzir a window_out pela metade
descr.activation = LReLU;
descr.optimisation = ADAM;
se (!convolution.Add(descr))
{
excluir descr;
return false;
}
}
// Camada de saída
Se (!(descr = new CLayerDescription())) return false;
descr.type = defNeuronBaseOCL;
descr.count = embedding_size;
descr.activation = LReLU;
descr.optimisation = ADAM;
se (!convolution.Add(descr))
{
excluir descr;
return false;
}
// A rede foi criada com sucesso
return true;
}
#ifndef Study
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool IsNewBar(void)
{
===CORTEI AS ÚLTIMAS PARTES porque os comentários são limitados a 64000 caracteres, mas você sabe o que fazer... =)
O comprimento da mensagem não deve exceder 64.000 caracteres

-----------------------------------------------------+