Описание задачи и решения соревнования Kaggle Understanding Clouds from Satellite Images



Не так давно, в конце 2019 года, я принял участие в данном соревновании и занял в нем второе 
место. В этой статье я расскажу про задачу и опишу методы ее решения.  
Итак, Институт метеорологии Макса Планка и лаборатория динамической метеорологии из 
Франции, совместно с Kaggle организовали соревнование по распознаванию типов облаков. 
Более 60 волонтеров, по предоставленной инструкции, разметили около 10000 спутниковых 
снимков и на них выделили 4 типа облаков. В соревновании участникам предлагалось 
построить алгоритм машинного обучения, который автоматизирует обнаружение облачных 
паттернов путем обучения по данным, размеченным человеком. 
Соревнование имело достаточно низкий порог вхождения (здесь не было датасетов в 600 Гб 
и миллионов картинок). К тому же, у меня уже был определенный опыт решения задач по 
сегментации. А три лучшие команды имели возможность получить призовой фонд 
в размере 10 000 долларов. В общем я просто не мог не принять участие.

Теперь о задаче и зачем все это нужно
Облака являются не только своеобразными отпечатками погоды, но также и регуляторами 
нашего климата. Роль неглубоких облаков в субтропических регионах пассатов для 
энергетического баланса нашего земного шара является одним из важнейших вопросов науки 
о климате. Один из особенно плохо изученных аспектов этих облаков заключается в том, что 
они самоорганизуются в более крупные структуры, которые часто можно увидеть по 
спутниковым снимкам. Чтобы лучше понять эти структуры, ученые классифицировали десять 
тысяч спутниковых изображений на четыре типа, которые они назвали: 
 Sugar, Flower, Fish, и Gravel. Выглядят они примерно так:

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

Входные данные
В обучающей выборке было 5546 спутниковых снимка, в проверочной 3698. 
Разрешение снимков 1400 x 2100. Выглядят они вот так:
Про странные черные полосы на снимках сейчас расскажу. Все данные были загружены c 
сервисов НАСА Worldview. Были выбраны три региона, охватывающие 21 градус долготы и 
14 градусов широты. Изображения были получены с двух полярно-орбитальных спутников, 
TERRA и AQUA, каждый из которых проходит определенную область один раз в день. Из-за 
небольшого размера сканера (MODIS) на борту этих спутников результирующее изображение 
сшивалось из двух кадров с двух разных орбит. Оставшаяся область, которая не была покрыта 
этими двумя кадрами, заливалась черным цветом. Немного не удобно, но, что есть, то есть.

Разметка человеком
Как я уже написал выше, в разметке датасета приняли участие 68 человек и в обработке 
каждого снимка принимало участие не менее 3 человек. Далее области разметки объединялись 
и получилась такая картина. 

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

Метрика
По условиям задачи алгоритм должен выдать предикт в бинарном виде 0/1. И видимо поэтому 
организаторы в качестве метрики выбрали старый, добрый Dice coefficient
Считается он так:
где X - предикт, а Y - разметка. Коэффициент Dice определяется как 1, 
когда X и Y пусты. Оценка в лидерборде - это среднее значение коэффициентов 
Dice для каждой пары в тестовом наборе.

В условии задачи имелась одна особенность. Входная картинка имела размер 1400 x 2100, 
а размер масок предиктов должен был быть в 4 раза меньше, т.е. 350 x 525. Далее бинарные 
маски кодировались алгоритмом RLE в текстовый файл и это и было результатом работы.
На решение задачи давали 3 месяца. Хм... Более чем достаточно для комфортной работы. 
В общем-то, о задаче и все. Давайте будем решать.


Решение
Я постараюсь по возможности понятней описать путь моих “замысловатых мыслей” в разработке
алгоритма.

