Начните прием заявок на участие в сателлитном конкурсе по машинному обучению

Подробное руководство по началу работы с конкурсом ETCI Flood Detection.

*** Обратите внимание, если вы найдете это руководство полезным или интересная проблема, ознакомьтесь с нашими текущими вакансиями по адресу https://cloudtostreet.info/careers. Мы всегда ищем увлеченных экспертов, которые присоединятся к нашей растущей команде! ***

Вступление

Соревнование по обнаружению наводнений ETCI - это новое захватывающее соревнование по машинному обучению, организованное группой NASA по межведомственному внедрению и продвинутым концепциям. Цель конкурса - обнаружение наводнений по спутниковым снимкам. Эта задача особенно важна для нас в Cloud to Street, поскольку наша миссия - обнаруживать события наводнения практически в реальном времени в любой точке мира, чтобы спасти жизни и улучшить прямую помощь наиболее пострадавшим. Поэтому мы хотели бы поделиться нашим опытом в области машинного обучения и дистанционного зондирования, чтобы помочь участникам сделать все возможное в этом конкурсе или просто узнать больше об увлекательной области машинного обучения. Если вас интересуют аналогичные наборы данных, мы недавно опубликовали набор данных Sentinel1Floods11, который можно использовать для обучения моделей обнаружения воды на радиолокационных и оптических спутниковых изображениях. Ознакомьтесь с нашими другими идеями и усилиями, чтобы сделать обнаружение наводнений с помощью машинного обучения повышением устойчивости к изменению климата, включая исследования как включить данные краудсорсинга в модели сегментации наводнений и использование GAN для синтеза SWIR и сегментирования наводнений на Planetscope.

Вы можете скачать набор данных и найти весь код в этом руководстве здесь: Google CoLab

Оглавление:

  1. Спутниковые данные
  2. Аннотационные данные
  3. Загрузка и форматирование набора данных
  4. Создание модели семантической сегментации
  5. Обучение модели
  6. Тестирование модели
  7. Представление наших результатов
  8. Дополнительно: изучение шума в наборе данных

Спутниковые данные

Теперь давайте углубимся в набор данных. Набор данных состоит из изображений РСА с синтезированной апертурой, сделанных в нескольких регионах, где произошло наводнение. Для тех, кто не знаком с этим типом спутниковых изображений, изображения SAR получают с помощью активного микроволнового датчика, установленного на спутнике. Системы SAR передают импульсы электромагнитных волн к поверхности Земли и регистрируют соответствующие эхо-сигналы. Это отличается от оптических спутниковых изображений, которые захватывают отраженный солнечный свет и могут обеспечить изображение поверхности Земли только в дневное время и при отсутствии облаков.

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

Если мы возьмем случайное изображение из набора данных, мы найдем пару изображений с одинаковой датой и номером плитки с именем «‹region› _ ‹datetime› * _x - * _ y - * _‹ vv | vh ›.png». Постфиксы VV и VH обозначают состояние поляризации передаваемых и принимаемых радиолокационных сигналов. VV обозначает радар с вертикальной поляризацией в переданном и принимаемый радар с вертикальной поляризацией. VH обозначает радар с вертикальной поляризацией в переданном и принимаемый радар с горизонтальной поляризацией. Обычно значения SAR-изображений сильно различаются, но команда NASA уже предварительно обработала и масштабировала изображения до целочисленных значений от 0 до 255, что облегчило нам работу с ними. Создатели этого набора данных также разделили (так называемые обрезанные) большие исходные изображения на более удобные изображения размером 256x256 пикселей2. Изображения были собраны в нескольких регионах мира, включая Небраску, США, Алабаму, США, Бангладеш, Индию, Ред-Ривер, север США, и Флоренцию, Италия. Изображения регионов были сделаны в течение нескольких дней. Давайте посмотрим на некоторые из этих изображений:

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

Или в терминах Python:

Последние три канала RGB-изображения имеют синий цвет там, где есть вода, что позволяет даже тем, кто не знаком с этим типом изображения, увидеть воду.

Аннотационные данные

Теперь, когда мы хорошо понимаем, как выглядят данные, давайте проанализируем, что модели машинного обучения будет предложено создать. В конце концов, модель возьмет входное изображение, подобное предыдущему разделу, и создаст изображение того же размера с двоичными значениями 0 и 1, соответствующими «не зоне затопления» или «зоне затопления». Создатели этой задачи предоставляют нам маску наводнения для каждого изображения в обучающем наборе и маску водного тела для всех обучающих и проверочных изображений. Давайте посмотрим на некоторые изображения RGB, маски наводнения и маски водоемов:

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

