Prophet para previsões de séries temporais com dados da Pandemia de COVID-19 no Brasil

Saiu mais um projeto do Bootcamp de Data Science da Alura!🥰
Neste projeto apliquei os conhecimentos obtidos no módulo 3. Então, todo arcabouço teórico adquirido até aqui foi aplicado para o entendimento das nuances envolvendo as séries temporais, utilizando a biblioteca Prophet, desenvolvida pelo Facebook.
E pra começar: o que são séries temporais???
Uma série temporal é uma sequência de dados ordenados de forma cronológica. Quando analisamos séries temporais, o objetivo é explorar o comportamento passado e também de prever o comportamento futuro em um determinado problema…
Nesse contexto, o objetivo desse projeto foi fazer previsões sobre o número de casos e óbitos diários, causados pelo novo coronavírus SARS-CoV-2, em Manaus.
Mas por que Manaus, Valquíria??? 🤔
Bom, essa motivação veio do meu primeiro projeto, feito nesse Bootcamp, onde eu fiz algumas análises sobre a evolução das taxas de mortalidade aqui no Brasil. Essas análises mostraram que a taxa de mortalidade dobrou no Amazonas em 2021 (apresentando uma taxa de mortalidade de 10,82), quando comparada a 2020 (taxa de 5,46), consequentemente se tornando o Estado com maior taxa de mortalidade do país.
O dataset utilizado nessas análises anteriores foi obtido no Tabnet em junho de 2021, e nesse período os dados disponíveis eram de 2007 a março de 2021.
O gráfico abaixo foi obtido com esses dados:

Agora vamos ao projeto atual…
Dados
Os dados utilizados neste projeto foram obtidos do Brasil.io, um banco de dados que disponibiliza dados acerca dos casos e óbitos de SARS-CoV-2 no Brasil todo.
Eu escolhi o dataset: caso_full, que possui os dados para todos os municípios do país.
O arquivo .csv desse dataset foi salvo no dia 18/06/21 e pode ser encontrado no Google Drive.
Análises
Antes de iniciar as previsões fiz algumas análises preliminares. Essas análises mostraram que a pandemia de COVID-19 no Amazonas é, até o momento, caracterizada por dois picos: a primeira onda começou em março de 2020 e atingiu o pico por volta do início de maio de 2020, quando o número de casos diminuiu e então permaneceu praticamente estável de junho a novembro de 2020. Porém, em meados de dezembro o número de casos começou a crescer exponencialmente, configurando a segunda onda da pandemia, como podemos visualizar abaixo no gráfico, que apresenta as médias de casos diários notificados:

A mesma situação é observada quando analisamos a média de óbitos diários notificados no Amazonas:

Estudos indicam que o aumento de casos e óbitos foram impulsionados por uma combinação de diminuições das medidas de distanciamento social e pelo surgimento de uma forma mais transmissível do vírus, a variante P.1, identificada em novembro de 2020. Essa variante causou um aumento exponencial da doença, o que estabeleceu a segunda onda da pandemia no estado.
Agora vamos ver uma comparação de Novos Casos x Novos Óbitos em Manaus:

Quando comparamos os casos (em azul) e óbitos diários (em vermelho), vemos que os dados não se alinham totalmente, pois em casos graves, após a pessoa ser contaminada pode levar alguns dias até que o óbito aconteça. Além disso, vemos que assim como os casos, os óbitos possuem duas ondas bem evidentes e há dois picos altos em setembro e outubro de 2020. Após verificar informações a respeito, encontrei matérias em alguns sites sobre a reclassificação de óbitos por COVID-19 em Manaus, que correspondem com esses picos. Essa reclassificação ocorreu, pois óbitos que ocorreram entre meses de abril e maio haviam sido registrados como SRAG (Síndrome respiratória aguda grave) de causa não especificada. Provavelmente, esses óbitos reclassificados foram incluídos nas datas: 2020–09–02 e 2020–10–01.
Quando analisei as médias móveis de casos e óbitos em Manaus, notei que houve uma diminuição e estabilização para casos e óbitos, após abril de 2021. O que, certamente, deve ser reflexo da vacinação, que foi iniciada em Janeiro de 2021 e segundo informações da secretaria municipal de saúde de Manaus: em maio de 2021, mais de 250 mil pessoas já estavam com o ciclo de imunização completo em Manaus.
A média móvel nos permite analisar se o número de casos confirmados e o número de óbitos causados pela COVID-19 na última semana tem aumentado ou diminuído, de acordo com o mesmo intervalo de tempo das semanas anteriores. Ou seja, a média móvel é calculada somando-se o número de casos ou óbitos de cada um dos sete dias anteriores e dividindo esse resultado por 7 (que é o número de dias considerado)
Aqui podemos ver esses gráficos de média móvel:


Bom, e como esse tal de Prophet funciona pra fazer previsões hein?!
A biblioteca Prophet é usada para criar modelos onde a série é ajustada considerando características não estacionárias, como tendência e sazonalidade.
O modelo ajustado pelo Prophet é do tipo:

Neste caso, a série usa o termo g para modelar a tendência, o s para as mudanças periódicas e o h para efeitos específicos, como: feriados. A tendência pode ser modelada como uma equação de reta. Por fim, o ϵ representa informações que não foram refletidas no modelo.
Já, a parte sazonal, utiliza série de Fourier:

Nesse caso P é igual a 365,25 no caso de sazonalidade anual. As séries de Fourier são uma combinação de funções seno e cosseno, que conseguem modelar os efeitos sazonais com períodos e fases diferentes.
E quais dados entram na previsão???
Quando usamos o Prophet, precisamos definir ds e y:
- ds: é a coluna dos dados que contém as datas
- y: é a coluna com os dados que vamos querer prever. No caso desse projeto será a coluna ‘new_confirmed’ para prever novos casos e a coluna ‘new_deaths’ para novos óbitos.
Além disso, quando estamos fazendo previsões, para saber se o nosso modelo está bom, precisamos fazer algo importante: Separar os dados em treino e teste!
Geralmente, quando separamos os dados em treino e teste, usamos 70% para treino e o restante para teste. Porém, no meu caso como temos aquele pico enorme, da segunda onda da Pandemia em Manaus, optei por usar mais que 70% dos dados para treino. Portanto, os 400 dados iniciais foram treinados.
Abaixo, mostro o código para separar os dados e definir ds e y:
Depois que você define quais serão os seus dados e o que você vai prever é só treinar o modelo e fazer as previsões.
Eu falei ‘só’ mas, na verdade, dá um certo trabalho 😅…pois você precisa deixar os dados ajustadinhos na curva de tendência e pra isso há uma série de parâmetros para serem estudados e testados.
Após realizar as previsões com o Prophet, tanto para novos casos quanto para novos óbitos, consegui obter modelos com curvas bem ajustadas e com dados de teste aderidos à curva. Ambos os modelos, mostram uma tendência de queda para os próximos meses.
Vou mostrar os modelos ajustados antes e depois da alteração de alguns parâmetros, para vocês notarem a diferença:
Modelo de Previsão para Novos Casos (Antes de alterar os parâmetros):

A divisão entre treino e teste é de extrema importância, para saber se o modelo está bom. Vemos que a maioria do pontos vermelhos (do teste) estão próximos ao ajuste. Porém, mais ajustes precisam ser realizados, pois os pontos precisam estar mais aderentes à curva. Além disso há uma grande quantidade de Outliers, que são esses pontos fora do modelo.
Modelo de Previsão para Novos Casos (Após alterar os parâmetros):

Agora temos poucos outliers, os dados de teste estão dentro do intervalo de confiança e a maioria deles está aderida ao modelo.
Vamos ver os resultados para Novos Óbitos:
Modelo de Previsão para Novos Óbitos (Antes de alterar os parâmetros):

Esse modelo, a princípio, ficou ainda pior que o modelo inicial para novos casos. Além da grande quantidade de Outliers, a maioria dos dados de teste nem entrou dentro do intervalo de confiança.
Modelo de Previsão para Novos Óbitos (Após alterar os parâmetros):

Ufa! Agora temos poucos outliers e os dados de teste estão dentro do intervalo de confiança e a maioria deles está aderida ao modelo.
Observando essas previsões, vemos que quando testamos períodos mais longos, o intervalo de confiança tende a aumentar cada vez mais. No caso das previsões feitas neste projeto, a curva de tendência indica que os números de novos casos e novos óbitos poderão se manter baixos nos próximos dois meses. Porém, quando pensamos em séries temporais o esperado seria encontrar uma sazonalidade constante e não foi isso que vimos nestes dados de Manaus. Em Manaus, observamos essa segunda onda catastrófica, que poderia ter sido evitada, mas uma série de fatores nos trouxeram essa triste realidade de vários óbitos causados pela COVID-19:
- Falha do governo em assumir a liderança e responsabilidade no desenvolvimento de estratégias coerentes destinadas à prevenção da transmissão do vírus;
- Descoordenação das políticas e ações entre os níveis nacional e estados/municípios, comprometendo as capacidades de mobilizar recursos essenciais para o enfrentamento da pandemia;
- Desvalorização de medidas preventivas e de tratamentos baseados na ciência e estímulo generalizado para a adoção de tratamentos sem comprovação científica;
- Demora nas decisões e ações necessárias para garantia de estoque de insumos (equipamentos de UTI e proteção, medicamentos e vacinas);
- E é claro: a criação de um clima de descrédito e desconfiança na população em temas relacionados ao uso de máscaras e ao conjunto de medidas de distanciamento físico e social, bem como às vacinas, minando os esforços de enfrentamento e respostas.
E como eu consegui ajustar essas previsões?
Todas as etapas do processo e códigos podem ser encontradas no meu notebook que está disponível no GitHub
- Criei uma lista com todos os feriados nacionais, estaduais (Amazonas) e do município Manaus;
- Removi os outliers (que são todos os pontos que ficam fora da curva);
- Então, fiz uma série de testes de como conseguir ajustar os dados e cheguei nos seguintes parâmetros finais:
Quando ajustei o modelo para Novos óbitos um changepoint_range=0.92 me trouxe um melhor resultado, porém para Novos casos eu mantive em 0.90.
Vamos entender o que é cada parâmetro:
- n_changepoints: Este é o número de changepoints colocados automaticamente. O padrão de 25 deve ser suficiente para capturar as mudanças de tendência em uma série temporal típica. Em vez de aumentar ou diminuir o número de pontos de mudança, provavelmente será mais eficaz se concentrar em aumentar ou diminuir a flexibilidade nessas mudanças de tendência, o que é feito com changepoint_prior_scale.
Change points são variações abruptas nos dados da série temporal.
- changepoint_range: Esta é a proporção em que a tendência pode mudar. O default desse parâmetro é 0.8, (80%), o que significa que o modelo não se ajustará a nenhuma mudança de tendência nos últimos 20% da série temporal. Isso é bastante conservador, para evitar overfitting nas mudanças de tendência no final da série temporal, onde não há pista suficiente para se encaixar bem. Isso é algo que pode ser identificado visualmente com bastante facilidade: pode-se ver claramente se a previsão está indo mal nos últimos 20%. Porém, acabei ajustando para 0.90 (nos Novos Casos) e para 0.92 (nos Novos óbitos), pois devido ao pico de segunda onda da pandemia, a curva não estava se ajustando bem apenas com o valor default de 0.8.
- changepoint_prior_scale: Este é provavelmente o parâmetro mais impactante. Ele determina a flexibilidade da tendência e, em particular, o quanto a tendência muda nos pontos de mudança de tendência. O default desse parâmetro é de 0.05 e isso funciona para muitas séries temporais, porém ajustei para 0.1.
- seasonality_mode: As opções são [‘additive’ ou ‘multiplicative’]. O default é ‘aditivo’, mas muitas séries temporais terão sazonalidade multiplicativa. Isso é melhor identificado apenas olhando para a série temporal e verificando se a magnitude das flutuações sazonais cresce com a magnitude da série temporal. No meu caso, a sazonalidade multiplicativa gerou resultados melhores.
Entendendo o conceito de sazonalidade aditiva e multiplicativa:
- Aditiva: quando a série apresenta flutuações sazonais mais ou menos constantes, não importando o nível global da série.
- Multiplicativa: quando o tamanho das flutuações sazonais variam dependendo do nível global da série.
- holidays: para passar em um DataFrame de feriados especificados.
- weekly_seasonality: 7 dias
- periods: é o número de dias de previsão
Análise dos Componentes:
Quando geramos as previsões com Prophet, podemos analisar um gráfico que mostra a Tendência, o efeito dos feriados e como os dados se comportam na semana, conforme vemos no gráfico abaixo:

Em trend vemos que há uma tendência de queda da previsão. Além disso, em holidays (que são aqueles feriados que eu comentei que adicionei), podemos perceber que há uma baixa nos casos e óbitos notificados, quando os dias úteis se tornam feriados. Finalmente, em weekly, vemos que aos domingos e segundas há uma diminuição da notificação dos casos e óbitos. Esses dados da Pandemia aos domingos, segundas e feriados, costumam ser menores devido a atrasos de notificação nas secretarias da saúde, que nesses dias, trabalham com menos profissionais, em esquema de plantão.
Para gerar esses gráficos bastar dar o comando: modelo.plot_components(previsao), após ter feito a previsão.
E como sei que o modelo está bom?
Bom, depois de alterar os parâmetros do nosso modelo, podemos analisar o ajuste dos dados usando o Scikit-learn, que possibilita o uso de Métricas e pontuação para quantificar a qualidade das previsões. Nos meus modelos, por exemplo, utilizei as métricas:
- mean_absolute_error
- median_absolute_error
- r2_score
Cheguei a comparar os resultados delas entre as sazonalidades aditiva e multiplicativa, e em todos os casos os resultados foram melhores na sazonalidade multiplicativa.
Além disso, é importante fazer a Cross-Validation!!!
Quando vamos validar nosso modelo separamos os dados em treino, validação e teste. Os dados de treino são os que o modelo vai usar para se ajustar. Os de validação são os o que vamos usar para calcular a performance do modelo enquanto alterarmos variáveis como os hiperparâmetros.
A etapa de separação dos dados pode nos gerar uma limitação, pois vamos validar nossos dados apenas uma vez, já que não podemos prever dados que estavam no conjunto de dados de treino.
Para resolver isso surgiu a técnica Cross-Validation (CV), que cria mais possibilidades de validação do nosso modelo com a mesma quantidade de dados que tínhamos antes.
Para criar o dataframe de validação cruzada:
O critério para essa divisão será definido através de alguns parâmetros:
- o primeiro é o
initial
, que define a porção inicial de dados que serão usados para o treinamento; - outro parâmetro de atenção é o
horizon
que é o horizonte: o tamanho da previsão que será feita; - o seguinte é o
period
, onde definimos de quanto em quanto tempo um novo horizonte será previsto.
Utilizei os seguintes critérios para fazer o Cross-Validation dos meus dados:
Ou seja: eu defini o parâmetro
initial
como 180 dias. Isso significa que o primeiro grupo será treinando com 180 dias dos dados disponíveis. O parâmetroperiod
com 30 dias, indicando as divisões dos grupos será de 30 em 30 dias. Já o último é o parâmetrohorizon
que também é de 30 dias, indicando que o modelo de cada grupo fará a previsão para 30 dias.
Algumas métricas são calculadas, medindo o quanto a nossa previsão está errando:
- MSE: Média do erro ao quadrado
- RMSE: Raiz quadrada da métrica MSE
- MAE: Média do erro absoluto
- MAPE: Média do erro absoluto percentual
- MDAPE: Mediana do erro absoluto percentual
Abaixo, temos um exemplo dos resultados que eu obtive, onde vemos a MSE (Média do erro ao quadrado) nos dados de Novos óbitos.
A MSE é a média obtida após calcular a diferença do valor real pelo valor previsto, elevando ao quadrado e realizando a média. Essa métrica dá um peso maior para erros maiores, já que todos os valores são elevados ao quadrado. O resultado dessa métrica para o modelo de previsão de Novos Óbitos, foi melhor do que vimos no modelo de Novos Casos. Vemos que a maioria dos pontos está próxima de zero e temos poucos pontos dispersos.

A avaliação de todas as métricas está disponível no meu notebook no GitHub
Conclusões
- O modelo de sazonalidade multiplicativa, que é usado com flutuações sazonais que variam dependendo do nível global da série, se mostrou mais adequado para os modelos previstos nesse projeto.
- Após realizar o Cross-Validation dos modelos de previsão, no geral, vemos que quanto maior o número de dias, maior é a dispersão dos dados no nosso modelo.
- Como esse projeto está usando dados reais da Pandemia de COVID-19, sabemos que em muitos momentos da pandemia os dados sofreram grandes mudanças, com picos de casos e óbitos e isso influencia nessa questão da dispersão dos pontos no modelo. Se fosse uma série temporal estabilizada, contendo dados de um tempo maior, possivelmente, os erros vistos nesses parâmetros poderiam ser bem menores do que estamos vendo aqui.
- Finalmente, duas hipóteses levantadas no início do projeto foram respondidas: Sim, após alguns meses de vacinação houve queda de casos e óbitos e a tendência é de que continuem diminuindo!
- Após concluir as análises, vemos que em poucas linhas de código é possível fazer previsões e validações, o que faz do Prophet uma ferramenta bastante poderosa e prática.
Referências
Muito obrigada pela leitura! Se alguém tiver sugestões ou dúvidas: pode me chamar pelo LinkedIn.
Até mais ❤️