Introdução
Previsão com séries temporais é uma subárea do Data Science com inúmeras aplicações que vão desde a previsão da procura até ao planeamento da produção e inventário, gestão das cadeias de abastecimento, processamento de sinal, meteorologia e reconhecimento de padrões em epidemiologia.
E o que é uma série temporal? Uma série temporal é um conjunto de observações ordenadas temporalmente. O principal objetivo da modelação preditiva em séries temporais é a previsão de valores futuros com base nos valores passados das séries.
Exemplo de série temporal na área do retalho, quantidade despendida em diferentes modelos de t-shirts por trimestre [1]
Apesar da abundância de aplicações, extensa literatura, robustos algoritmos, bibliotecas e dados disponíveis, a previsão em séries temporais é ainda uma área extremamente desafiante para vários cientistas de dados. Não é popular ou “trendy” como reconhecimento de imagem ou processamento de linguagem natural, tem pouca ou nenhuma atenção na maioria dos cursos introdutórios de ciência de dados ou nas academias das empresas.
O objetivo deste artigo é ser uma pequena introdução à análise de séries temporais, especialmente para previsão. Começamos por introduzir os conceitos principais como estacionariedade e modelação através de ARIMA. De seguida, passamos para o conceito central do artigo, como transformar um problema de previsão em séries temporais num problema de aprendizagem supervisionada. Ao longo do artigo, algumas bibliotecas de Python e uma pequena demo serão apresentadas.
Propriedades das Séries Temporais e Modelação ARIMA
A maioria dos modelos de ciência de dados tem a assunção implícita de que a relação entre inputs e outputs se mantém estática. Se esta relação se alterar com o tempo, o modelo poderá estar a fazer previsões obsoletas.
Na análise de séries temporais, uma forma de verificar a estabilidade da relação entre inputs e outputs ao longo do tempo é analisar se a série temporal é estacionária. Uma série temporal pode ser considerada estacionária se as suas propriedades estatísticas como a média ou a variância se mantêm constantes ao longo do tempo. Um teste rápido para confirmar a estacionariedade é o teste Augmented Dickey-Fuller.
Na vida real, a maioria das séries temporais é não estacionária e a maioria das técnicas de previsão clássicas foca-se em converter séries não estacionárias em estacionárias.
Uma das técnicas de previsão mais famosas é ARIMA (autoregressive integrated moving average). ARIMA é uma combinação de métodos que permitem a previsão baseada em valores passados. Combina um modelo de regressão linear – que usa atrasos da variável a prever como features – com diferenciação para prever valores futuros. A diferenciação é usada para tornar a série temporal estacionária, subtraindo o valor anterior ao valor atual na série.
ARIMA é um método muito bem estabelecido e documentado, no entanto a configuração dos parâmetros é bastante complexa, requerendo um enorme conhecimento dos dados. Isto pode ser trivial quando o problema de previsão é simples (por exemplo apenas fazer uma previsão numa série temporal), mas normalmente, nos problemas reais, isso não acontece.
Na vida real, normalmente, não está presente apenas uma única série individual, mas muitas, por vezes milhões, o que resulta num número elevado de modelos ARIMA a configurar, com um número ainda maior de parâmetros a estudar. Também, cada série temporal pode ter um comportamento diferente.
Um bom exemplo desta situação é no retalho. Um grande retalhista pode carregar milhares de produtos em diferentes localizações, o que resulta em milhões de séries temporais individuais, cada uma para cada combinação produto/localização. É praticamente impossível para um cientista de dados analisar todas estas séries temporais, assim a utilização de uma ferramenta de seleção de modelos automática torna-se num fator crucial para uma análise bem-sucedida [3]. Exemplos de bibliotecas populares de Python para a escolha automática de modelos, com bons resultados documentados, são pyramid-arima e uma biblioteca desenvolvida pelo Facebook, o Fb Prophet.
Modelação com Machine Learning Supervisionado
Outra abordagem, que será o foco durante o resto do artigo, é transformar um problema de previsão de séries temporais num problema de machine learning supervisionado utilizando os algoritmos típicos deste método como elastic-net, random forests, gradient boosting machines, etc.
Através desta metodologia é possível ultrapassar o problema das múltiplas séries temporais independentes, o que pode ser extremamente vantajoso quando algumas das séries individuais têm poucos ou nenhum dado.
Utilizando o exemplo sobre o retalho, de novo, alguns produtos podem não ter registos para certas alturas do ano devido a variadas razões como: o produto esgotou, nenhuma procura nesse par tempo/local ou quando o produto é novo. Concatenando todas estas séries individuais numa única tabela e treinando um único modelo em vez de múltiplos modelos, o algoritmo será capaz de aprender padrões mais subtis que se repetem ao longo das séries e extrapolar esses padrões que aparecem numa série para uma com menos informação/dados [4]. Assim, em vez de ter um número muito elevado de modelos (o que pode resultar em dificuldades durante a entrada em produção e longos tempos de treinos), apenas temos um modelo para estas séries temporais independentes.
Feature Enginnering
A forma mais simples de transformar um problema de previsão em séries temporais num problema de Machine Learning supervisionado é através da criação de lags/atrasos. Uma primeira abordagem é prever o valor de certo tempo t dado o valor num tempo anterior t-1.
Um atributo que também pode ser útil é a diferença entre um ponto numa altura (t) e a observação anterior (t-1). Esta variável deve ser calculada a partir das lag features para evitar leakage.
É possível calcular inúmeros lags, dependendo do negócio pode ser útil ter lag features da semana passada, mês passado, ano anterior… Utilizando uma Regressão de Ridge poderá ser possível selecionar os lags features que terão um maior impacto no modelo ou detetar séries temporais não estacionárias.
Atributos mais avançados podem ainda ser computados através da adição de estatísticas dos valores anteriores. Isto pode ser atingido com uma janela deslizante com uma largura fixa e depois estatísticas como a média, máximos, mínimos ou percentis são aplicadas. Um exemplo da média aplicada a uma janela com largura de 3, seria média(t-1, t-2, t-3). Para calcular estas estes atributes deslizantes, a biblioteca de Python, Pandas, providencia uma função muito útil, rolling().
Outra janela muito útil é a expanding window, que inclui todos os pontos prévios dos dados das séries temporais e pode ajudar ao monitorizar os limites dos dados. Como nas janelas deslizantes, estatísticas podem ser aplicadas. O cálculo de uma expanding window num conjunto de dados com apenas 4 linhas seria algo como, média(NaN, t-1, t-2, t-3). A função do Pandas para calcular estas janelas é expanding().
É também possível extrair atributos bastante informativos para o modelo a partir do timestamp, como dia do ano, trimestre, mês, feriados, semanas, etc. Isto é bastante trivial de ser feito em Pandas.
Treino e Validação
O procedimento comum para o desenvolvimento de modelos em Machine Learning é treinar o modelo com os dados disponíveis, e depois de fazer os necessários processos de avaliação. O modelo então é lançado para produção e corre sem aprender mais, apenas aplicando o que já aprendeu antes. Depois de um certo tempo, quando a performance do modelo se degrada, este é retreinado.
Este tipo de treino não funciona para previsão na maior parte dos casos de séries temporais. É importante relembrar que a maiorias das séries temporais é estacionária, e, portanto, as propriedades estatísticas das mesmas mudam ao longo do tempo. Para ultrapassar este problema, o modelo tem de ser retreinado sempre que novos dados cheguem.
Também, as técnicas comuns em Machine Learning como validação cruzada podem induzir leakage durante o processo de validação, por exemplo, não faz sentido prever os valores para maio usando dados de treino de abril e junho.
Um bom procedimento de validação neste caso é a chamada “walk forward validation” que tenta recriar a tradicional separação em treino e teste para um cenário de séries temporais. A ideia aqui é separar as séries temporais em intervalos de tempo fixos, expandindo o conjunto de treino em cada iteração. Scikit-learn tem uma função que implementa esta validação, a função TimeSeriesSplit().
Avaliação
Modelos de previsão em séries temporais podem ser avaliados através de métodos de avaliação de regressão comuns, como o Erro Médio Absoluto (MAE) ou o R2.
O MAE é basicamente a média das diferenças absolutas entre as previsões e os valores reais.
R2, também conhecido como o coeficiente de determinação, é a percentagem de variação do target que é explicada por um modelo linear. Resumidamente, indica qualidade de ajuste de um modelo de regressão linear.
Outra métrica de avaliação interessante é o Erro Percentual Médio (MAPE). Esta métrica toma a forma de percentagem, o que é extremamente útil para o negócio, e consegue dar um insight rápido do quão bem o modelo está a comportar-se. O MAPE é simples de explicar e não depende de uma escala. O MAPE é a média do rácio das diferenças absolutas entre as previsões e os valores reais a dividir pelos valores reais.
Uma diferença importante entre os típicos problemas de Machine Learning como classificação e séries temporais é que é mais difícil definir alguns valores ideais para certas métricas de avaliação, devido a problemas de estacionariedade ou séries temporais com poucos dados. Um modelo com um MAPE de 5% pode não ter um bom desempenho ou, ao contrário, um modelo com MAPE de 30% não significa que seja um modelo fraco. Uma maneira de superar essa desvantagem é definir uma baseline que o modelo deve bater. Um exemplo desse tipo de baseline são as vendas do mês passado como a previsão para as vendas deste mês.
Em certas aplicações, a incerteza da previsão é tão crucial quanto a própria previsão. Por exemplo, em aplicações de organização de inventário e na previsão da procura, a incerteza da previsão, representada por quantis e intervalos de previsão, pode ser usada para calcular o stock de segurança, i. e. a quantidade adicional de stock necessária para evitar perdas. Na previsão em séries temporais financeiras, existem classes de modelos construídos explicitamente para modelar a incerteza da série no lugar da própria série temporal, como os modelos GARCH e ARCH.
Exemplo de Implementação:
Nesta demonstração, alguns dos conceitos acima serão demonstrados. Os dados são do Repositório UCI [5] e consistem em 811 produtos / séries temporais independentes ao longo de 52 semanas. Na próxima imagem é possível ver uma amostra dos dados:
Conforme referido anteriormente, uma das abordagens seria treinar um modelo para cada um dos 811 produtos. No entanto essa abordagem pode ser problemática porque cada série temporal tem apenas 52 pontos, o que não é muita informação para um modelo de Machine Learning.
Assim, neste exemplo, todas as séries temporais serão concatenadas e em vez de treinar vários modelos com poucos dados, treinaremos um único modelo com muito mais dados.
Feature Engineering
A primeira etapa é transformar os dados num problema de Machine Learning supervisionado, criando lag features. Para este propósito, a função shift () do Python é usada.
Para melhorar o poder preditivo do modelo, a diferença entre as vendas na semana anterior e as vendas duas semanas antes (t-1 – t-2) é calculada com a função diff (). Desta forma, dois atributos extras são adicionados (Vendas da última semana e Diferença entre as duas últimas semanas). O target é a variável Sales.
Definição de uma Baseline e Validação
É importante definir uma baseline que o modelo necessita superar para perceber se vale a pena ou não usar o modelo desenvolvido. Neste exemplo, uma baseline relativamente forte é usar as vendas da semana passada como previsão para as vendas da semana atual.
A ideia neste exemplo é treinar o modelo a cada semana para prever as vendas da próxima semana. Assim, será utilizada uma janela deslizante em formato de “walk forward validation”. Para evitar obter um bom desempenho numa pequena amostra de semanas apenas por sorte, usaremos as semanas de 40 a 51, repetindo o processo uma de cada vez, e calcularemos a pontuação [4].
A métrica de avaliação que vamos usar é o MAE, por ser mais intuitivo para perceber os valores. A métrica de avaliação MAPE, embora muito direta em termos de avaliação para o negócio, neste conjunto de dados, devido ao facto de que em algumas semanas para certos produtos as vendas serem zero, é bastante complicada de calcular. Por isso não a iremos usar nesta demonstração, por simplicidade.
Como não há muitos dados disponíveis e este exemplo é apenas uma pequena demonstração, não haverá divisão em treino e teste. Porém, em projetos mais complexos, é aconselhado manter alguns períodos fora da amostra de validação para uma avaliação mais robusta do modelo de previsão desenvolvido [4].
Treino do Modelo
Um bom primeiro modelo a experimentar é a Random Forest. É um algoritmo muito robusto ao overfitting devido ao elevado número de árvores de decisão que podem ser utilizadas (usaremos 1000), e porque as árvores podem ser treinadas em paralelo, sendo mais eficiente computacionalmente.
Aplicando o modelo aos dados é possível ver uma redução do erro em 10% o que é um bom começo
Passos adicionais para Melhorar o Modelo
Para melhorar o desempenho preditivo do modelo, novos atributos podem ser calculados, e a transformação da distribuição do target também poderá ser importante.
Olhando para o histograma da distribuição do target (Sales), podemos ver que os dados não seguem uma distribuição normal, na verdade estão bastante desviados para as baixas quantidades. Uma forma de tentar resolver este problema é tentar colocar os dados um pouco mais “normais” calculando o logaritmo do target.
Também podemos aumentar o número de lags e diferenças. Tentar algoritmos diferentes também poderá levar a melhores resultados.
Depois de criar mais lag features até seis semanas antes da semana atual, calcular o log do target e utilizando outro algoritmo foi possível reduzir o erro em relação à pontuação base em quase 20%.
Em resumo
A previsão em séries temporais é um assunto complexo na área de Data Science. Tem uma ampla gama de aplicações, desde meteorologia até economia e finanças. Este artigo cobriu as principais características das séries temporais, como modelá-las e como transformar um problema de previsão de séries temporais num problema de Machine Learning supervisionado. Esta abordagem é especialmente útil quando várias séries temporais estão presentes nos dados. No final, foi apresentada uma demonstração desta última abordagem.
Bibliografia
[1]: https://academy.dataiku.com/path/ml-practitioner/time-series-basics-1/579107
[2] https://machinelearningmastery.com/time-series-data-stationary-python/
[5] https://archive.ics.uci.edu/ml/datasets/Sales_Transactions_Dataset_Weekly