English Русский 中文 Español Deutsch 日本語
preview
Funcionalidades do assistente MQL5 que você precisa conhecer (Parte 02): Mapas de Kohonen

Funcionalidades do assistente MQL5 que você precisa conhecer (Parte 02): Mapas de Kohonen

MetaTrader 5Sistemas de negociação | 3 novembro 2022, 09:52
292 0
Stephen Njuki
Stephen Njuki

 

1. Introdução    

1.1 Continuando com esta série sobre o assistente MQL5, neste artigo nós vamos nos aprofundar nos Mapas de Kohonen. De acordo com o Wikipédia, eles são técnicas usadas para produzir uma representação de baixa dimensão (tipicamente bidimensional) de um conjunto de dados de dimensão superior, preservando a estrutura topológica dos dados. Este método foi sugerido por Teuvo Kohonen na década de 1980.

Em termos simples, os mapas de kohonen (também conhecidos como mapas auto-organizados) estão longe de sintetizar a complexidade sem perder a distinção do que é sumarizado. A síntese serve como uma forma de organização, daí o nome de auto-organização. Com os dados ou mapas reorganizados, nós temos, portanto, dois conjuntos de dados relacionados. Os dados originais de alta dimensão que servem como nossa entrada e a forma sintetizada (dados de baixa dimensão) que geralmente são, mas nem sempre, representados em duas dimensões como saída. Os dados de entrada são conhecidos, já os de saídas são desconhecidos, ou seja, o que está sendo 'estudado'.

Para um trader, se o objetivo deste artigo for centrar apenas nas séries de preços baseadas no tempo, os dados conhecidos (que nós chamaremos de dados de alimentação) a qualquer momento serão os preços restantes desse momento, enquanto os dados desconhecidos (que vamos chamar de dados functor) sendo aqueles à direita. A forma como classificamos os dados conhecidos e desconhecidos determina o respectivo número de dimensões para os dados de alimentação e do functor. Aqui, teremos que prestar a máxima atenção, pois isso dependerá em grande parte das opiniões do trader e de sua abordagem à negociação. 

1.2 Um equívoco comum sobre os mapas de Kohonen é que os dados functor devem ser uma imagem 2D como é exibido abaixo. As imagens como as que se encontram abaixo são frequentemente compartilhadas como representativas do que são os Mapas de Kohonen.

typical_image

Embora não esteja errado, eu quero destacar que o functor pode e talvez deva (para traders) ter uma única dimensão. Então, em vez de reduzir os nossos dados de alta dimensão a um mapa 2D, vamos mapeá-los em uma única linha.Os mapas de Kohonen, por definição, destinam-se a reduzir a dimensionalidade, então quero que levemos isso para o próximo nível neste artigo.O mapa de kohonen é diferente das redes neurais regulares tanto no número de camadas quanto no algoritmo subjacente. Ele é uma camada única (geralmente uma grade 2D linear, como mencionado anteriormente) de um conjunto de neurônios, em vez de múltiplas camadas. Todos os neurônios nesta camada que nós estamos nos referindo como functor se conectam aos dados de alimentação, mas não para si significando que os neurônios não são influenciados pelos pesos dos outros de maneira direta, e eles são atualizados apenas em relação aos dados de alimentação. A camada de dados do functor é frequentemente um mapa" que se organiza a cada iteração de treinamento dependendo dos dados de alimentação. Como tal, após o treinamento, cada neurônio tem dimensão ajustada ao peso na camada functor e isso permite calcular a distância euclidiana entre dois desses neurônios.

 

2. Criação da classe

2.1  Estrutura da classe

2.1.1 A classe abstrata Dimension é a primeira classe que nós vamos definir. Este código teria sido mais organizado se eu tivesse feito a maior parte dele em um arquivo separado e simplesmente o referenciado, mas eu quero cobrir isso junto com as classes money e trailing no próximo artigo, então, por enquanto, como no artigo anterior, todo o código estará no arquivo signal. As dimensões são sempre importantes nesta rede, já que elas influenciam fortemente a saída. Os dados de alimentação (as entradas) serão multidimensionais, como normalmente é o caso. Os dados do functor (as saídas) terão uma dimensão contrária à saída típica x e y. Com base na multidimensionalidade dos dados de alimentação e do functor, um tipo de dado ideal seria uma matriz do tipo double.