Архитектура
Для начала нужно было выбрать архитектуру модели сегментации. К счастью, уже давно прошли 
времена, когда вы должны были строить модель с нуля, мучительно подбирая наиболее удачную 
архитектуру, параметры обучения и стратегию валидации. Решая две предыдущие задачи 
сегментации SIIM-ACR Pneumothorax Segmentation и Severstal: Steel Defect Detection, я познакомился 
с чудесной библиотекой Segmentation models. И в ней уже было все что нужно.
Что же у нее под капотом?
Модель сегментации обычно состоит из энкодера и декодера. Если просто, энкодер 
(его еще называют backbone) выделяет признаки из изображения, а декодер из них формирует 
предикт. Набор доступных архитектур в библиотеке впечатляет, 25 предобученных на датасете 
ImageNet архитектур backbone и 4 типа декодеров. Теперь для того чтобы построить модель 
достаточно 10-15 строк кода.
В качестве декодера я выбрал архитектуру Unet. Она была создана в 2015 году для сегментации 
биомедицинских изображений и сейчас является стандартом де факто для решения задач 
сегментации.  До этого соревнования я ее уже использовал многократно и хорошо 
представлял как она работает.
Сеть содержит сжимающий путь (слева) и расширяющий путь (справа), поэтому архитектура 
похожа на букву U, что и отражено в названии.
При выборе энкодера я посматривал на не сильно тяжелые Resnext50, Seresnext50 и достаточно 
новую архитектуру EfficientNetB1. На период экспериментов я хотел, чтобы модели считались 
побыстрее, и я бы оперативно получал результаты экспериментов для дальнейшей работы.
От прошлых задач у меня остался почти готовый пайплайн (процесс разработки модели). 
Нужно было только изменить некоторые параметры, в частности, изменить размер входного 
изображения. И тут я подумал, что 1400 x 2100 - это слишком много для сверточной сети. 
Размер батча будет маленьким и сеть будет очень долго обучаться. Ресайзить картинку в 4 раза 
я не хотел, вдруг что-то из информации потеряется. 


Компрессор
Немного подумав, я решил сделать небольшую промежуточную сеть,, которая бы сохраняла 
полезную информацию при сжатии изображения. Этот прием мы придумали несколько лет назад
в Даталитике, работая над коммерческим проектом для компании Biosense Webster, 
производящей медицинское оборудования для кардиологов, и дали ему имя “компрессор”.
Получилось вот такая конструкция:

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

К входному изображению пришлось добавить 
пустую рамку (4, 38, 4, 38), чтобы при уменьшении 
в 4 раза выходные размеры 352 и 544 делились на 32. 
Это требование архитектуры энкодера. 


Эта идея была первым из существенных факторов, позволившим занять второе место в соревновании.

Стратегия обучения
Проблему высокого разрешения входных изображений мы решили, двигаемся дальше. 
Поиграв с обучением нескольких вариантов сетей и различных стратегий обучения, 
я остановился на двух наиболее удачных архитектурах - EfficientNetB1 и Seresnext50.
Теперь немного о стратегии валидации, тут все просто ... ее нет! 
Обычно я  разделяю все данные на обучающую и проверочную части, но здесь я сознательно 
отступил от общепринятой методики обучения.
Я решил использовать для обучения все доступные данные, а с переобучением бороться 
подбирая число эпох обучения и профиля изменения learning rate LR.  Это существенно ускорило 
разработку и позволило изучить больше возможных архитектур моделей. 
Предполагаю, это было вторым из факторов, позволившим занять высокое место в соревновании.

Профиль изменения LR
Так же я хотел попробовать использовать преимущества нового для меня подхода под 
названием cycle cosine annealing (циклический отжиг). Все известные модели, использующие 
данную технику, показывали стабильно лучшие результаты. Есть даже стратегии изменения LR 
состоящие всего из одного цикла .  Мне показалось, что это уже слишком и я сделал вот такой 
профиль длиной 30 эпох и состоящий из двух циклов.


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


