FBprophet, алгоритм машинного обучения

Анализ временных рядов для предсказания конца COVID-19 в Канаде.

Закончится ли это в июле?

Вступление

Многие из нас задаются вопросом, когда закончится пандемия COVID-19 и когда мы сможем вернуться к работе и поесть с нашими коллегами, не беспокоясь о правилах социального дистанцирования. В этой статье я пытаюсь ответить на этот вопрос, используя FBprophet в качестве алгоритма машинного обучения для анализа временных рядов. Я выбрал Канаду для этого тематического исследования, однако использованная мною процедура может быть легко применена для прогнозирования ситуации с пандемией в любой стране.

Данные

В самом начале я должен поблагодарить отдел науки о данных JHU за сбор и обмен информацией о пандемии COVID-19. Если бы не их усилия и ежедневные обновления, изучение пандемии было бы невозможным. Вы можете получить доступ к созданному набору данных на их официальном сайте или из их репозитория на GitHub.

Загрузим временные ряды для инфицированных и умерших:

Форма данных - это не то, что нам нужно для моделирования. Мы должны внести некоторые изменения, чтобы объединить оба набора данных и преобразовать их в желаемый формат. Я пропускаю коды здесь, но вы можете скачать предоставленный Jupyter Notebook здесь и выполнить код.

В новом наборе данных у нас есть иерархические столбцы для каждой страны и количество подтвержденных случаев, а также случаев смерти. Обратите внимание, что дата перемещена из столбца в индекс в формате Timestamp. Давайте посмотрим на данные Канады и построим график:

В этой статье я использовал plotly вместо обычного matplotlib.pyplot в качестве моей библиотеки для построения графиков. Если вы еще не установили его, сделайте это с помощью кода ниже:

pip install plotly

Ситуация в Канаде до даты написания этого документа выглядит следующим образом:

К настоящему времени (20 мая 2020 г.) в Канаде выявлено 81575 случаев COVID-19, и, к сожалению, 6150 человек погибли из-за этого заболевания.

Машинное обучение и прогнозирование

Отказ от ответственности: эта статья не является медицинским советом, и на нее не следует ссылаться для получения каких-либо медицинских рекомендаций. Любые цифры, числа и даты, представленные в этом разделе, являются лишь предположениями, основанными на алгоритме машинного обучения. На основании этих прогнозов не может быть принято никакого решения.

Prophet был выпущен Facebook в 2017 году для Python и R и дал специалистам по обработке данных по всему миру новые инструменты для анализа временных рядов. Эта модель использует временные ряды и ежедневные наблюдения, чтобы делать прогнозы на основе периодических или непериодических точек изменения. Он также может обнаруживать общую тенденцию в наблюдаемых данных, включая влияние праздников и будних дней. FBprophet в основном используется для анализа фондового рынка и бизнеса. Если вам нужна дополнительная информация, пожалуйста, посетите раздел справки, где есть ссылка на полное введение на GitHub.

При этом мы должны решить, каким должен быть наш импорт. Это должны быть совокупные или ежедневные данные? Это должны быть все данные или только их часть после определенной даты?

Как я уже упоминал, ключевыми в этом алгоритме являются точки тренда и изменения. Если мы импортируем восходящую волну, мы получим аналогичную восходящую волну на основе обнаруженных точек изменения. Точно так же, если мы импортируем нисходящий тренд с подъемами и падениями, он будет выводить аналогичный тренд, пытаясь определить причины этих пиков и минимумов в течение следующих месяцев или недель. Таким образом, импортированные данные должны явно быть ежедневными случаями, а не совокупными цифрами.

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

# Grab an slice of our main DataFrame:
df = Countries['Canada']['Confirmed']
# find the index of maximum value:
index_max = Countries.diff()['Canada']['Confirmed'].rolling(window=7).mean().idxmax()
df = df.reset_index()
# Use rolling average to find the date with maximum number of cases
df['Rolling'] = df['Confirmed'].rolling(window=7).mean()
# for modelling we only use the data after the index_max date:
dfT = df[df['Time']>=index_max]
dfT=dfT.dropna()

