Напишите программу на Java для анализа данных COVID-19 и прогнозирования тенденции.

В 2020 году Таиланд поразительно хорошо справился с COVID-19. Число случаев заболевания и летальных исходов было относительно низким по сравнению с другими странами. Ситуация изменилась с момента последней волны пандемии, начавшейся примерно в апреле 2021 года. Число погибших быстро растет. Хотя в последние месяцы их количество снизилось.

Мы обсудим:

  • Модель SEIR
  • Моделирование SEIR в коде
  • Получение общедоступных данных о COVID
  • Поиск параметров модели
  • Прогнозирование по модели
  • Визуализация результата
  • Визуализация изменения скорости воспроизведения

Модель SEIR

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

Модель делит население на следующие группы:

  • Восприимчивый (S). Лица этой группы еще не инфицированы.
  • Открыт (E). Люди в этой группе инфицированы, но еще не заразны.
  • Инфекционный (I). Группа могла заразить других людей.
  • Восстановлено (R). Люди в группе выздоровели.

Пять дифференциальных уравнений описывают, как количество людей в этих группах меняется со временем. Мы рассматриваем только упрощенную версию, а не строгую, потому что мы игнорируем уровень рождаемости и смертности от других причин.

Параметры модели SEIR:

  • Альфа (𝛼) - это средний уровень смертности от болезней.
  • Бета (𝜷) - это вероятность передачи болезни при одном контакте, умноженная на количество контактов в единицу времени.
  • Эпсилон (𝜺) - это скорость прогрессирования от контакта с инфекционным заболеванием. Это величина, обратная инкубационному периоду.
  • Гамма (𝜸) - это скорость восстановления. Это противоположность заразному периоду.

Чтобы использовать модель для прогнозирования, нам необходимо знать указанные выше параметры, а также следующие значения в начале:

  • Выставленный счет
  • Инфекционный счет
  • Количество восстановленных
  • Счет смерти

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

Так проще реализовать в коде.

Есть два показателя, связанных с COVID-19. Коэффициент воспроизводства (R0) - это среднее количество вторичных случаев, вызванных инфекционным индивидуумом. Если мы проигнорируем естественную рождаемость и смертность от других причин, следующее уравнение описывает коэффициент воспроизводства:

Если R0 меньше 1, заболевание прекращается. Если R0 больше 1, болезнь продолжает распространяться.
Другой фактор - инфекция и летальность (IFR). Следующее уравнение описывает IFR:

Моделирование SEIR в коде

Сначала мы моделируем параметры SEIR в одном классе. Затем мы представляем дифференциальные уравнения в другом.

Класс ModelParameter

Здесь мы инкапсулируем как параметры SEIR, так и начальные условия. Переменные-члены: альфа, бета, эпсилон, гамма, начальное воздействие, инфекция, выздоровление и количество смертей.

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

Класс модели SEIR

Класс модели SEIR имеет один конструктор, который принимает параметр модели в качестве аргумента.

Метод run принимает один параметр - количество дней, которое модель должна прогнозировать. Метод прогона выполняет расчет для прогнозирования количества людей во всех группах в будущем. Метод run имеет вложенный цикл. Внешний цикл обрабатывает сутки. Мы делим каждый день на небольшие промежутки, в нашем случае десять интервалов. Внутренний цикл for будет вычислять приращения количества людей в каждой группе. Для расчетов мы используем разностные уравнения SEIR. Мы помещаем результат в объект SEIRResult.

Получение общедоступных данных о COVID

Наши данные о COVID взяты с этого сайта. Спасибо Дилану Джею и другим участникам.

Мы используем библиотеку Tablesaw для обработки данных таблиц и столбцов. Библиотека может обрабатывать статистический анализ, а также некоторые визуализации данных. Более подробно о столовой пиле можно прочитать здесь.

Население

Данные о населении Таиланда взяты из файла Excel здесь. Хотя в файле гораздо больше информации, нам нужна только общая численность населения страны. Ниже приведен код.

