Завершите проект прогнозирования новых случаев COVID-19 в течение следующих 90 дней с помощью LSTM (код включен)

В Индии снова наблюдается резкий рост числа случаев COVID-19! 27 декабря 2021 года было зарегистрировано всего 6 358 новых случаев. Но всего за 14 дней, 10 января 2022 года, было зарегистрировано колоссальное количество новых случаев — 168 063. Кривая третьей волны очень крутая, поэтому сейчас это вызывает большую озабоченность.

Итак, я подумал об использовании архитектуры искусственной рекуррентной нейронной сети (RNN) с долговременной кратковременной памятью (LSTM), чтобы предсказать, как будет выглядеть график COVID-19 в ближайшем будущем (следующие 90 дней).

Набор данных:

Набор данных загружен из COVID-19 India Datasets by DataMeet. Данные собираются, очищаются и систематизируются сообществом с различных государственных веб-сайтов, которые находятся в свободном доступе для всех индийцев.

Репозиторий Github: https://github.com/datameet/covid19

Набор данных имеет международную общественную лицензию Creative Commons Attribution 4.0. Набор данных загружен 10 января 2022 г. и содержит данные на ту же дату.

Мы используем файл all_totals.JSON в каталоге data. Этап предварительной обработки демонстрирует, как я обработал данные из этого файла JSON, чтобы использовать их для архитектуры LSTM.

Методология

Давайте обсудим методологию того, как я выполнил проект. В разделах результатов после этого будут обсуждаться результаты, которые мы получили от всего проекта.

Импорт библиотек:

Давайте импортируем необходимые библиотеки для проекта.

import json
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM,Activation,Dense,Dropout
%matplotlib inline
scaler = MinMaxScaler()
from tensorflow.keras.callbacks import EarlyStopping

Предварительная обработка данных:

Из набора данных all_totals.JSON я создал фрейм данных, который содержит новые случаи, регистрируемые каждый день.

f = open('all_totals.json')
# returns JSON object as a dictionary
data = json.load(f)
total_cases_list = []
new_cases_list = []
    
pre_total_cases = 0
for row in data["rows"]:
    if "total_confirmed_cases" in row["key"]:
        temp_list = []
        temp_list.append(row["key"][0][0:10]) # Appending the date (the time part is trimmed)
        temp_list.append(row["value"]) # Appending the value on that date
        total_cases_list.append(temp_list)
        
        temp_list_2 = []
        temp_list_2.append(row["key"][0][0:10])
        temp_list_2.append((row["value"] - pre_total_cases)) # Appending the value on that date
        new_cases_list.append(temp_list_2)
        
        pre_total_cases = row["value"]
    
df_total = pd.DataFrame(total_cases_list, columns = ["Date", "Total Cases"])
df_new = pd.DataFrame(new_cases_list, columns = ["Date", "New Cases"])

Фрейм данных с именем df_new содержит новые случаи, регистрируемые каждый день (некоторые даты отсутствуют), начиная с 2020–01–30.

Сделаем поле «Дата» индексом.

df_total = df_total.set_index("Date")
df_new = df_new.set_index("Date")

Давайте удалим некоторые ошибочные значения в файле:

#deleting two faulty values
df_total.drop('2021-09-16', inplace=True, axis=0)
df_total.drop('2021-09-17', inplace=True, axis=0)
df_total.drop('2021-07-21', inplace=True, axis=0)
df_total.drop('2021-07-22', inplace=True, axis=0)
df_new.drop('2021-09-16', inplace=True, axis=0)
df_new.drop('2021-09-17', inplace=True, axis=0)
df_new.drop('2021-07-21', inplace=True, axis=0)
df_new.drop('2021-07-22', inplace=True, axis=0)

Вот как теперь выглядит датафрейм:

Давайте посмотрим на кривую общего числа случаев COVID-19, зарегистрированных в Индии:

А это кривая новых случаев COVID-19, зарегистрированных в Индии:

Теперь мы создадим обучающий набор данных и обучающие метки. Набор обучающих данных будет представлять собой данные временного ряда. Мы выбрали 90 дней в качестве размера окна данных временного ряда.

day = 90 # Number of days (window size)

Теперь давайте создадим обучающий набор данных и обучающие метки.

k = 0
array = []
array_temp = []
train_data = []
train_labels = []
for i in range(len(df_new)):
    array_temp.append(df_new.iloc[i]['New Cases'])
array_temp = np.array(array_temp).reshape(-1,1)
array_temp = scaler.fit_transform(array_temp)
array_temp = array_temp.tolist()
for i in array_temp:
    array.append(i[0])
for i in range(len(array)):
    try:
        train_data.append(array[k:day+k]) # Creating inner lists with 'day' days of data
        train_labels.append([array[day+k]])
        k+=1
    except:
        break
length = max(map(len, train_data))
train_data=np.array([xi+[None]*(length-len(xi)) for xi in train_data]).astype('float32')
length = max(map(len, train_labels))
train_labels = np.array([xi+[None]*(length-len(xi)) for xi in train_labels]).astype('float32')

Мы использовали MinMaxScaler, чтобы привести наши данные в диапазон 0–1. Затем мы изменили его форму, сделав всего один столбец и n количество строк (n = количество элементов в массиве). После этого мы преобразовали массив в список.

Затем мы создали обучающие данные. Для каждых 90 пунктов в одном списке 91-й пункт будет их меткой. Затем мы создали список списков со всеми списками, содержащими 90 точек. Мы создали еще один список, содержащий ярлыки. Позже все эти списки преобразуются в массивы NumPy и массивы или массивы NumPy.

Форма набора данных обучения и метки выглядит следующим образом:

print(train_data.shape)
print(train_labels.shape)

Форма:

(644, 90)
(643, 1)

Давайте расширим размеры обучающего набора данных для архитектуры LSTM.

train_data = train_data[:len(train_labels)]
train_data = np.expand_dims(train_data,1)
train_data.shape

Форма: (643, 1, 90)

Давайте посмотрим, как теперь выглядит одна строка обучающих данных.

train_data[1]

Давайте посмотрим, как одна строка набора данных label:

train_labels[1]

Вывод: массив ([0.0027741], dtype=float32)

Архитектура:

Давайте построим архитектуру LSTM сейчас

model = Sequential()
model.add(LSTM(250,input_shape=(1,day)))
model.add(Dropout(0.5))
model.add(Dense(250,activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(day,activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(1,activation='relu'))
model.compile(loss='mean_squared_error',optimizer='adam')
model.summary()

Обучение:

Подгонка данных к модели сейчас.

E = 1000
callback = EarlyStopping(monitor='loss', mode='min', patience=20)
H = model.fit(train_data,train_labels,epochs=E, verbose=0, callbacks=[callback])

После того, как этап обучения завершен, давайте нанесем на график значение потерь.

loss = H.history['loss']
epochs = range(0,len(loss))
plt.figure(figsize=(15,5))
plt.plot(epochs,loss)

Давайте построим прогнозы, данные LSTM, вместе с реальными значениями новых зарегистрированных случаев COVID-19 каждый день, чтобы увидеть, насколько точны прогнозы.

preds = scaler.inverse_transform(model.predict(train_data))
plt.figure(figsize=(30,10))
plt.plot(preds,label='our predictions')
plt.plot(scaler.inverse_transform(train_labels),label='real values')
plt.legend()

Из этого графика видно, что прогнозируемые значения очень точны, а модель очень перспективна.

Прогнозы на будущее:

Попробуем спрогнозировать эту кривую в ближайшем будущем. Мы постараемся спрогнозировать, сколько новых случаев COVID-19 будет зарегистрировано в Индии в ближайшие 90 дней (начиная с 10 января 2022 года).

days_to_predict = 90
seed = array[-day:]
#seed

Здесь мы создаем начальное число. Начальное число — это не что иное, как последние 90 дней данных в массиве. Мы будем использовать это начальное число для прогнозирования данных на следующий день. Когда он это предскажет, мы обновим наше начальное число и сделаем так, чтобы оно содержало предсказанные данные, которые будут использоваться в следующем предсказании.

Возьмем пример. Начальное значение сначала содержит данные за последние 90 дней (значения того, сколько новых случаев ковида регистрируется каждый день), заканчивающиеся 10 января 2022 года. Используя его, мы спрогнозируем значение на 11 января 2021 года. Затем мы воспользуемся прогнозируемым значением. данные на 11 января 2022 года в качестве точки данных в начальном значении и прогнозировать данные значения на 12 января 2022 года и так далее.

Давайте используем эту модель, чтобы предсказать количество случаев на следующие 90 дней:

for _ in range(days_to_predict):
    current_days = seed[-day:]
    current_days = np.squeeze(current_days)
    current_days = np.expand_dims(current_days,0)
    current_days = np.expand_dims(current_days,0)
    pred = model.predict(current_days)
    seed = np.append(seed,pred)

Построим прогнозные значения:

upcoming_days_prediction = scaler.inverse_transform(seed[-days_to_predict:].reshape(-1,1))
plt.figure(figsize=(30,10))
plt.plot(range(0,days_to_predict),upcoming_days_prediction)

Давайте добавим прогнозируемые значения со значениями в нашем наборе данных и построим полный график.

# Adding real values and predicted values together
arr_without_pred = scaler.inverse_transform(train_labels)
arr_pred = scaler.inverse_transform(seed[-days_to_predict:].reshape(-1,1))
arr_with_pred = np.concatenate((arr_without_pred, arr_pred))
plt.figure(figsize=(30,10))
plt.plot(arr_with_pred)

Полученные результаты:

Прежде чем мы увидим результаты, я надеюсь, вам понравилось читать эту статью. Если вы это сделали, пожалуйста, станьте участником Medium. Всего за 5$ в месяц вы можете прочитать любую статью на Medium (не только мои статьи, любую статью). Нажмите на ссылку ниже.

https://samratduttaofficial.medium.com/membership

Я получу небольшую комиссию от 5$ и это будет мотивировать меня писать больше!

Посмотрим прогноз новых зарегистрированных случаев COVID-19 на ближайшие 90 дней (начиная с 11 января 2022 года).

Давайте посмотрим полный график новых зарегистрированных случаев COVID-19 каждый день вместе с прогнозируемыми значениями на ближайшие 90 дней (начиная с 11 января 2022 года).

Итак, сколько всего случаев прогнозирует модель на ближайшие 90 дней?

total_new_cases = 0
for i in upcoming_days_prediction:
    total_new_cases += i[0]
    #print(i)
print(total_new_cases)

Ответ: 23 417 088.

Эта модель предсказывает около 23,5 миллионов новых случаев COVID-19 в Индии в ближайшие 90 дней (начиная с 11 января 2022 года).

Заключение

Это исследование/проект просто демонстрирует использование архитектуры LSTM для прогнозирования данных временных рядов. В этом случае мы использовали данные COVID-19 из Индии для нашего исследования. Эта модель не учитывает трансмиссивность и другие факторы при прогнозировании.

Поскольку трансмиссивность варианта Омикрон намного выше, чем вариант Дельта COVID-19 (вариант Дельта был доминирующим вариантом во время второй волны пандемии в Индии), я лично думаю, что мы увидим гораздо более крутую и высокую кривую в ближайшем будущем.

Но я не медицинский работник и не врач. Так что принимайте все, что я говорю, с долей скептицизма.

Репозиторий: https://github.com/SamratDuttaOfficial/Covid_India_LSTM

Не забудьте поставить репозиторию Github звезду.

Самрат Датта:

Github: https://github.com/SamratDuttaOfficial

Linkedin: https://www.linkedin.com/in/SamratDuttaOfficial [Наймите меня]

Самые мудрые друзья (машинное обучение) Discord: https://discord.gg/7Bx6PGVy

Купите мне кофе: https://www.buymeacoffee.com/SamratDutta