Руководство по прогнозированию временных рядов с помощью Facebook’s Prophet с использованием данных COVID-19 из Центра Университета Джона Хопкинса

Временной ряд - это просто последовательность точек данных, упорядоченных по времени с регулярным интервалом, где время обычно является независимой переменной, а цель состоит в том, чтобы сделать прогноз (предсказание) на будущее. Временные ряды - это обычная модель для многих приложений в жизни, например, для цен на акции, погоды, продаж. Умение прогнозировать данные временных рядов - важный навык в мире науки о данных.

Новый коронавирус, также известный как COVID-19, представляет собой продолжающуюся пандемию, которая широко распространяется по всему миру с декабря 2019 года. Использование прогнозирования временных рядов для прогнозирования будущих ежедневных случаев COVID-19, несомненно, поможет понять, насколько быстро это происходит. увеличивается и что может определять это увеличение. Кроме того, это может помочь понять, какое вмешательство, такое как физическое дистанцирование или изоляция, может повлиять на рост с течением времени.

Prophet - это библиотека, предоставленная группой инженеров по обработке данных Facebook, и это мощный, но простой инструмент для анализа и прогнозирования периодических данных, доступный как для Python, так и для R.

Эта статья призвана объяснить, как выполнять прогнозирование временных рядов с помощью Prophet, используя данные COVID-19 из Центра Университета Джонса Хопкинса.

Инструменты

В нашей настройке среды для этой статьи используется Python 3.7 со следующими установленными пакетами:

  • NumPy
  • панды
  • Матплотлиб
  • fbprophet
  • scikit-learn

Загрузка набора данных

Данные, используемые в этой статье, предоставлены Центром Университета Джона Хопкинса. Он ежедневно обновляется из официальных источников с новыми зарегистрированными случаями COVID-19 во всем мире. Набор данных доступен в репозитории GitHub https://github.com/CSSEGISandData/COVID-19.

В этой статье мы получим доступ к необработанному CSV-файлу непосредственно из репозитория через его URL-адрес. Сначала мы загружаем данные с помощью метода Pandas read_csv (), который загружает данные CSV из URL-адреса в DataFrame. Затем мы отображаем первые несколько строк с помощью head (), чтобы вкратце взглянуть на структуру и состав данных.

Данные за период с 22 января 2020 года до даты, когда мы получили к ним доступ. Каждая строка представляет провинцию (штат) со столбцами, представляющими страну, широту, долготу и количество подтвержденных случаев за день. Страны расположены в алфавитном порядке, и у каждой даты есть столбец, в котором хранится общее количество подтвержденных случаев.

импортировать панды как pd
% matplotlib inline

# загрузка данных
data_url = '«https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_global.csv' data )
df.head ()

Подготовка данных

Следующим шагом будет подготовка и очистка данных. Во-первых, мы фильтруем данные, используя столбец Country / Region, поскольку мы собираемся делать наши прогнозы для каждой страны. loc [] предоставляет доступ к группе строк и столбцов, передавая логический массив, содержащий условие фильтрации, которым в нашем случае является df ['Country / Region'] == 'Germany.' Обратите внимание, что вы можете изменить название страны в эта строка для прогноза результатов для другой страны. Затем мы удаляем столбцы, которые нам не нужны, например, провинция / штат, широта и долгота.

#filter с использованием названия страны
df = df.loc [df [‘Country / Region’] == ‘Germany’] # измените название страны здесь

# удалить неиспользуемые столбцы
df.drop ('Область / Штат', axis = 1, inplace = True)
df.drop ('Lat', axis = 1, inplace = True)
df.drop ('Длинный', axis = 1, inplace = True)
df.head ()

Затем группа по операции используется для объединения результатов с использованием столбца Страна / регион, т.е. в некоторых странах может быть несколько строк для нескольких провинций / штатов. Количество случаев в день суммируется с помощью функции суммы. Продолжаем удалять все столбцы с нулевыми значениями (без случаев). Затем мы сбрасываем индекс, чтобы удалить неиспользуемый столбец страны.