При использовании аугментации входные изображения подвергаются различным искажениям. 
Таким образом увеличивается многообразие обучающих данных и повышается обобщающая 
способность модели. Использовалась хорошо известная библиотека  albumentations. С разной 
долей вероятности к исходному изображению применялись следующие искажения: Equalize, 
CLAHE, VerticalFlip, HorizontalFlip, RandomBrightnessContrast, RandomGamma, Cutout, 
CoarseDropout, ShiftScaleRotate, GaussNoise
После обучения моделей операция аугментации также применялась и при формировании 
предиктов. Этот подход называется Test Time Augmentation.
Входные данные подвергаются преобразованиям fliplr, flipud, fliplr+flipud и подаются на модель. 
После получения предсказаний к ним применяются обратные преобразования и далее все 
предсказания усредняются. Эта операция позволяет существенно увеличить точность 
итогового прогноза. 


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

Формирование бинарных масок
По условиям задачи, нам нужно сформировать бинарные маски, соответствующие типу облаков. 
Они выглядят примерно так:
Поскольку на выходе моделей у нас вероятности в диапазоне 0..1, нам нужно подобрать такой 
оптимальный порог, который бы максимизировал нашу метрику Dice.
У Dice есть одно неприятное свойство. Метрика очень чувствительна к ошибкам False positive. 
Т.е. если y_true у нас не содержит маску, а предсказание содержит хоть один пиксель, мы 
получаем ошибку. Поэтому, кроме подбора порога, подбиралось еще значение min_size
При этом если количество единичных пикселей в маске было меньше min_size, маска обнулялась.
Это позволило убрать шум, мелкие выбросы из предиктов и понизить значение False positive.

Собственно и все. Весь пайплайн, условно можно разделить на шесть шагов:
  1. Предобработка данных 
  2. Компрессор
  3. Модель
  4. TTA
  5. Поиск оптимального порога и min_size 
  6. RLE   
    Посчитав скоры одиночных моделей, я получил такой результат на лидерборде:
    EfficientNetB1:  0.66433
    Seresnext50: 0.66785
    Усреднение EfficientNetB1, Seresnext50: 0.67243
    Последний результат поднял меня до пятого места. Затем я пару недель пробовал некоторые 
    другие идеи - взвешенные суммы предиктов, различные архитектуры, модели object detection 
    FastRCNN, MaskRCNN. За это время моя позиция опустилась в район 30 места. 
    Нужно было усиливать решение.

    Ансамбль
    Объединение прогнозов различных по архитектуре моделей практически всегда дает улучшение 
    результата. Поэтому очевидный способ усилиться - создать ансамбль моделей. Я решил подобрать 
    такие комбинации входных размеров, преобразований и архитектур, чтобы эти наборы свойств 
    были по возможности не похожи друг на друга. 
    В математике такие наборы называются ортогональными.
    У меня получилось вот такая матрица свойств моделей:


    Предикты TTA всех восьми моделей усреднялись и далее считались оптимальный порог и 
    min_size. 

    Финальный результат ансамбля: 
    Public:0.67707  Private:0.67167

    Софт и железо 
    Все вычисления проводились в среде OS Ubuntu 18.04, на рабочей станции i5 6400 / 64Gb / 
    512 SSD / 2Tb HDD / NVidia GTX 1080. 
    Использовался python 3.6, его библиотеки numpy, pandas, scipy, OpenCV 4.1, 
    для создания моделей keras 2.3 и tensorflow 1.14.
    За три недели до окончания соревнования, для ускорения обучения,  добавил два инстанса 
    Amazon p3.2xlarge с GPU Nvidia V100.
    Среднее время обучения одной модели на p3.2xlarge составило около 15 часов.

    Идеи и методы которые не дали результата 
    • Loss: BCE-DICE, lovasz, triple_loss.
    • Классификатор наличия маски 
    • Различные варианты многофолдовых моделей, Adversarial validation.
    • Pseudo labeling.
    • модели mmdetection / FasterRCNN / MaskRCNN.


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

    Андрей Кирясов, Даталитика, 2020г.

    Комментарии

    Популярные сообщения из этого блога

    Подготовка данных для алгоритмов машинного обучения

    Выбор метрики в машинном обучении

    Обзор библиотеки PyQtGraph на языке python для интерактивной визуализации графиков