No entanto, seguindo a tendência de explorar a Biblioteca MQL5, nós utilizaremos uma lista de matrizes do tipo double em vez disso. Os dados de alimentação serão as alterações nas mínimas menos as alterações nas máximas em um espaço de uma barra, como nós usamos no artigo anterior. Como regra, as entradas são melhor selecionadas com base nos "insights" de um trader sobre o mercado e não devem ser adotadas e usadas por todos em uma conta real ou mesmo de teste. Cada trader deve modificar este código para permitir os seus próprios dados de entrada. Os dados do functor serão unidimensionais conforme indicado. No entanto, como ele também é uma lista, ele pode ser personalizado para adicionar mais dimensões. Para os nossos propósitos, nós vamos nos concentrar na mudança entre a abertura e o fechamento da barra mais recente. Mais uma vez, o assistente em MQL5 permite que você defina o que é uma barra selecionando o seu próprio período de tempo. A classe dimension herdará da interface double da lista na biblioteca de códigos em MQL5. Duas funções serão adicionadas a esta classe, chamadas, Get e Set. Como o próprio nome sugere, eles ajudam a recuperar e definir os valores na lista quando um índice é fornecido.

#include                        <Generic\ArrayList.mqh>
#include                        <Generic\HashMap.mqh>

#define                         SCALE 5

#define                         IN_WIDTH 2*SCALE
#define                         OUT_LENGTH 1

#define                         IN_RADIUS 100.0
#define                         OUT_BUFFER 10000

//
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class Cdimension                :  public CArrayList<double>
  {
    public:
        
      Cdimension()              {};
      ~Cdimension()             {};
        
     virtual double             Get(const int Index)                                    
                                {       
                                  double _value=0.0; TryGetValue(Index,_value); return(_value); 
                                };
     virtual void               Set(const int Index,double Value)       
                                {  
                                  Insert(Index,Value);                                                                                                                   
                                };
  };


2.1.2   A classe Feed herdará da classe dimension criada acima. Nenhuma função especial será adicionada aqui. Apenas o construtor especificará a capacidade da lista (análoga ao tamanho da matriz) e o tamanho padrão da nossa lista de dados de alimentação será 10.

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class Cfeed             : public Cdimension
 {
   public:
                
     Cfeed()            { Clear(); Capacity(IN_WIDTH);  };
     ~Cfeed()           {                               };
 };


2.1.3  A classe Functor será semelhante a classe feed, com apenas uma ressalva no seu tamanho. Como afirmado, nós consideraremos uma (não as duas usuais) dimensão para os nossos dados functor, portanto, o tamanho do conjunto será 1.

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class Cfunctor          : public Cdimension
 {
   public:
                
   Cfunctor()           { Clear(); Capacity(OUT_LENGTH); };
   ~Cfunctor()          {                                };
 };


2.1.4   A classe Neuron é onde o nosso código fica interessante. Nós vamos declará-lo como uma classe que herda de uma interface na biblioteca MQL5 que recebe dois tipos de dados personalizados. Uma chave e um valor. A interface do modelo em questão é a HashMap. E os dados personalizados digitados que nós usaremos serão as duas classes declaradas acima. Ou seja, a classe Feed como a nossa chave e a classe Functor como o nosso valor. Nós também não temos as funções, mas apenas ponteiros para as classes Feed, Functor e uma classe 'chave-valor' do mesmo. O objetivo desta classe, como o nome sugere, é definir o neurônio. O neurônio é nossa unidade de dados, pois inclui o tipo de dados de entrada (dados de alimentação) e o tipo de dados de saída (dados do functor). São os dados de alimentação de um neurônio que são combinados com os neurônios já treinados para projetar o que o functor poderia ser. Além disso, os neurônios mapeados têm os seus dados functor ajustados sempre que um novo neurônio está treinando.

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class Cneuron           : public CHashMap<Cfeed*,Cfunctor*>
 {
   public:
                
    double              weight;
                        
    Cfeed               *fd;
    Cfunctor            *fr;
                        
    CKeyValuePair
    <
    Cfeed*,
    Cfunctor*
    >                   *ff;
                        
    Cneuron()           {
                          weight=0.0;
                          fd = new Cfeed();
                          fr = new Cfunctor();
                          ff = new CKeyValuePair<Cfeed*,Cfunctor*>(fd,fr);
                          Add(ff);
                        };
                                                                        
   ~Cneuron()           {
                          ZeroMemory(weight);
                          delete fd;
                          delete fr;
                          delete ff;
                        };
 };


