Привет, Хабр!Это последняя из трех статей, в которых я (автор канала Зайцем по ХаХатонам) рассказываю о задачах Всеросийского чемпионата Цифрового Прорыва, объясняю базовые решения (baseline) и даю советы, которые помогут подняться выше по рейтингу. В данной статье будет рассмотрен кейс от МФТИ по привязке аэроснимков к местности.  Данная статья является особенной, так как она содержит исправленный бейзлайн, который изначально не работал. Сейчас же приведенное ниже решение дает результат на 9 место в лидерборде! Спойлер: в конце статьи есть советы для улучшения базового решения. Думаю, все и так знают, что такое Цифровой Прорыв. Однако, напомню, что в этом году основной тематикой стал искусственный интеллект. И сезон этого года в самом разгаре! Хоть часть мероприятий уже прошла, впереди участников ждет ещё 19 региональных чемпионатов, 5 окружных хакатонов и 3 всероссийских чемпионата. Советую присоединиться ко мне и другим участникам, чтобы не упустить возможность выиграть денежные призы и крутые путешествия, а также набраться опыта на самых разных задачах. В современном мире огромное количество задач решается с помощью спутниковых фотографий и аэрофотоснимков. Зачастую от скорости и качества интерпретации этих данных зависит то, как быстро выявляются пожары, наводнения и другие чрезвычайные ситуации. Технологии машинного зрения только начинают применяться в решении такого рода задач, однако потребность в их использовании постоянно растет. Решение данной задачи позволит оперативно привязывать изображения к географическим координатам, что в дальнейшем может ускорить геодезические работы, поможет оперативно искать пропавших людей, контролировать вырубку лесов. И это только краткий список того, где требуется привязка аэрофотоснимков к местности.  Участникам чемпионата будет предложено найти местоположение и ориентацию снимка на крайне большом изображении по высоте и ширине с географической привязкой к местности. Цель задачи — необходимо найти местоположение и ориентацию снимка на подложке. Для лучшего понимания контекста задачи участникам стоит ознакомиться со следующими терминами: Подложка — крайне большое изображение по высоте и ширине с географической привязкой к местности, т.е. координаты каждого пикселя известны или их можно вычислить. Как правило, на изображении размещена большая площадь земли (квадратные километры и более) Аэрофотоснимок — изображение со спутника или беспилотного летательного аппарата, направление камеры при фотографировании смотрело вертикально вниз. Имеет существенно меньшее разрешение в сравнении с подложкой. По сути фотография, сделанная на обычный фотоаппарат. Главная особенность в том, что аэрофотоснимок сделан в отличное от подложки время, время года, или даже в совершенно другой год или на разной высоте. Перекрытие — положение изображений, при котором одна и та же площадь местности видна на двух и более аэрофотоснимках. Взаимное ориентирование разновременных снимков разного разрешения подразумевает под собой сопоставление снимков и получение их географической привязки за счет ручного сопоставления оператором с картой. В качестве данных выступают аэрофотоснимки фиксированного размера: train/img — папка, содержащая 800 фотографий тренировочного набора; train/json — папка с данными в формате json со следующими значениями left top — координата левого верхнего угла фотографии относительно подложки; right top — координата правого верхнего угла; left bottom — координата левого нижнего угла; right bottom — координата правого нижнего угла; angle — угол поворота. test/ — папка, содержащая 400 фотографий для предсказания; original.tiff — подложка с расширением 10496 x 10496: Снимки сделаны в разные временные промежутки и при различных погодных условиях. Например, часть поверхности может быть скрыта за облаками. Стоит также заметить, что фотографий для обучения мало, расширить набор для обучения можно за счет самостоятельной нарезки фотографий с подложки. Для такой специфичной задачи разработана своя метрика, которая определяет разницу между предсказанным центром, углом поворота фотографии и их оригинальными значениями. В базовом решении предложено решить задачу, как регрессии. Таргетными значениями данном случае выступают 4 координаты и угол поворота изображения относительно оригинального. Схема решения будет следующей: Установка и импорт всех библиотек Предобработка данных Создание загрузчиков (DataLoader) для подачи данных в модель  Вспомогательные функции для обучения модели Создание и обучение модели Тестирование полученного решения Начнем с импорта всех необходимых библиотек. В качестве фреймворка для обучения нейросети выбран torch. На данном этапе данные, хранящиеся в json файлах, преобразовываются в pandas-датафрейм. Для эффективного обучения нейросети данные нужно подавать в виде батчей. Батч хранит в себе несколько экземпляров данных. К примеру, в базовом решении параметр batch_size равен 16, то есть каждый батч, подаваемый в модель содержит в себе 16 экземпляра данных. Ниже представлен один из вариантов реализации подобного загрузчика данных. Сначала напишем класс, в котором данные непосредственно загружаются и приводятся в нужный формат. Далее зададим аугментации, которые будут использоваться при обучении модели. Посмотрим на количество данных и разделим их на тренировочную и валидационную части. Каждую из выборок подадим в ранее созданный класс. После чего обернем это в другой класс, уже существующий в библиотеке torch - DataLoader. Для обучения модели нам понадобятся функции расчета метрики, построения графика обучения и непосредственно обучения. Ниже приведена функция рассчета метрики. Важное замечание - метрика для лидерборда рассчитывается исправленной метрикой, что именно исправлено можно прочитать в разделе "Метрика". Функция визуализации графиков обучения. Процесс обучения модели написан вручную без готовых функций (таких как TrainEpoch). Это дает более четкий контроль процесса обучения и возможность его кастомизировать.  В качестве модели используем resnet50, предобученный на датасете imagenet с выходным слоем размером 5, так как мы хотим предсказывать 5 параметров. Функцией потерь же будет MSELoss, используемый в задачах регрессии. Запустим обучение и понаблюдаем за изменением лоссов. Посчитаем метрику на датасете для валидации. Получаем метрику 0.98. Однако, не стоит забывать о том, что обучались мы на небольшом наборе данных и итоговая метрика на лидерборде может отличаться. Для начала нужно написать класс для загрузки тестовых данных, аналогичный тому, что написан для тренировочных. Далее собираем названия всех тестовых файлов и объявляем даталоадер с размером батча 16, так как тестовых картинок 400, а 400%16==0. Собираем предсказания в список. Записываем полученные предсказания в нужный для сабмита формат. После чего можно сжать все .json-файлы в архив и загрузить его на платформу. Пример того, что содержит в себе каждый .json-файл. Первым вариантом улучшения решения является увеличения количества эпох и дообучение модели. Также можно попробовать изменить архитектуру модели на более сложную. Попробовать создать ансамбль моделей и применить метод TTA (Test Time Augmentation). Поменять размер входных изображений и изучить возможность улучшить используемые аугментации. Расширить датасет из предоставленной подложки или из сторонних ресурсов. Поразмышлять над иными подходами к решению задачи - не регрессии. Кейс весьма интересен за счет нестандартной постановки задачи. Есть простор для экспериментов над подходами. А если вам удастся подобрать эффективный подход, то еще и сможете получить денежный приз до 250 тысяч рублей! Все интересующие вас вопросе вы можете задать в канале Зайцем по ХаХатонам. Всем удачи на чемпионатах и хакатонах!  ML Team Lead