Код прост. Создаем таблицу из файла excel. Затем мы берем первую строку столбца «Итого». Это ценность населения. Наконец, мы устанавливаем его в объект параметра модели.

Брифинг кейсов

Ежедневно новая информация доступна в формате CSV здесь. Ниже приводится пример содержания.

Данных много, но нас интересуют только эти столбцы:

  • Случаи
  • Летальные исходы
  • Восстановлен

Вот код:

  • Сначала мы создаем таблицу, читая онлайн-файл CSV.
  • В таблице много столбцов. Мы удаляем все, кроме столбцов «Дата», «Случаи», «Выздоровление» и «Смерти».
  • Мы вычисляем 7-дневное скользящее среднее столбца «Смерти» и сохраняем его в новом столбце. Мы не будем использовать новый столбец в модели SEIR. Только визуализировать.
  • Далее фильтруем таблицу. Возьмите только те данные, которые относятся к определенной дате или после нее. Дата - начало последней волны COVID в стране.
  • Мы создаем новый столбец «Инфекционные» из столбца «Случаи», вычитая столбец «Восстановлено».
  • Случаи заражения, выздоровления и смерти регистрируются ежедневно. Для каждого мы создаем столбец совокупного значения.
  • Наконец, мы строим графики.

Это три графика:

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

Поиск параметра модели

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

  • Определите неизвестные независимые параметры модели и начальные условия.
  • Определите возможные значения каждого неизвестного параметра.
  • Реализуйте общий поиск по сетке
  • Реализовать поиск по сетке параметров SEIR

Выявление неизвестных независимых параметров

Эти:

  • Альфа
  • Бета
  • Эпсилон
  • Гамма
  • Первоначальный выставленный счет. Неизвестно.
  • Первоначальный инфекционный подсчет. Хотя официальное значение доступно, оно может быть слишком низким, потому что у органа может не быть достаточного количества тестов на COVID. Мы будем относиться к нему как к неизвестному.
  • Первоначальный восстановленный счетчик. По той же причине, что и выше, значение из данных может быть слишком низким. Мы будем относиться к нему как к неизвестному.

Первоначальное количество смертей доступно из полученных нами данных. Он должен быть достаточно надежным.

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

Определение возможных значений каждого неизвестного параметра

Для каждого параметра модели мы определяем или перечисляем возможные значения.

  • Альфа колеблется от 0,000005 до 0,0001.
  • Бета колеблется от 0,05 до 1,0.
  • Эпсилон - это инкубационный период, обратный. Средний инкубационный период составляет 5,2 дня. Мы составляем список значений от 1 / 5,6 до 1 / 4,8.
  • Гамма - это инверсия инфекционного периода. Считается, что период составляет неделю или меньше. Мы составляем список значений от 1/9 до 1/4.
  • Первоначальный выставленный счет. У нас нет точного числа. Мы предполагаем, что он будет начинаться с 2-кратного официального количества инфекционных заболеваний до 20-кратного официального количества инфекционных заболеваний.
  • Первоначальный инфекционный подсчет. По нашим оценкам, он будет начинаться с официального начального количества инфекционных заболеваний до 10-кратного значения.
  • Первоначальный восстановленный счетчик. У нас есть официальный номер; однако правильное число может быть больше. Мы предполагаем, что он начнется с официального подсчета восстановленных до 10-кратного официального числа восстановленных.

Класс GridSearch

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

Параметры метода:

  • Сетка параметров.
  • Ограничение объекта ModelParameter.
  • Целевая функция, которую нам нужно минимизировать. Обычно мы предоставляем функцию ошибок между выходными данными модели и фактическими данными.
  • Размер набора результатов, который должна возвращать функция.

Метод будет оценивать целевую функцию со всеми возможными значениями в сетке. Затем верните отсортированный набор объектов ModelParameter, которые имеют наименьшие значения целевой функции.

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