2.1.5   A classe abstrata Layer é o que segue a seguir. Ela herda de um modelo de lista da classe neuron, possuindo um objeto - um ponteiro do neurônio. Sendo uma classe abstrata, esse ponteiro do neurônio deve ser usado por classes que herdam dessa classe. Existem duas dessas classes, chamadas de camada de entrada e camada de saída. A rigor, os mapas de Kohonen não devem ser classificados como redes neurais, pois eles não possuem conexões de feed forward com pesos e back propagation. Alguns proponentes acham que eles são apenas um tipo diferente. 

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class Clayer            : public CArrayList<Cneuron*>
 {
   public:
                
    Cneuron             *n;
                
    Clayer()            { n = new Cneuron();     };
    ~Clayer()           { delete n;              };
 };


2.1.6   A classe Input Layer  herda da classe abstrata layer. É onde os valores dos dados de alimentação ao vivo e recentes são armazenados quando a rede está em execução. Em vez de ser uma camada típica com vários neurônios, ele apresentará um único neurônio que possui os dados de alimentação e o functor mais recentes, portanto, seu tamanho será 1.

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class Cinput_layer      : public Clayer
 {
   public:
                
   static const int     size;
                        
    Cinput_layer()      {
                          Clear();
                          Capacity(Cinput_layer::size);
                          for(int s=0; s<size; s++)
                          {
                            n = new Cneuron();
                            Add(n);
                          }
                        }
    ~Cinput_layer()     {};
 };
 const int Cinput_layer::size=1;


2.1.7  A classe Output Layer também herda da classe layer, mas ela serve como o nosso mapa, pois os neurônios "treinados" são armazenados aqui. A porção de dados functor dos neurônios nesta camada é equivalente a uma imagem ou um mapa típico do SOM. Seu tamanho será inicialmente de 10.000 e será incrementado de acordo com a quantia dos novos neurônios que são treinados.

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class Coutput_layer      : public Clayer
 {
   public:
                
    int                  index;
    int                  size;
                        
    Coutput_layer()      {
                           index=0;
                           size=OUT_BUFFER;
                           Clear();
                           Capacity(size);
                           for(int s=0; s<size; s++)
                           {
                             n = new Cneuron();
                             Add(n);
                           }
                         };
                                                                        
    ~Coutput_layer()     {
                           ZeroMemory(index);
                           ZeroMemory(size);
                         };
 };


2.1.8  A classe Network parecida com a classe neuron também herda do modelo da interface HashMap. Seus tipos de dados de chave e valor são a classe da camada de entrada e a classe da camada de saída. Ele tem o maior número de funções (9) não apenas para obter o tamanho da lista, mas também para recuperar e atualizar os neurônios nas respectivas camadas.

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class Cnetwork           : public CHashMap<Cinput_layer*,Coutput_layer*>
 {
   public:
                
     Cinput_layer        *i;
     Coutput_layer       *o;
                        
     CKeyValuePair
     <
     Cinput_layer*,
     Coutput_layer*
     >                   *io;
                        
     Cneuron             *i_neuron;
     Cneuron             *o_neuron;
                        
     Cneuron             *best_neuron;
                        
     Cnetwork()          {
                           i = new Cinput_layer();
                           o = new Coutput_layer();
                           io = new CKeyValuePair<Cinput_layer*,Coutput_layer*>(i,o);
                           Add(io);
                                                                                
                           i_neuron = new Cneuron();
                           o_neuron = new Cneuron();
                                                                                
                           best_neuron = new Cneuron();
                         };
                                                                        
     ~Cnetwork()         {
                           delete i;
                           delete o;
                           delete io;
                           delete i_neuron;
                           delete o_neuron;
                           delete best_neuron;
                         };
                        
      virtual int        GetInputSize()
                         {
                           TryGetValue(i,o);
                           return(i.size);
                         };
                        
      virtual int        GetOutputIndex()
                         {
                           TryGetValue(i,o);
                           return(o.index);
                         };
                        
      virtual void       SetOutputIndex(const int Index)
                         {
                           TryGetValue(i,o);
                           o.index=Index;
                           TrySetValue(i,o);
                         };
                        
      virtual int        GetOutputSize()
                         {
                           TryGetValue(i,o);
                           return(o.size);
                         };
                        
      virtual void       SetOutputSize(const int Size)
                         {
                           TryGetValue(i,o);
                           o.size=Size;
                           o.Capacity(Size);
                           TrySetValue(i,o);
                         };
                        
      virtual void       GetInNeuron(const int NeuronIndex)
                         {
                           TryGetValue(i,o);
                           i.TryGetValue(NeuronIndex,i_neuron);
                         };
                        
      virtual void       GetOutNeuron(const int NeuronIndex)
                         {
                           TryGetValue(i,o);
                           o.TryGetValue(NeuronIndex,o_neuron);
                         };
                        
      virtual void       SetInNeuron(const int NeuronIndex)
                         {
                           i.TrySetValue(NeuronIndex,i_neuron);
                         };
                        
      virtual void       SetOutNeuron(const int NeuronIndex)
                         {
                           o.TrySetValue(NeuronIndex,o_neuron);
                         };
 };


