Интерактивное введение в глубокое геопространственное обучение в Google Colab

автор daveluo (на гитхабе и в других местах)

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

Все, что вам понадобится, это учетная запись Google, подключение к Интернету и пара часов, чтобы научиться создавать данные и модель, которая учится создавать что-то вроде этого:

Постепенно мы научимся…

Предварительно обработайте файлы изображений geoTIFF и вручную помеченные файлы данных geoJSON в обучающие данные для глубокого обучения:

Создайте модель сегментации U-net, чтобы предсказать, какие пиксели на изображении представляют здания (и связанные со зданиями особенности):

Проверьте производительность нашей модели на невидимых изображениях с помощью графического процессора или процессора:

Постобработка необработанных выходных данных модели в георегистрируемые формы зданий, оцениваемых на основании фактов:

Попутно мы познакомимся с отличными геопространственными данными и инструментами / ресурсами глубокого обучения, такими как:

Как получить максимальную отдачу от этого урока:

Блокнот Colab - это наш главный учебный ресурс - мы настоятельно рекомендуем работать в интерактивном режиме в среде ноутбука Colab с ускорением на GPU!

Код состоит из модульных разделов, настроенных для установки / импорта всех необходимых зависимостей и исполняемых на процессоре или графическом процессоре (в зависимости от раздела). Ссылки для загрузки файлов, сгенерированные на каждом этапе, также включены, поэтому вы можете выбрать и начать с любого раздела. Inline# comments (и ссылки для дальнейшего чтения) предоставляются в ячейках кода для более подробного объяснения шагов или нюансов по мере необходимости. Сквозное выполнение всех ячеек кода на GPU занимает ‹1 часа.

Этот пост среднего уровня служит концептуальным пошаговым руководством на высоком уровне и сопоставляется непосредственно с разделами в записной книжке Colab. Этот пост лучше всего подходит для краткого обзора с удобными закладками на Colab (см. [Ссылка на раздел Colab] под заголовком каждого раздела) или просматривается рядом с записной книжкой Colab в качестве сопутствующего набора кода и концепции. .

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

С этим в качестве психологической подготовки давайте займемся глубинным геопространственным обучением!

Откройте учебную записную книжку и создайте свою собственную рабочую копию Colab с помощью File > Save a Copy in Drive (рекомендуемый вариант):

Или просмотрите блокнот в неинтерактивном режиме (не рекомендуется для оптимального обучения, но подходит для быстрого просмотра):



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

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

[Ссылка на раздел Colab]

В этом руководстве мы будем использовать набор данных Tanzania Open AI Challenge, состоящий из снимков с дронов с разрешением 7 см и этикеток с контурами зданий над островом Унгуджа, Занзибар, Танзания. Большое спасибо следующим организациям за создание, открытое лицензирование и предоставление доступа к этому бесценному набору данных:

  • CC-BY-4.0 по лицензии Комиссии по земельным ресурсам (COLA) - Революционного правительства Занзибара (RGoZ)
  • Помеченные данные, созданные и обработанные Государственным университетом Занзибара (SUZA), World Bank OpenDRI, WeRobotics
  • Снимки с дрона, созданные Zanzibar Mapping Initiative и размещенные на OpenAerialMap:

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

Мы будем работать с изображениями и надписями из сетки изображений znz001, покрывающей северную оконечность главного острова Занзибара, Унгуджа. Вот просматриваемый предварительный просмотр изображений беспилотника znz001 с соответствующими метками контуров зданий, проиндексированных в соответствии с расширением меток Spatio-Temporal Asset Catalog (STAC) и визуализированных в экземпляре STAC browser:

После предварительного просмотра помеченных данных и изображений в браузере мы импортируем наши инструменты геообработки, копируем URL-адреса прямой загрузки из вкладки «Ресурсы» браузера и тестируем их загрузку в нашей записной книжке.

Нарисуйте области обучения и проверки (AOI) с помощью geojson.io

[ссылка на раздел Colab]

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

Используя geojson.io, мы нарисуем нашиtrn и val полигоны областей интереса (AOI) в формате geojson и добавим dataset:trn или dataset:val к соответствующему многоугольнику properties.

Готовые полигоны в geojson.io будут выглядеть примерно так:

И вот точный файл GeoJSON, который я создал, отображается в github gist:

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

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

Рисование AOI в виде многоугольников geoJSON таким образом дает нам гибкость в выборе, что именно и где представляют данные для обучения и проверки.

Преобразование AOI поездов и валидации в скользящие многоугольники тайлов карты с помощью supermercado и geopandas

[ссылка на раздел Colab]

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

В этом руководстве мы будем работать со скользкими фрагментами карты tile_size=256 и zoom_level=19, которые дают управляемое количество фрагментов и удовлетворительные результаты сегментации без слишком длительного времени на предварительную обработку или обучение модели.

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

Вот пример другой плитки zoom_levels над одним и тем же районом Занзибара (см. Круглую белую тарелку спутникового телевидения для визуального ориентира одинакового размера):