# группировать все строки одной страны
df = df.groupby (‘Country / Region’). sum ()

# удалить нулевые значения
df = df.loc [:, (df! = 0) .any (axis = 0)]

# удалить неиспользуемый столбец страны
df.reset_index (inplace = True)
df.drop (‘Country / Region’, axis = 1, inplace = True)
df.head ()

Нам понадобится, чтобы в нашем фрейме данных была одна строка для каждого значения временного ряда. Мы используем функцию transpose (), чтобы преобразовать индекс и столбцы в желаемый формат. Кроме того, мы преобразовываем тип данных нашего столбца даты в Timestamp вместо строки.

# транспонируем матрицу, чтобы создать строку для каждой записи даты
df = df.transpose ()

# изменить на datetime
dformat = '% m /% d /% y'
df.index = pd.DatetimeIndex (pd.to_datetime (df.index, format = dformat))
df .голова()

Модель Prophet требует, чтобы фрейм данных имел определенный формат столбцов, и мы меняем имена наших столбцов на «ds» и «y», чтобы они соответствовали требуемому формату. И мы сбрасываем наш индекс с помощью reset_index.

#prepare for Prophet
df.reset_index (inplace = True)
df.rename (columns = {'index': 'ds', 0: 'y'}, inplace = True)
df.head ()

Визуализация данных

Теперь, когда наши данные подготовлены в требуемом формате, мы строим данные с помощью функции построения графика, и даты отображаются на оси x, а количество наблюдений - на оси y. Цель этого шага - глубже понять данные. Это поможет нам в дальнейшем при выборе гиперпараметров, используемых для нашей модели. График ниже показывает, что количество случаев со временем резко увеличивается.

# график количества случаев за время
ax = df.plot (x = 'ds', y = 'y', figsize = (12,6), title = 'Ежедневные случаи Covid-19')
ax.autoscale (axis = 'both', tight = True)
ax.set (xlabel = 'Date', ylabel = 'Cases');

Модельное обучение

Затем мы собираемся настроить Prophet, чтобы начать моделирование наших данных. Импортируем нужную библиотеку. Кроме того, мы разделяем данные на обучающие и тестовые наборы. Поскольку наша модель будет переобучаться каждый раз, когда мы хотим создать новый прогноз, мы будем использовать 95% для обучения и 5% для тестирования для оценки результатов модели.

из fbprophet import Prophet

# разделить данные на обучающие и тестовые наборы
train_to_index = round (len (df) * .95)
train_data = df.iloc [: train_to_index]
test_data = df.iloc [train_to_index:]

print ('длина обучающих данных', len (train_data), 'test data length', len (test_data))

Создаем экземпляр модели Prophet. Поскольку наш график данных показывает экспоненциальный тренд, т. Е. Общую тенденцию к увеличению данных в течение периода, мы устанавливаем входные аргументы Seasonality_mode = 'multiplicative' и growth = 'linear'. И поскольку наши данные относятся к дневной частоте , мы устанавливаем daily_seasonality = True. Параметр настройки changepoint_prior_scale установлен на 0,5. Далее обучаем нашу модель на обучающей выборке. Кроме того, можно настроить параметры на основе набора данных и предметной области.

Фрейм данных создается с будущими датами для прогнозирования с использованием make_future_dataframe с частотой, установленной на «D», поскольку наши данные являются ежедневными. Длина этих дат установлена ​​на ту же длину, что и набор тестов, так как мы собираемся сравнивать результаты позже для оценки модели. Затем фрейм данных передается в нашу модель, чтобы предсказать значения для этих дат.

# создание модели и обучение на обучающем наборе
model = Prophet (growth = 'linear',
Seasonality_mode = 'multiplicative',
changepoint_prior_scale = 0.5,
weekly_seasonality = False,
daily_seasonality = True)
model.fit (train_data)

# создать фрейм данных с будущими датами, частота установлена ​​ежедневно
future = model.make_future_dataframe (period = len (test_data), freq = ’D’)