2.1.9   A classe Map é a última classe guarda chuva. Ela chama uma instância da classe network e inclui outras variáveis para treinar os neurônios e obter o melhor neurônio correspondente para a network.

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class Cmap
  {
    public:
                        
      Cnetwork               *network;
                        
      static const double     radius;
      static double           time;
                        
      double                  QE;       //proxy for Quantization Error
      double                  TE;       //proxy for Topological Error
                        
      datetime                refreshed;
                        
      bool                    initialised;
                        
      Cmap()                  {
                                network = new Cnetwork();
                                                                                        
                                initialised=false;
                                                                                        
                                time=0.0;
                                                                                        
                                QE=0.50;
                                TE=5000.0;
                                                                                        
                                refreshed=D'1970.01.05';
                               };
                                                                                
      ~Cmap()                  {
                                 ZeroMemory(initialised);
                                                                                        
                                 ZeroMemory(time);
                                                                                        
                                 ZeroMemory(QE);
                                 ZeroMemory(TE);
                                                                                        
                                 ZeroMemory(refreshed);
                               };
 };
 const double Cmap::radius=IN_RADIUS;
 double Cmap::time=10000/fmax(1.0,log(IN_RADIUS));

 


2.2. Topologia

2.2.1 O treinamento de neurônios é o processo de aprendizagem competitiva de ajuste dos pesos dos functors dos neurônios existentes na camada de saída e a adição de um novo neurônio treinador. A taxa na qual esses pesos são ajustados e, mais importante, o número de iterações necessárias para ajustar esses pesos, são parâmetros muito sensíveis na determinação da eficácia da rede. A cada iteração de ajuste dos pesos, um novo raio menor é calculado. Refiro-me a este raio como o erro-functor (ele não deve ser confundido com o erro topológico SOM), mas a maioria se refere a ele como o raio da vizinhança medido pela distância euclidiana. Eu escolho 'erro', pois este é um parâmetro que precisa ser minimizado para obter os melhores resultados da rede. Quanto mais iterações forem realizadas, menor será o erro-Functor. Além do número de iterações, a taxa de aprendizado precisa ser reduzida gradativamente de um número próximo a um para zero.

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CSignalKM::NetworkTrain(Cmap &Map,Cneuron &TrainNeuron)
  {
    Map.TE=0.0;

    int _iteration=0;
    double _training_rate=m_training_rate;

    int _err=0;
    double _functor_error=0.0;

    while(_iteration<m_training_iterations)
    {
      double _current_radius=GetTrainingRadius(Map,_iteration);

      for(int i=0; i<=Map.network.GetOutputIndex(); i++)
      {
        Map.network.GetOutNeuron(i);
        double _error = EuclideanFunctor(TrainNeuron,Map.network.o_neuron);

        if(_error<_current_radius)
        {
          _functor_error+=(_error);
          _err++;

          double _remapped_radius = GetRemappedRadius(_error, _current_radius);

          SetWeights(TrainNeuron,Map.network.o_neuron,_remapped_radius,_training_rate);

          Map.network.SetOutNeuron(i);
        }
      }

      _iteration++;
      _training_rate=_training_rate*exp(-(double)_iteration/m_training_iterations);
    }

    int
    _size=Map.network.GetOutputSize(),
    _index=Map.network.GetOutputIndex();
    Map.network.SetOutputIndex(_index+1);
    if(_index+1>=_size)
    {
      Map.network.SetOutputSize(_size+OUT_BUFFER);
    }

    Map.network.GetOutNeuron(_index+1);
    for(int w=0; w<IN_WIDTH; w++)
    {
      Map.network.o_neuron.fd.Set(w,TrainNeuron.fd.Get(w));
    }
    
    for(int l=0; l<OUT_LENGTH; l++)
    {
      Map.network.o_neuron.fr.Set(l,TrainNeuron.fr.Get(l));
    }

    Map.network.SetOutNeuron(_index+1);

    if(_err>0)
    {
      _functor_error/=_err;
      Map.TE=_functor_error*IN_RADIUS;
    }
  }