Обратите внимание, что столбец для прогнозирования должен называться «y», а временной ряд должен называться «ds», если вы хотите использовать Prophet.

dfT.rename(columns={"Time":'ds','Confirmed':'y'},inplace=True)

Перед любыми дальнейшими шагами мы должны выбрать масштабатор точек изменения для fbprophet. Это значение в нашей модели, которое определяет компромисс между смещением и дисперсией. ChangePoint Scaler - это значение от нуля до единицы; более высокие значения могут привести к чрезмерной подгонке, а более низкие значения могут вызвать недостаточную подгонку. Если эта тема вам не знакома, вы можете обратиться к этой статье за дополнительными пояснениями.

Масштабатор по умолчанию установлен на 0,05, что дает приемлемые результаты, но я запустил цикл, чтобы найти лучшее значение для большей точности при моделировании этого конкретного набора данных; Лучшее число - около 0,09.

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

# First, predict 10 days to see how model react:
dfTrain = dfT[:len(dfT)-10]
# create an instance of fbprophet and fit the training data:
import fbprophet
mymodel = fbprophet.Prophet(changepoint_prior_scale=0.09)
mymodel.fit(dfTrain)
# make an empty dataframe with future dates:
pre_dfT = mymodel.make_future_dataframe(periods=10,freq='D')
pre_dfT = mymodel.predict(pre_dfT)
# calculate the error for each test day:
pre_dfT.set_index('ds',inplace=True)
dfT.set_index('ds',inplace=True)
Merged_df = pd.DataFrame([pre_dfT['yhat'],dfT['y']]).transpose()[:37]
Merged_df['ERROR'] = (Merged_df['yhat'] - Merged_df['y'])/Merged_df['y'] * 100

Как видим, модель показала себя неплохо; наша средняя ошибка за все тестовые дни составляет около 1,5%. То есть наша модель предсказывала точное количество случаев с ошибками только 15 человек на каждые 1000 случаев.

(abs(Merged_df['ERROR'])/Merged_df['y']*100).mean()

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

Мы можем повторить процедуру прогнозирования количества смертей:

С помощью FBprophet мы можем исследовать тенденцию в целом или в недельном масштабе.

mymodel.plot_components(pre_dfT)

Однако поначалу приведенная выше цифра может интуитивно показаться неправильной - поскольку не должно быть никакой разницы в количестве инфицированных в разные дни недели, я считаю, что это дает некоторые факты о результатах тестов и их процедурах.

После некоторого исследования, которое я обнаружил в Канаде из-за большого количества запросов на тест на коронавирус, результаты могут занять до 3 или 5 рабочих дней. С другой стороны, многие люди заказывают тест в начале недели, потому что им не разрешают выходить на улицу по выходным из-за правил социального дистанцирования в Канаде. В результате по четвергам и пятницам мы получаем больше инфицированных.

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

Отказ от ответственности: эта статья не является медицинским советом, и на нее не следует ссылаться для получения каких-либо медицинских рекомендаций. Любые цифры, числа и даты, представленные в этом разделе, являются лишь предположениями, основанными на алгоритме машинного обучения. На основании этих прогнозов не может быть принято никакого решения.

Модель предлагает:

Канада будет отмечать окончание пандемии в последнюю неделю июля. (25 июля)

К 5 июля общее число зараженных вырастет до 10 6293 человека.

Общее количество смертей от COVID-19 вырастет до максимума в 7945 человек к 25 июля (через 20 дней после 5 июля в связи с инкубационным периодом)

Заключение

FBprophet - это быстрый и достаточно точный алгоритм машинного обучения, который без особых усилий может работать с временными рядами.

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

Оставайтесь в безопасности!

Загрузите Jupyter Notebook для этой формы публикации здесь.

использованная литература

Репозиторий Facebook на GitHub

Компромисс между отклонениями и смещениями: переоснащение и недостаточное оснащение