#predict значения для будущих дат
прогноз = model.predict (будущее)

Построение результатов модели

Теперь, когда наша модель обучена, нам нужно визуализировать результаты. Prophet имеет функцию построения графиков, называемую графиком, которая рисует исходные данные (черные точки), модель (синяя линия) и ошибку прогноза (заштрихованная синяя область).

# построение графика результатов
m.plot (прогноз);

Оценка модели

Чтобы помочь нам понять точность наших прогнозов, мы сравниваем прогнозируемое количество случаев с реальным количеством случаев для временного ряда. Для этого нам нужно создать комбинированный фрейм данных с «yhat» из прогнозов и исходными значениями «y» из данных.

# создать комбинированный фрейм данных
metric_df = прогноз.set_index ('ds') [['yhat']]. join (df.set_index ('ds'). y) .reset_index ()
metric_df.tail ()

Теперь, когда у нас есть прогнозируемые значения в сравнении с реальными значениями, мы используем r2_score () из sci-kit-learn для создания нашего R-Squared. Коэффициент детерминации (обозначенный R2) интерпретируется как доля дисперсии в зависимой переменной, которая предсказуема по независимой переменной.

Наилучшая возможная оценка - 1,0, поэтому значение 0,99 очень хорошо для нашей модели.

из sklearn.metrics импортировать r2_score

r2_score (metric_df.y, metric_df.yhat)

Кроме того, мы используем mean_squared_error () из scikit-learn для оценки наших результатов. Среднеквадратичная ошибка (MSE) - это сумма квадратов всех (предсказанных - фактических значений), деленная на количество точек данных. MSE - это показатель качества оценщика. Чем меньше MSE, тем ближе мы к поиску наиболее подходящей линии. Наше значение MSE составляет 4455269, что довольно велико и означает, что еще есть возможности для дальнейшего улучшения, используя настройку гиперпараметров на модели или дополнительные данные для получения лучших результатов.

из sklearn.metrics import mean_squared_error

mean_squared_error (metric_df.y, metric_df.yhat)

Прогнозирование будущих дат

В предыдущих разделах мы оценивали нашу модель на основе прогноза дат тестовых данных, которые у нас уже есть. Теперь нам нужно построить некоторые будущие даты для прогнозов. Чтобы спрогнозировать эти будущие данные, мы генерируем фрейм данных с 10 днями в будущем, затем прогоняем его с помощью функции «прогнозирования» модели Prophet и отображаем результаты.

# создать фрейм данных с будущими датами, частота установлена ​​ежедневно
future = m.make_future_dataframe (периоды = 10, freq = ‘D’)

# прогноз значений на будущие даты
прогноз = m.predict (будущее)

#print только обязательные столбцы ds, yhat, yhat_lower, yhat_upper
прогноз [[‘ds’, ‘yhat’, ‘yhat_lower’, ‘yhat_upper’]]. tail (10)

Заключение

Мы объяснили, как делать прогнозы временных рядов с помощью Prophet, используя данные из Центра Университета Джона Хопкинса по коронавирусу (Covid19). Мы прошли через загрузку данных, подготовку данных для модели Пророка, построение данных, обучение модели, построение результатов модели, оценку модели и прогнозирование будущих дат. Отметим, что невозможно придумать общий подход для всех задач прогнозирования, поскольку каждая задача имеет свои особенности и требует особых шагов. Тем не менее, эта статья была предназначена для того, чтобы дать базовое руководство и понимание прогнозирования временных рядов, которые могут быть в дальнейшем изменены в зависимости от предметной области.

Ссылки и дополнительная литература

[1] https://github.com/CSSEGISandData/COVID-19
[2] https://facebook.github.io/prophet/docs/quick_start.html
[3 ] Https://nextjournal.com/eric-brown/forecasting-with-prophet
[4] https://nextjournal.com/eric-brown/forecasting-with-prophet-part-4
[5] https://towardsdatascience.com/implementing-facebook-prophet-efficiently-c241305405a3