Узнайте больше о скользких картах здесь, здесь и здесь.

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

Загрузите изображение фрагмента скользящей карты из COG с помощью rio-tiler и соответствующей метки с геопандами

[ссылка на раздел Colab]

Теперь мы будем использовать rio-tiler и многоугольники фрагментов скользящей карты, сгенерированные supermercado, чтобы протестировать загрузку одного фрагмента 256x256 пикселей из нашего файла изображения znz001 COG. Мы также загрузим znz001 метки geoJSON в geopandas GeoDataFrame и обрежем геометрию здания только до тех, которые пересекают границы изображения плитки:

Винсент Сараго из Development Seed:



Затем мы создадим нашу соответствующую 3-канальную маску RGB, передав эти обрезанные геометрии в функцию df_to_px_mask solaris. Значение 255 пикселей в сгенерированной маске:

  • в 1-м (красном) канале изображены следы строений,
  • во 2-м (зеленом) канале представляют границы здания (визуально выглядит желтым на отображении маски RGB, потому что пиксели перекрывают красный и зеленый + красный = желтый),
  • а в 3-м (синем) канале представляют собой точки тесного контакта между соседними зданиями.

Сделайте и сохраните все плитки изображений и масок

[ссылка на раздел Colab]

Теперь, когда мы успешно загрузили одно изображение плитки из COG с помощью rio-tiler и создали его 3-канальную маску RGB с помощью solaris, давайте сгенерируем наши полные наборы данных для обучения и проверки. Мы напишем несколько функций и циклов, чтобы пройти через все наши trn и val плитки в zoom_level=19 и сохранить их как файлы без потерь png в соответствующие папки со схемой имени файла {save_path}/{prefix}{z}_{x}_{y}, чтобы мы могли легко идентифицировать и геолокатировать плитку, которую представляет каждый файл.

Обучите модель сегментации u-net с помощью fastai и pytorch

В качестве нашего фреймворка для глубокого обучения и библиотеки инструментов мы будем использовать отличную библиотеку fastai, созданную на основе PyTorch. Для получения дополнительной информации:

Загрузите и установите fastai, при необходимости установите Colab на время выполнения GPU

[ссылка на раздел Colab]

Давайте скачаем, установим и настроим fastai v1 (сейчас 1.0.55). И если мы еще этого не сделали, давайте переустановим Colab в среду выполнения GPU (это удалит локально сохраненные файлы, так как он переключается на новую среду, поэтому вам придется повторно загрузить и разархивировать набор данных обучения, созданный в вышеуказанных шагах):

Бесплатные графические процессоры Colab варьируются от Tesla K80, T4 или T8 в зависимости от их доступности. См. Раздел ===Hardware=== документа show_install(), чтобы узнать, какой тип графического процессора и сколько памяти графического процессора доступно, что повлияет на размер пакета и время обучения.

Для всех этих графических процессоров и размеров памяти размер пакета bs=16 при size=256 должен тренироваться со скоростью bs до 8.

Настроить данные

[ссылка на раздел Colab]

Теперь мы настроим наш обучающий набор данных мозаичных изображений и масок, созданных выше, для правильной загрузки в fastai для обучения и проверки. Код на этом шаге очень похож на код урока 3-camvid курса fastai, поэтому, пожалуйста, обратитесь к этим видео урока и записной книжке для более подробного и превосходного объяснения Джереми Ховарда кода и API блока данных fastai.

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

# define the valdation set by fn prefix
holdout_grids = ['znz001val_']
valid_idx = [i for i,o in enumerate(fnames) if any(c in str(o) for c in holdout_grids)]

И мы создадим подкласс SegmentationLabelList, чтобы изменить поведение open_mask и PIL.Image, лежащих в его основе, чтобы открывать 3-канальные целевые маски как изображения RGB (convert_mode=’RGB’) вместо стандартных 1-канальных изображений в оттенках серого (convert_mode=’L’).

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

Определение пользовательских потерь и показателей для обработки трехканальных целевых масок

[ссылка на раздел Colab]

Здесь мы реализуем некоторые новые функции потерь, такие как Dice Loss и Focal Loss, которые, как было показано, хорошо работают в задачах сегментации изображений. Затем мы создадим класс MultiChComboLoss, чтобы объединить несколько функций потерь и вычислить их по 3 каналам с регулируемым весом.

Подход комбинирования потерь в кости или Жаккара для учета контекста всего изображения с индивидуальной пиксельной бинарной перекрестной энтропией или потерями фокуса с регулируемым взвешиванием 3 каналов целевой маски, как было показано, последовательно превосходит функции одиночных потерь. Это хорошо подтверждается подробным описанием Ника Вейра недавних пяти лучших результатов SpaceNet 4 Off-Nadir Building Detection:



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

Настроить модель

[ссылка на раздел Colab]

Мы настроим модель Fastai Dynamic Unet с предварительно обученным кодировщиком resnet34 ImageNet. Эта архитектура, вдохновленная оригинальной U-net, по умолчанию использует многие передовые методы глубокого обучения, такие как:

Мы определим нашу MultiChComboLoss функцию как сбалансированную комбинацию Focal Loss и Dice Loss и установим нашу точность и показатели:

# set up metrics
acc_ch0 = partial(acc_thresh_multich, one_ch=0)
dice_ch0 = partial(dice_multich, one_ch=0)
metrics = [acc_thresh_multich, dice_multich, acc_ch0, dice_ch0]
# combo Focal + Dice loss with equal channel wts
learn = unet_learner(data, models.resnet34,
                     model_dir='../../models',
                     metrics=metrics, 
                     loss_func=MultiChComboLoss(
                        reduction='mean',
                        loss_funcs=[FocalLoss(gamma=1, alpha=0.95),
                                    DiceLoss()], 
                        loss_wts=[1,1],
                        ch_wts=[1,1,1])
                    )

Также обратите внимание, что наши метрики, отображаемые во время обучения, показывают точность канала 0 (только канал следа здания) и метрики кубиков в крайних правых 2 столбцах, в то время как первые две метрики точности и кубика (левые столбцы) показывают среднее значение соответствующей метрики. по всем 3 каналам.

Обучить модель, проверить результаты, разморозить и обучить, экспортировать для вывода

[ссылка на раздел Colab]

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

Мы будем отслеживать показатели valid_loss, acc_... и dice_... для каждой эпохи по мере продвижения обучения, чтобы убедиться, что они продолжают улучшаться и мы не переобучаем. И мы устанавливаем SaveModelCallback, который будет отслеживать счет кубиков канала 0, сохранять контрольную точку модели каждый раз, когда есть улучшение, и перезагружать файл наиболее эффективной контрольной точки модели в конце обучения.

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

Совет для профессионалов: отображайте и просматривайте свои результаты при любой возможности! Вы получите множество интересных подсказок о поведении вашей модели и о том, как ее улучшить.

Наконец, мы экспортируем нашу обученную модель сегментации Unet для целей вывода в виде .pkl файла. Узнайте больше об экспорте моделей fastai для вывода в этом руководстве:



Вывод на новые образы

[ссылка на раздел Colab]

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

Мы также сравним время вывода нашей модели на плитку на GPU и CPU:

Постобработка

Прогнозирование по плитке, порогу, полигонизации и георегистратору

[ссылка на раздел Colab]

Для хорошей оценки производительности модели на основе фактов мы будем использовать другой набор помеченных данных, на которых модель не была обучена. Мы получим это из более крупного набора данных о Занзибаре. Предварительно просмотрите изображения и метки наземных истинных данных для znz029 в браузере STAC здесь:

Для демонстрации мы будем использовать эту конкретную плитку в z=19, x=319454, y=270706 с znz029:

Используя solaris и geopandas, мы преобразуем прогноз нашей модели в виде трехканального пиксельного растрового изображения в файл GeoJSON следующим образом:

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

Оценивайте предсказание относительно истинного положения вещей

[ссылка на раздел Colab]

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

Мы закрепим метки истинности на границах этой конкретной плитки и воспользуемся функцией Solaris Evaluator для расчета точности, отзыва и оценки F1. Мы также визуализируем наши предсказанные здания (красным) на фоне наземных зданий (синего цвета) на этой конкретной плитке:

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





Идеи для повышения производительности

Поздравляю, у вас получилось!

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

Чтобы усовершенствовать полученные знания и сделать вашу модель потенциально намного лучше, попробуйте реализовать некоторые или все эти идеи:

  • Создавайте и используйте больше обучающих данных: существует 13 таблиц обучающих данных для Занзибара, выпущенных как часть набора данных Open AI Tanzania Building Footprint Segmentation Challenge.
  • Измените zoom_level плитки обучения / проверки. А еще лучше попробовать использовать плитки с разными масштабами (например, z21, z20, z19, z18). Обратите внимание, что при использовании нескольких уровней масштабирования для одного и того же изображения следует проявлять особую осторожность, чтобы не перекрывать плитки на этих разных уровнях масштабирования. ← проверьте свое понимание скользких фрагментов карты, убедившись, что вы понимаете, что я имею в виду, но не стесняйтесь писать мне для ответа!
  • Измените кодировщик Unet на более крупную или другую архитектуру (например, resnet50, resnet101, densenet).
  • Измените комбинации, веса и гиперпараметры функций потерь. Или реализовать совершенно новые функции потерь, такие как Lovasz Loss.
  • Попробуйте разные комбинации и методы увеличения данных.
  • Тренируйтесь для большего количества эпох и с разными графиками обучения. Попробуйте смешанную точность для более быстрого обучения модели.
  • Ваша идея здесь.

Я с нетерпением жду того, что вы откроете для себя!

Скоро

Если вам понравился этот урок, ждите следующих, которые потенциально будут охватывать такие темы, как:

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

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

Удачи и счастливого глубокого обучения!

Благодарности и особая благодарность