Хабрахабр

Kaggle: Amazon from Space — трюки и хаки при обучении нейросетей

Наша команда заняла 7 место из 900+ участников. Летом прошлого года закончилось соревнование на площадке kaggle, которое было посвящено классификации спутниковых снимков лесов Амазонки. За подробностями под кат.
tldr.py Не смотря на то, что соревнование закончилось давно, почти все приемы нашего решения применимы до сих пор, причём не только для соревнований, но и для обучения нейросетей для прода.

import kaggle
from ods import albu, alno, kostia, n01z3, nizhib, romul, ternaus
from dataset import x_train, y_train, x_test oof_train, oof_test = [], []
for member in [albu, alno, kostia, n01z3, nizhib, romul, ternaus]: for model in member.models: model.fit_10folds(x_train, y_train, config=member.fit_config) oof_train.append(model.predict_oof_tta(x_train, config=member.tta_config)) oof_test.append(model.predict_oof_tta(x_test, config=member.tta_config)) for model in albu.second_level: model.fit(oof_train) y_test = model.predict_proba(oof_test) y_test = kostia.bayes_f2_opt(y_test)
kaggle.submit(y_test)

Описание задачи

Planet подготовила набор спутниковых снимков в двух форматах:

  1. TIF — 16 bit RGB + N, где N — Near Infra Red
  2. JPG — 8bit RGB, которые производные от TIF и которые были предоставлены для уменьшения порога входа в задачу, а также для упрощения визуализации. В предыдущем соревновании на Kaggle, необходимо было работать с мультиспектральными изображениями. невизуальные, то есть инфракрасный, а также каналы с большей длиной волны очень сильно улучшали качество предсказания, причем как сети, так и unsupervised методы.

Географически данные были взяты с территории бассейна реки Amazon, и с территорий стран Brazil, Peru, Uruguay, Colombia, Venezuela, Guyana, Bolivia, and Ecuador, в которых были выбраны интересные участки поверхности, снимки с которых и были предложены участникам.

И по полученным jpg силами работников Planet из Берлинского и Сан Францисского офиса, а также через платформу Crowd Flower, производилась маркировка. После того, как из tif создавались jpg, все сцены резались на мелкие куски размером 256x256.

Перед участниками ставилась задача для каждого 256x256 тайла предсказать одну из взаимоисключающих погодных меток:

Cloudy, Partly cloudy, Haze, Clear

А также 0 или более непогодных: Agriculture, Primary, Selective Logging, Habitation, Water, Roads, Shifting Cultivation, Blooming, Conventional Mining

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

Точность модели оценивалась по метрике F2:

$Score=(1+\beta^2)\frac{(\beta^2p + r)}$

$p=\frac{tp}{tp +fp}$

$r=\frac{tp}{tp +fn}$

$\beta=2$

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

В тесте 40к. Всего в трейне 40к сэмплов. Из-за небольшого размера датасета, но большого размера картинок, можно сказать, что это “MNIST на стероидах”

Лирическое отступление

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

member

net

1crop

TTA

diff, %

alno

densenet121

0.9278

0.9294

0.1736

nizhib

densenet169

0.9243

0.9277

0.3733

romul

vgg16

0.9266

0.9267

0.0186

ternaus

densenet121

0.9232

0.9241

0.0921

albu

densenet121

0.9294

0.9312

0.1933

kostia

resnet50

0.9262

0.9271

0.0907

n01z3

resnext50

0.9281

0.9298

0.1896

В таблице приведены F2 score моделей всех участников для single crop и TTA. Как видно, разница невелика для реального использования, однако это важно для режима соревнования.

Командное взаимодействие

Но с тех пор затащил кучу соревнований, стал отцов вся ODS по семантической сегментации и уехал в Минск, грести в Mapbox, про что вышла статья Александр Буслаев albu
На момент участия в соревновании руководил всем мл направлением в компании Geoscan.

Работал в Evil Martians. Алексей Носков alno
Универсальный мл боец. Сейчас перекатился в Yandex.

С тех пор Костя успел получить еще несколько медалей и без 5 минут Kaggle Grandmaster Константин Лопухин kostialopuhin
Работал и продолжает работать в Scrapinghub.

Но в районе нового года перекатился в блокчейн стартап Dbrain на должность Lead Data Scientist. Артур Кузин n01z3
На момент участия в этом соревновании я работал в Avito. Надеюсь, скоро порадуем комьюнити своими конкурсами с докерами и ламповой разметкой.

С этого соревнования Женя открыл в себе тайное умение находить лики в картиночных конкурсах. Евгений Нижибицкий @nizhib
Lead Data Scientist в Rambler & Co. Об одном из них я рассказывал. Что помогло ему затащить пару соревнований на платформе Topcoder.

Руслан Байкулов romul
Занимается трекингом спортивных событий в компании Constanta.

Работал в TrueAccord, но затем перекатился в модный-молодежный Lyft. Владимир Игловиков ternaus
Мог вам запомниться по остросюжетным статье о притеснении британской разведкой. Продолжается тащить соревнования и недавно получил Kaggle Grandmaster. Где занимается Computer Vision для Self-Driving car.

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

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

Гистограмма классов по фолдам:

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

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

Обучение нейросетей

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

Общий подход


Картинка из github.com/tornadomeet/ResNet