2.2.2 O erro topológico é um atributo chave nos mapas de Kohonen. Eu tomo isso como uma medida do quão perto a camada de saída está do seu objetivo de longo prazo. Lembre-se, a cada treinamento, os neurônios da camada de saída se adaptam ao resultado real ou pretendido, então a questão é como nós medimos esse progresso. A resposta para isso é que, se nós estivermos preservando mais a camada de saída, nós estaremos mais próximos desse alvo. Para os propósitos deste artigo, eu farei com que o erro-functor atue como um proxy para ele.


2.3. Quantização

2.3.1 O mapeamento de neurônios é um processo de encontrar os pesos do functor que melhor se ajustam a um neurônio para o qual apenas os dados de alimentação estão presentes. Isso é feito através da busca do neurônio na camada de saída com a menor distância euclidiana dos dados de alimentação do neurônio, para o qual nenhum dado functor é conhecido. Assim como no treinamento, eu refiro-me a essa distância como o erro de alimentação. Novamente, quanto menor nosso valor, mais confiável deve ser a rede.

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CSignalKM::NetworkMapping(Cmap &Map,Cneuron *MapNeuron)
  {
    Map.QE=0.0;
    
    Map.network.best_neuron = new Cneuron();

    int _random_neuron=rand()%Map.network.GetOutputIndex();

    Map.network.GetInNeuron(0);
    Map.network.GetOutNeuron(_random_neuron);

    double _feed_error = EuclideanFeed(Map.network.i_neuron,Map.network.o_neuron);

    for(int i=0; i<Map.network.GetOutputIndex(); i++)
    {
      Map.network.GetOutNeuron(i);

      double _error = EuclideanFeed(Map.network.i_neuron,Map.network.o_neuron);

      if(_error < _feed_error)
      {
        for(int w=0; w<IN_WIDTH; w++)
        {
          Map.network.best_neuron.fd.Set(w,Map.network.o_neuron.fd.Get(w));
        }

        for(int l=0; l<OUT_LENGTH; l++)
        {
          Map.network.best_neuron.fr.Set(l,Map.network.o_neuron.fr.Get(l));
        }

        _feed_error = _error;
      }
    }

    Map.QE=_feed_error/IN_RADIUS;
}


2.3.2 O Erro de Quantização é outro atributo crítico nos mapas de Kohonen que não possui uma definição concisa na minha opinião. Minha opinião é que o erro está na transformação dos dados de alta dimensão para a saída de baixa dimensão. No nosso caso, aqui estaria o erro na conversão dos dados de alimentação para o functor. Para os fins deste artigo, eu farei com que o erro de alimentação funcione como um proxy para ele.


 

3. Desenvolvimento com o Assistente MQL5

3.1  O desenvolvimento com o assistente é bem direto. O único cuidado que eu tenho aqui é de começar a testar em grandes intervalos de tempo primeiro, já que as 10.000 iterações ideais de treinamento por barra levarão algum tempo ao treiná-lo por um período significativo.

wizard_1

 


 

4. Testando no Strategy Tester

4.1 As entradas padrão para os nossos testes investigará a sensibilidade do nosso proxy de erro de quantização (QE) e o proxy de erro topológico (TE). Nós veremos os dois cenários. Primeiro, nós vamos testar com valores mais conservadores com QE e TE em 0.5 e 12.5; em seguida nós vamos testar essas entradas com 0.75 e 25.0 respectivamente.

criteria_1

opções conservadoras


criteria_2

opções agressivas

 

 

Não são muitas entradas. Nós temos 'training read' que determina se nós devemos ou não ler um arquivo de treinamento antes da inicializá-lo. Se este arquivo estiver ausente, o expert não validará. Nós também temos a 'training write' que, como o nome sugere, determina se um arquivo de aprendizado deve ser gravado assim que o expert for desinicializado. O treinamento sempre ocorre quando o expert está em execução. A opção de treinar apenas e não negociar é definida pelo parâmetro de entrada 'training only'. Os outros dois parâmetros significativos para os mapas de Kohonen são o 'training rate' (também conhecido como taxa de aprendizado) e as iterações de treinamento. Geralmente, quanto maior esses dois forem (a taxa de treinamento é limitada a 1.0), um melhor desempenho deve ser esperado, no entanto, isso terá um maior custo de tempo e de recursos da CPU. 

O expert foi treinado no par EURJPY no período em forma de V de 01.10.2018 até 01.06.2021 e testado a partir da data final do treinamento até a data atual.

A opção conservadora está no relatório abaixo:

report_1

E esta é a curva do patrimônio:

curve_1


No entanto, a opção mais agressiva gerou o seguinte relatório:

report_2

 

E esta é a curva do patrimônio:

curve_2

 

Claramente, mais testes e ajustes são necessários em relação ao dimensionamento do risco e da posição, mas para um sistema que é treinado em um tempo tão curto, ele é promissor. Comparando os dois cenários acima, porém, parece que a opção mais conservadora não é suficientemente recompensada, dado que o valor do índice de Sharpe foi de 0.43 é quase metade do valor 0.85 em mais negociações. São necessários mais estudos antes de usar e como sempre, além de personalizar os dados de alimentação e functor para o estilo de como ele negocia; testes preliminares sempre devem ser feitos nos dados de ticks reais da sua corretora por longos períodos de tempo significativos antes de seu uso efetivo.

 

5. Conclusão

5.1 O Assistente MQL5 é claramente uma ferramenta muito ágil quando se trata de desenvolver sistemas de negociação em uma janela de tempo apertada. Para este artigo, nós exploramos a opção dos mapas de Kohonen que portam os dados de alimentação multidimensionais da série temporal de preço em uma única dimensão que varia de -1.0 a 1.0. Embora isso não seja uma prática comum, essa abordagem defende a própria essência dos mapas de Kohonen, que é reduzir a complexidade e facilitar a tomada de decisões. Nós também fizemos isso enquanto nós mostramos mais código da biblioteca MQL, como listas de matrizes e os mapas hash. Espero que tenha gostado. Obrigado por ler!

Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/11154

Arquivos anexados |
Aprendendo a construindo um EA que opera de forma automática (Parte 04): Gatilhos manuais (I) Aprendendo a construindo um EA que opera de forma automática (Parte 04): Gatilhos manuais (I)
Aprenda como criar um EA que opera de forma automática, isto de forma simples e o mais seguro possível ...
Redes neurais de maneira fácil (Parte 21): Autocodificadores variacionais (VAE) Redes neurais de maneira fácil (Parte 21): Autocodificadores variacionais (VAE)
No último artigo, analisamos o algoritmo do autocodificador. Como qualquer outro algoritmo, tem suas vantagens e desvantagens. Na implementação original, o autocodificador executa a tarefa de separar os objetos da amostra de treinamento o máximo possível. E falaremos sobre como lidar com algumas de suas deficiências neste artigo.
Ciência de Dados e Aprendizado de Máquina (Parte 06): Gradiente Descendente Ciência de Dados e Aprendizado de Máquina (Parte 06): Gradiente Descendente
O gradiente descendente desempenha um papel significativo no treinamento das redes neurais e muitos algoritmos de aprendizado de máquina. Ele é um algoritmo rápido e inteligente, apesar do seu trabalho impressionante, ele ainda é mal interpretado por muitos cientistas de dados, vamos ver do que ele se trata.
Redes neurais de maneira fácil (Parte 20): autocodificadores Redes neurais de maneira fácil (Parte 20): autocodificadores
Continuamos a estudar algoritmos de aprendizado não supervisionado. Talvez você como o leitor possa ter dúvidas sobre se as publicações recentes se encaixam no tópico de redes neurais. Neste novo artigo, voltamos ao uso de redes neurais.