Загрузка и форматирование набора данных

Скачивание набора данных о соревнованиях

Чтобы получить доступ к набору данных, нам необходимо сначала войти в систему или создать профиль CodaLab. После того, как у вас есть аккаунт, вы должны подать заявку на конкурс. После получения подтверждения (должно быть меньше суток) вы можете загрузить файлы по ссылке на Google Диск в разделе Участвовать → Получить данные. Если вы используете удаленную систему и хотите загрузить файл напрямую, вы можете использовать пакет gdown. Чтобы следовать руководству, мы рекомендуем вам создать папку, в которой будут размещены наборы данных для обучения и проверки.

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

Создание фреймов данных

Теперь, когда у нас есть загруженный набор данных, мы хотим отформатировать данные так, чтобы получение изображения и всей его дополнительной информации было быстрым и простым. Популярным фреймворком для организации наборов данных является DataFrame из библиотеки Pandas. Мы можем использовать эту структуру данных для многих целей, включая поиск маски потока изображений или поиск всех изображений для определенного региона. Для целей этого руководства мы будем использовать класс DataFrame как легко доступный лист Excel, но не стесняйтесь узнать больше об удивительных возможностях этой структуры данных. Мы построим отдельные DataFrames для обучающего и проверочного наборов.

Давайте создадим обучающий DataFrame. Обратите внимание: этот раздел может сбивать с толку, поэтому вы можете просто запустить код в Colab, скопировать и вставить этот код и перейти к следующему разделу. Мы начинаем с нахождения всех путей к изображениям VV, извлечения имен файлов и нахождения регионов, которым они принадлежали.

Затем мы пройдемся по этим путям, чтобы найти соответствующее изображение VH, маску водного тела, маску наводнения и название региона. В каждом цикле for мы настраиваем пути к файлам и используем имя изображения VV, чтобы найти соответствующий путь и поместить его в конкретный объект списка.

Наконец, мы создаем словарь, который будет использоваться для создания Dataframe. Ключи будут заголовками столбцов нашего DataFrame, а значения будут столбцами. Вы можете получить размер фрейма данных с помощью train_df.shape и просмотреть первые пять строк данных с помощью train_df.head ().

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

Создание разделов обучения и развития

Набор для проверки не содержит ярлыков, поэтому мы не можем использовать его количественно, чтобы измерить, насколько хорошо работает наша обученная модель. Поэтому мы создаем набор для разработки, разбивая обучающий набор. Обратите внимание, что точное определение термина «набор для разработки» варьируется в области машинного обучения, но вы можете думать о наборе для разработки в этом случае как «набор для проверки», а фактический набор для проверки - как «набор для тестирования». Есть много способов разбить набор данных на набор для обучения и развития, но для соответствия сценарию реальной жизни мы собираемся разделить набор для обучения по регионам. В обучающий набор входят три региона: Небраска, Алабама (север) и Бангладеш. Мы случайным образом выбираем один регион для набора разработки, а остальные оставляем в обучающем наборе.

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

Создание класса набора данных

В Cloud to Street мы используем PyTorch в качестве нашей библиотеки глубокого обучения, поэтому мы будем использовать ее и в этом руководстве. Все современные библиотеки глубокого обучения (PyTorch, TensorFlow, Keras, MXNet и т. Д.) Одинаково мощны, но многим исследователям и инженерам нравится PyTorch за простоту использования и взаимодействие с динамическими моделями.

При этом нам нужно создать класс PyTorch Dataset, чтобы позже передать данные в модель. Вы можете следовать этому официальному руководству по PyTorch, чтобы узнать об этом еще больше. Чтобы создать собственный объект набора данных PyTorch, мы создаем дочерний класс на основе класса набора данных PyTorch. Нам нужно перезаписать методы __init__, __len__ и __getitem__.

Метод __init__ - это то место, где мы загружаем набор данных, который просто загружает DataFrame. Метод __len__ просто возвращает общее количество пар VV и VH, которые есть в наборе данных. Метод __getitem__ получает индекс набора данных и загружает пример для модели. В этом методе мы загружаем изображения в память, нормализуем их от 0–255 до 0–1, объединяем изображения VV и VH в изображение RGB и, наконец, применяем функции преобразования перед возвратом примера.

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

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