Стартуют с рандомно инициализированных весов с SGD (lr 0. Типичный процесс обучения представлен на графике обучения Resnet нейросетей на imagenet’e. 0001 WD 0. 1 Nesterov Momentum 0. 9) и затем через 30 эпох понижают learning rate в 10 раз.

Либо некоторые участники просто сократили количество эпох на каждом уроне LR и понижали по расписанию. Концептуально каждый из нас использовал такой же подход, однако чтобы не состариться пока обучается каждая сеть, понижение LR происходило если на валидации лосс не падал 3-5 эпох подряд.

Аугментации

Аугментации должны отражать вариативность природы данных. Выбор правильных аугментаций очень важен при обучении нейросетей. Под смещением можно понимать разные низкоуровневые статистики, типа гистограмм цветов или характерный размер. Условно аугментации можно разделить на два типа: те, которые вносят смещение в данные, и те, которые не вносят. В этом плане, скажем, HSV аугментации и скейл — вносят смещение, а рандомный кроп — нет.

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

Замораживание слоев

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

Циклический отжиг

После завершений базового процесса обучения нейросети берутся лучшие веса и процесс обучения повторяется. Этот процесс выглядит так. Это позволяет нейросети спуститься в более низкий локальный минимум и показать лучший перформанс. Но стартует он с более низкого Learning rate и происходит за короткое время, скажем 3-5 эпох. Этот поход стабильного улучшает результат в довольно широком числе конкурсов.

Более подробно про два приема здесь

Test time augmentations

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

Snapshot Ensembling (Multicheckpoint TTA)

На каждой стадии отжига нейросеть залетает в немного разные локальные минимумы. Идеей отжига можно развить дальше. Таким образом во время предсказаний теста можно взять три лучших чекпоинта и усреднить их предсказания. А это значит, что это по сути немного разные модели, которые можно усреднить. Ну и для продакшена такой трюк не применим и я пробовал усреднять веса моделей. Я также пробовал брать не три лучших, а три самых разнообразных из топ10 чекпоинтов — было хуже. Это давало очень незначительный, но стабильный прирост.

Подходы каждого члена команды

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

nick

Conv freeze,
epoch

Optimizer

Strategy

Augs

TTA

albu

3

SGD

15 epoch LR decay,
Circle 13 epochs

D4,
Scale,
Offset,
Distortion,
Contrast,
Blur

D4

alno

3

SGD

LR decay

D4,
Scale,
Offset,
Distortion,
Contrast,
Blur,
Shear,
Channel multiplier

D4

n01z3

2

SGD

Drop LR, patient 10

D4,
Scale,
Distortion,
Contrast,
Blur

D4, 3 checkpoint

ternaus

-

Adam

Cyclic LR (1e-3: 1e-6)

D4,
Scale,
Channel add,
Contrast

D4,
random crop

nizhib

-

Adam

StepLR, 60 epochs, 20 per decay

D4,
RandomSizedCrop

D4,
4 corners,
center,
scale

kostia

1

Adam

D4,
Scale,
Distortion,
Contrast,
Blur

D4

romul

-

SGD

base_lr: 0.01 — 0.02
lr = base_lr * (0.33 ** (epoch / 30))
Epoch: 50

D4,Scale

D4, Center crop,
Corner crops

Стеккинг и хаки

И затем на out of fold (OOF) предиктах обучили модели второго уровня: Extra Trees, Linear Regression, Neural Network и просто усреднение моделей. Каждую модель с каждым набором параметров мы обучили на 10 фолдах.

Более подробно про стэккинг можно почитать тут и тут. И уже на OOF предиктах моделей второго уровня подобрали веса для смешивания.

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

Оптимизация F2 по Баесу

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

Надо перебрать все комбинации (т.е. Что это означает? Для какой комбинации оно лучше, да и даст оптимальный F2. для каждого лейбла 0 и 1), посчитать вероятность каждой комбинации, и домножить на F2 — получаем ожидаемое F2. 05 до 0. Вероятности считались просто перемножением вероятностей отдельных лейблов (если у лейбла 0, берем 1 — p), а чтобы не перебирать 2 в 17 вариантов, шатались только лейблы у которых вероятность от 0. По идее, было бы круто получать вероятность комбинации лейблов не просто перемножая индивидуальные вероятности (т.к. 5 — таких было 3-7 в строке, так что вариантов немного (сабмит делался за пару минут). лейблы не независимы), но это не зашло.

когда модели стали хорошими, подбор порогов после ансамбля перестал работать, а эта штука давала небольшой но стабильный прирост и на валидации, и на public/private. что это дало?

Послесловие

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

Да, вполне. Можно ли было обучить меньше моделей и получить такой же или лучший результат? Про решение можно посмотреть разбор и почитать пост. Наши соотечественники с 3го места Станислав stasg7 Семенов и Роман ZFTurbo Соловьев обошлись меньшим числом моделей первого уровня и компенсировали 250+моделями второго уровня.

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

И если подумали, что он просто по фану отправил пару сабмитов, то не угадали. Еще из интересного: широко известный в узких кругах Jeremy Howard, отец fastai финишировал 22м. Он участвовал в команде и отправил 111 посылок.

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

В качестве бонуса, я выступал в Mail.ru с материалом этого поста и вот еще презентация Владимира Игловикова с митапа в Долине.

Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»