Вот некоторые пояснения к коду

  • Сначала метод подсчитывает количество создаваемых задач потребителя. Это количество доступных процессоров минус 2.
  • Затем он создает блокирующую двухстороннюю очередь. Deque - это очередь, в которую элемент может быть добавлен или удален как спереди, так и сзади. Дека переплетается. Это означает, что мы можем добавить определенное количество элементов. Задача производителя будет заблокирована, если достигнет предела.
  • Метод создает и отправляет задачу производителя.
  • Задача производителя проверяет ограничение для каждого объекта ModelParameter в сетке, а затем помещает его в двухстороннюю очередь.
  • Для каждого потребителя задача производителя кладет в очередь отравленную пилюлю. Потребители будут знать, когда остановиться.
  • Метод run создает и отправляет задачи потребителя.
  • Каждая задача потребителя создает набор связанных деревьев. Сортируем заданное дерево по значению целевой функции. Кроме того, он сохраняет только наименьшее назначенное количество элементов. Исходный код древовидного набора находится здесь.
  • Каждый потребитель берет объект ModelParameter из двухсторонней очереди. Если это не ядовитая таблетка, оцените целевую функцию и добавьте в набор пару ModelParameter и значение функции. Когда потребительская задача находит отравленную пилюлю, она останавливается.
  • После завершения работы всех потребителей метод run объединяет результат всех и возвращает его вызываемой стороне.

Класс SEIRParameterGridSearch

Этот класс использует таблицу данных из краткого обзора случаев для поиска параметра модели.

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

Поиск по сетке и результат

Приведенный выше код выполняет поиск параметров. Позже трансформируем результат в таблицу. Затем сохраните таблицу как файл CSV, как показано ниже.

  • Мы используем данные за 61 день: с 3 августа 2021 года по 2 октября 2021 года.
  • Наименьшее значение RMSE - 29,9. Мы думаем, что значение имеет смысл, учитывая зашумленность данных.
  • Скорость воспроизведения - 1,6.
  • IFR составляет 0,032%. Это кажется слишком низким. Но, по данным этого сайта, самая низкая смертность - около 0,07%.

Визуализация результата

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

  • Первый график - это ежедневное количество смертей на основе фактических данных и наших моделей. Мы могли видеть, что модели достаточно хорошо согласуются с данными. Кроме того, все результаты модели очень близки.
  • Второй график похож на тот, за исключением того, что мы смотрим на 60 дней в будущее. Мы могли видеть, что прогнозируемое количество смертей постепенно уменьшается. Тем не менее, еще не совсем ноль.
  • На 3-м графике показано количество инфекций по наблюдаемым данным и моделям SEIR. Здесь мы видим, что значения модели намного выше, чем официальное количество инфекционных заболеваний.

Мы увидели, что ситуация для страны кажется лучше.

Визуализация изменения скорости воспроизведения

Посмотрим, как от месяца к месяцу меняется скорость воспроизводства. Мы сделаем это:

  • Разделите данные по делу по месяцам.
  • Запустите поиск в сетке параметров, используя ежемесячные данные.
  • Вычислите ежемесячный коэффициент воспроизводства и нанесите на график данные.

Вот код:

График ниже.

  • В апреле воспроизводимость меньше 1.
  • Затем R0 продолжает увеличиваться до июля.
  • В августе R0 немного снижается, но по-прежнему превышает 1.
  • В сентябре R0 значительно снижается. Теперь значение снова меньше единицы.

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

Вывод

Мы анализируем и прогнозируем тенденцию COVID-19, используя модель SEIR и общедоступные ежедневные онлайн-данные. Результат выглядит многообещающим. Результат модели вполне соответствует наблюдаемым данным.

Вот несколько вещей, которые мы могли бы сделать, чтобы улучшить модель:

  • Мы могли бы включить естественную рождаемость и смертность от других причин.
  • Мы могли бы добавить к уравнениям числа трудящихся-мигрантов.

Все файлы с исходным кодом доступны на GitHub здесь.

Цитата: Дилан Джей. Данные о COVID-19 в Таиланде. Получено с https://github.com/djay/covidthailand. Он находится под Международной лицензией Creative Commons Attribution 4.0.