PyTorch использует специальный класс, называемый DataLoader, для эффективной загрузки примеров из нашего класса Dataset с использованием параллельной обработки. Мы можем установить такие параметры, как размер пакета, количество параллельных процессов (num_workers) и перемешивание порядка.

Создание модели семантической сегментации

Мы только что узнали, как загружать изображения и подготавливать их для использования в модели глубокого обучения, а теперь давайте построим нашу модель. Существуют тысячи различных моделей семантической сегментации, и вы даже можете создать свою собственную, однако мы будем использовать испытанную и надежную архитектуру UNet, разработанную Роннебергером и др. Эта сеть возьмет наше входное изображение RGB, обработает его, а затем создаст маску сегментации того же размера, что и наш вход. Чтобы быстро начать работу, мы воспользуемся пакетом Segmentation Models PyTorch package, чтобы получить нашу модель UNet.

У нас есть несколько вариантов на выбор для этой модели. Наиболее важными для нас являются in_channels и аргументы класса. Поскольку мы преобразовали наши изображения в трехканальное изображение (RGB), мы выбираем 3 in_channels. Наша модель предсказывает либо наводнение, либо отсутствие наводнения на изображении, поэтому у нас количество классов 2.

Для эффективного обучения модели вам следует найти графический процессор для обучения вашей модели. Предположим, что он у вас есть или вы используете Google CoLab и выбрали экземпляр графического процессора. В PyTorch нам нужно загрузить модель и данные в память графического процессора для быстрых вычислений. Сделать это можно просто так:

device = 'cuda' 
model.to(device)

Если у вас нет доступа к графическому процессору, вы все равно можете играть с этим кодом, но мы не рекомендуем обучать вашу модель, так как это займет очень много времени. Чтобы запустить этот код без графического процессора, вам нужно только вместо этого установить device = ‘cpu’.

device = 'cpu'

Обучение модели

У нас есть отформатированные данные и загруженная модель, давайте обучим модель! Чтобы обучить модель, нам нужно знать, как обновлять ее веса и как отслеживать производительность модели. Мы будем использовать встроенный оптимизатор Adam и CrossEntropyLoss.

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

Мы можем отслеживать прогресс модели, отслеживая потери и другие метрики, такие как среднее пересечение по метрике объединения (mIoU). Эта метрика дает нам представление о том, насколько хорошо предсказания нашей модели перекрывают основную истину. Мы вычисляем глобальное среднее значение mIoU для всех изображений в наборах.

Тестирование модели

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

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

После того, как модель прошла через все данные в наборе проверки, мы конвертируем наши списки прогнозов и входных данных в массивы numpy:

Посмотреть наши результаты

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

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

Отправка наших результатов

Как только мы будем довольны окончательными прогнозами нашей модели, мы можем отправить результаты в CodaLab и оценить их. Согласно инструкциям конкурса, нам нужно сохранить наши двоичные изображения результатов в виде zip-файла. Поскольку в Python нет простого способа сделать это (если есть, сообщите нам!), Мы сохраним наши прогнозы с помощью np.save (), а затем заархивируем файл из командной строки. Обратите внимание: нам нужно правильно задать следующие аргументы, чтобы обеспечить обратную совместимость с Python 2.7 (который, по-видимому, используется для оценки результатов).

Если вы используете Linux на основе Ubuntu, вы сможете заархивировать файл из Python:

Последний файл submission.zip готов к загрузке и оценке!

Дополнительно: изучение шума в наборе данных

Некоторые из вас, возможно, заметили неправильные изображения при изучении набора данных, как мы. Похоже, что некоторые плитки на краю собранных изображений SAR не содержат информации и не были удалены. Эти изображения содержат все значения 0 или 255 без каких-либо особенностей местности. Отфильтруем эти изображения из обучающей выборки! Мы берем наш полезный обучающий DataFrame и находим все пути изображений VV (мы используем изображения VV, но изображения VH, похоже, имеют те же значения в шумных случаях). Затем мы загружаем каждое изображение VV ​​и проверяем уникальные значения в изображении, если они содержат только 0 или 255 значений, мы отмечаем их индекс.

Все изображения с отслеживаемыми индексами удаляются из обучающего DataFrame, оставляя только изображения с хотя бы некоторыми данными о местности (оказывается, это 75% данных! Хороший эксперимент - посмотреть, улучшит ли удаление этих изображений производительность моделей.