Coletânea Python do ZERO às Redes Neurais Artificiais

Fernando Feltrin · Capítulo 276 de 287

Páginas do PDF

Coletânea Python do ZERO às Redes Neurais Artificiais

Previsão de Séries Temporais – Bolsa Dataset

Para entendermos de fato, e na prática, o que é uma rede neural artificial recorrente, vamos usar de uma das principais aplicações deste modelo, a de previsão de preços de ações.

O modelo que estaremos criando se aplica a todo tipo de previsão com base em série temporal, em outras palavras, sempre que trabalharmos sobre uma base de dados que oferece um padrão em relação a tempo, seja horas, dias, semanas, meses, podemos fazer previsões do futuro imediato. Para isso, usaremos de uma base real e atual extraída diretamente do site Yahoo Finanças.

 

Inicialmente acessamos o site do Yahoo Finanças, usando a própria ferramenta de busca do site pesquisamos por Petrobras.

A base que usaremos é a PETR4.SA.

 

Na página dedicada a Petrobras, é possível acompanhar a atualização de todos os índices.

Por fim clicando em Dados Históricos é possível definir um intervalo de tempo e fazer o download de todos os dados em um arquivo formato .csv. Repare que a base que usaremos possui como informações a data (dia), o valor de abertura da ação, o valor mais alto atingido naquele dia, assim como o valor mais baixo e seu valor de fechamento. Essas informações já são mais do que suficientes para treinar nossa rede e realizarmos previsões a partir dela.

Apenas lembrando que um ponto importante de toda base de dados é seu volume de dados, o interessante para este modelo é você em outro momento baixar uma base de dados com alguns anos de informação adicional, dessa forma o aprendizado da rede chegará a melhores resultados.

 

Como sempre, o processo se inicia com as devidas importações. Para nosso modelo importamos como de costume, as bibliotecas numpy e pandas, assim como as ferramentas Sequential, Dense e Dropout de seus respectivos módulos da biblioteca keras.

Em seguida, como de costume, criamos nossa variável de nome base que receberá todos os dados importados pela função .read_csv( ) de nosso arquivo baixado do site Yahoo Finanças.

 

Na sequência realizamos um breve polimento dos dados, primeiro, excluindo todos registros faltantes de nossa base via função .dropna( ), em seguida criamos nossa variável de nome base_treino que recebe pelo método .iloc[ ].values todos os dados de todas as linhas, e os dados da coluna 1 (lembrando que fora a indexação criada pela IDE, a leitura de todo arquivo .csv começa em índice 0), referente aos valores de abertura das ações.

 

Selecionando e executando o bloco de código anterior podemos verificar que as variáveis foram criadas corretamente, delas, base_treino agora possui 1242 registros divididos em apenas uma categoria (valor de abertura da ação).

 

Em seguida realizaremos uma etapa de polimento desses dados bastante comum a este tipo de rede neural, onde normalizaremos os dados dentro de um intervalo numérico que fique mais fácil a visualização dos mesmos assim como a aplicação de certas funções.

Para isso criamos uma variável de nome normalizador que inicializa a ferramenta MinMaxScaler, nela, passamos como parâmetro feature_range = (0,1), o que em outras palavras significa que por meio dessa ferramenta transformaremos nossos dados em um intervalo entre 0 e 1, números entre 0 e 1.

Logo após criamos nossa variável base_treino_normalizada que aplica essa transformação sobre os dados de base_treino por meio da função .fit_transform( ).

 

Selecionado e executado o bloco de código anterior podemos visualizar agora nossa base de dados de treino normalizados como números do tipo float32, categorizados em um intervalo entre 0 e 1.

 

Uma vez terminado o polimento de nossos dados de entrada, podemos realizar as devidas separações e conversões para nossos dados de previsão e de saída, que faremos a comparação posteriormente para avaliação da performance do modelo. Inicialmente criamos as variáveis previsores e preco_real com listas vazias como atributo. Em seguida criamos um laço de repetição que percorrerá nossa variável base_treino_normalizada separando os primeiros 90 registros (do número 0 ao 89) para que a partir dela seja encontrado o padrão que usaremos para nossas previsões.

Por fim, ainda dentro desse laço, pegamos os registros de nº 90 para usarmos como parâmetro, como preço real a ser previst pela rede. Fora do laço, realizamos as conversões de formato, transformando tudo em array do tipo numpy e definindo que a posição 0 na lista de previsores receberá os 1152 registros, enquanto a posição 1 receberá as informações referentes aos 90 dias usados como previsão.

 

Uma vez encerrado o processo de tratamento dos dados, é possível conferir cada variável assim como seus valores via explorador de variáveis, e mais importante que isso, agora podemos dar início a criação do nosso modelo de rede neural recorrente.

 

Como de praxe, não será necessário criar manualmente toda a estrutura de nossa rede neural, mas criar a partir de uma ferramenta que possui essa estrutura pré-pronta e configurada. Par isso, realizamos a importação da ferramenta LSTM do módulo layers da biblioteca keras.

Dando início a codificação da estrutura da rede, criamos inicialmente nossa variável regressor que inicializa Sequential sem parâmetros. Na sequência adicionamos a camada LSTM, que por sua vez tem como parâmetros input_shape que recebe os dados referentes aos registros e intervalo de tempo de nossa variável previsores, retornando essa sequência (recorrência) via parâmetro return_sequences definido como True (False será sem recorrência, em outras palavras, sem atualização de dados no próprio neurônio da camada) e por fim units especificando quantos neurônios estarão na primeira camada oculta.

Em seguida é adicionada a primeira camada de Dropout, que por sua vez, descartará 30% dos neurônios dessa camada aleatoriamente. Logo após criamos mais uma camada LSTM onde há recorrência, agora com tamanho de 50 neurônios. A seguir é adicionada mais uma camada Dropout, descartando mais 30% dos neurônios da camada, mais uma camada LSTM agora sem recorrência, ou seja, os valores que preencherem os neurônios dessa camada agora são estáticos, servindo apenas como referência para camada subsequente.

Por fim é criada uma camada Dense, onde há apenas 1 neurônio de saída e seu método de ativação é ‘linear’, que em outras palavras é uma função de ativação nula, o valor que chegar até esse neurônio simplesmente será replicado.

Como de costume, criadas as camadas estruturais da rede, hora de criar a camada de compilação da mesma e a que a alimentará, colocando a rede em execução. Sendo assim criamos nossa camada de compilação onde como parâmetros temos optimizer = ‘rsmprop’, método de otimização muito usado nesses tipos de modelo em função de oferecer uma descida de gradiente bastante precisa quando trabalhada uma série temporal, loss definimos como ‘mean_squared_error’, já usada em outro modelo, onde os valores de erro são elevados ao quadrado, dando mais peso aos erros e buscando assim melhor precisão, por fim metrics é parametrizado com nosso já conhecido ‘mean_absolute_error’. Para alimentação da rede via camada .fit( ) passamos todos os dados contidos em previsores, preco_real, assim como definimos que a rede será executada 100 vezes, atualizando seus pesos de 32 em 32 registros.

 

Selecionado e executado o bloco de código anterior veremos a rede sendo processada, após o término da mesma podemos ver que em suas épocas finais, graças ao fator de dar mais peso aos erros, a mesma terminou com uma margem de erro próxima a zero.

 

Rede treinada hora de começarmos a realizar as devidas previsões a partir da mesma, no caso, a previsão do preço de uma ação. Para isso, inicialmente vamos realizar alguns procedimentos para nossa base de dados.

Primeiramente criamos uma variável de nome base_teste que recebe todo conteúdo importado de nosso arquivo petr4-teste.csv. Da mesma forma criamos nossa variável preco_real_teste que recebe todos os valores de todas as linhas e da coluna 1 de base_teste via método .iloc[ ].values.

Por fim criamos a variável base_completa que realiza a junção dos dados da coluna ‘Open’ de base e base teste por meio da função .concat( ).

 

Via explorador de variáveis é possível visualizar todos dados de todas variáveis que temos até o momento.

 

Dando continuidade, criamos uma variável de nome entradas que de forma parecida com a que fizemos anteriormente dentro de nosso laço de repetição i, recebe como atributos os últimos 90 registros (que serão usados para encontrar o padrão para previsão), em seguida são feitas as transformações de formato par cruzamento de dados. Nada muito diferente do que já fizemos algumas vezes em outros modelos.

Para criação de nossa estrutura previsora teríamos diversas opções de estrutura, seguindo como fizemos em outros modelos, vamos nos ater ao método mais simples e eficiente. Para uma série temporal, primeiro criamos uma variável de nome previsores_teste que recebe uma lista vazia como atributo, em seguida criamos um laço de repetição que irá percorrer, selecionar e copiar para previsores_teste os 90 primeiros registros de entradas (do 0 ao 89) através da função .append( ).

Na sequência realizamos as devidas transformações para array numpy e no formato que precisamos para haver compatibilidade de cruzamento. Por fim realizamos as previsões como de costume, usando a função .predict( ).

Repare na última linha deste bloco, anteriormente havíamos feito a normalização dos números para um intervalo entre 0 e 1, agora após realizadas as devidas previsões, por meio da função .inverse_transform( ) transformaremos novamente os dados entre 0 e 1 para seu formato original, de preço de ações.

 

Repare que previsores_teste aqui está com valores normalizados.

Após a aplicação da função .inverse_transform( ) os dados de previsores_teste voltam a ser os valores em formato de preço de ação.

 

Como já realizado em outros modelos, aqui também se aplica fazer o uso de média dos valores, por meio da função .mean( ) tanto dos valores previstos quanto dos valores reais.

 

Selecionado e executado o bloco de código anterior podemos ver via console os valores retornados, note que o valor real da ação era de R$ 17,87, enquanto o valor previsto pela rede foi de R$ 17,15, algo muito próximo, confirmando a integridade de nossos dados assim como a eficiência de nossa rede.

Já que estamos trabalhando em cima de um exemplo de ações, quando vemos qualquer aplicação deste tipo de atividade costumamos ver percentuais ou gráficos apresentados para uma visualização mais clara, aqui podemos fazer a plotagem de nossos resultados para ter um retorno mais interessante.

Como de praxe, para plotagem de nossas informações em forma de gráfico importamos a biblioteca matplotlib. De forma bastante simples, por meio da função .plot( ) passamos como parâmetro os dados de preco_real_teste e de previsores_teste, com cores diferentes para fácil visualização assim como um rótulo para cada um. Também definimos um título para nosso gráfico assim como rótulos para os planos X e Y, respectivamente.

Por fim por meio da função .show( ) o gráfico é exibido no console.

 

Agora podemos visualizar de forma bastante clara a apresentação de nossos dados, assim como entender o padrão. Note a semelhança entre a escala dos valores reais em decorrência do tempo e dos dados puramente previstos pela rede neural. Podemos deduzir que esse modelo é bastante confiável para este tipo de aplicação.

Código Completo: