Skip to content

Latest commit

 

History

History
80 lines (68 loc) · 14.7 KB

solution_comments.md

File metadata and controls

80 lines (68 loc) · 14.7 KB

Contains comments from authors about their solution after first investigation

1st Place Sergey Zlobin: Решение основано на модели Yolo v5 от ultralytics. https://github.com/ultralytics/yolov5 Внешние датасеты не использовались. Хотя, скорее всего, от них будет польза. Возможно, у меня, просто не было стимула поковырять внешние данные. 1) Так как люди на снимках очень маленькие, то я сразу решил делать детекцию окнами 1024x1024. Для обучения я разрезал каждую картинку на ~24 таких окон (по большей части непересекающихся – просто для ускорения обучения). Далее взял все (2950 штук) окна с боксами и некоторое количество безбоксовых окон (500 штук). Обучение производилось на 5 фолдах и разрешении 640. 2) Для инференса картинка разбивалась на несколько пересекающихся окон, и делалось предсказание с помощью модели из п.1. Слияние боксов пересекающихся окон делалось “ручным” способом аналогично NMS, только условие заменил на: площадь пересечения боксов более половины минимума площади из 2 боксов. при этом делалось еще одно предсказание на отраженной (Hor Flip) картинке. Ансамбль боксов делался по методу WBF: https://github.com/ZFTurbo/Weighted-Boxes-Fusion модель получила mAP 0.962 на лидерборде 3) После этого я добавить негативных примеров (вместо 500 стало 1366 штук). Причина - при визуальном просмотре не редкость False Positive. Также я увеличил разрешение обучения и инференса до 1024. Такая модель дала 0.968 на лидерборде. 4) После ансамбля моделей из пунктов 2 и 3 с весами 1:2 получил скор 0.975. Ivan Ага. Описание до меня не дошло, где-то потерялось по пути :man-walking: Теперь более понятно, что такое 2 и 3 🙂 А False руками добавлял?

Sergey Zlobin Когда я разрезал исходные на окна, получилось довольно много картинок без боксов. Можно было бы их добавить ВСЕ в обучение, но это сильно бы увеличило время обучения. Поэтому моя идея была взять только некоторые из пустых, на которых может быть что-то похожее на детектируемый объект. Для этого я обучил вначале модель номер 1 на 1 фолде БЕЗ пустых картинок вообще, и прогнал инференс на пустых изображениях. Отобрал те 500 из них, на которых нашлись самые уверенные боксы. Это nonempty.csv. Вторая версия nonempty_p2.csv - это то же самое, но это я прогнал Model 2 (уже обученную с 500 пустыми боксами). То, что лежит в csv это такая вероятность, вычисляемая по всем найденным боксам на картинке:

        is_empty = 1
        for label, score, location in test_locations[test_filename]:
            is_empty *= 1 - score
        non_empty_probs.append(1 - is_empty)
Я не знаю, насколько важно было выбирать, такие картинки. Может было бы достаточно докинуть 2000 любых случайных пустых картинок, например.
Насчет прода. Я не пытался оптимизировать скорость. Например, когда я разбиваю на окна я делаю инференс, то там по 1 окну передаются. 
Думаю быстрее засовывать массив сразу батчами.

2nd+3rd anahoret 10:06 AM

У меня там по сути три проекта и куча скриптов.
Если вкратце о решении:
немного модифицированный yolox, тренеруется на рандомных тайлах, которые режутся рандомно вокрух bbox'ов, с рандомными размерами
инференс тайлов yolox
отдельный классификатор с очень толстой effnet-b7 найденных bbox'ов + немного пространства вокруг
сшивка тайлов с отладочной визуализацией, постпроцессингом разрезанных боксов и учетом данных классификатора
Все тяжелое и медленное, "закатывать в прод" такое не советую :slightly_smiling_face:

я пробовал yolox-s/l/x, точно не помню разницу, но что-то около 5% разница была
бочки, ветки похожие на людей и тд не получалось полностью отстреливать, потому добавил еще классификатор
просто классификатор тоже сразу "не смог", пока не перешел на тяжелые архитектуры

Viva 8:28 PM Добрый вечер. Точно воспроизводить смысла нету, потому что в сабмишн файлах на тех картинках, которые без людей, проставлены единичные боксы по углам, ибо иначе файл не принимался)) Мы во многих вопросах кооперировались со Slava Dodatko, особенно по части подготовки данных. В команду мы объединиться не успели, но сделали это уже сейчас. Собственно, со времени сабмишна сам код уже был преображен и много где переписан, вообще говоря мы со Славой решили добить эту задачу до результата получше и кода поприятнее, и потом уже передать Вам. Поэтому пока дам описание, подробное насколько могу написать. Если будут вопросы - само собой обращайтесь. Основные идеи Вам уже должны быть известны: сперва нужно большую картинку правильно нарезать на куски, и тренировать сеть уже на этих маленьких кусках (тайлах). Нарезать нужно по-разному: для тренировки и для инференса соответственно. Сперва о трейне. Нарезать подряд (как делал человек на первом месте, если я правильно понял, смотрел бегло) - плохо, потому что бокс с человеком может попасть на два тайла одновременно (на границу двух тайлов), и тогда на каждый из тайлов попадет только часть бокса, а это потенциально ухудшает качество, потому что при детекции будет большее количество боксов, которые детектят только части тела. Это касается также и нарезки для инференса. Далее, просто нарезать тайлов с людьми и без - не очень хорошо, потому что тайлы будут одинаковые, и из огромной картинки в сеть попадет всего-ничего. Значит нужно рандомизировать нарезку, каждый раз делая рандомные сдвиги вокруг боксов, но так, что бы в итоге в тайл попадало целое количество боксов (не было обрезок людей). Также мы нарезаем так, что каждый бокс попадет в трейн сет какое-то количество раз, но каждый раз на другом тайле. Пустые тайлы просто берем в рандомных местах. Дальше различные общеизвестные аугментации. Для инференса просто нарезается подряд с установленным перехлестом, как показано на видео Славы. После прохода сети эти тайлы нужно сшить. Если сделать перехлест достаточно большим, то для каждого человека будет хотя бы один тайл, который захватывает бокс целиком. Значит, если сеть неплохо обучена, то у нас не должно быть ситуации, когда человек задетектился двумя непересекающимися боксами (один на тулувище, другой - на ноги). Но, даже если есть тайл, который захватывает человека целиком и в итоге дает хороший бокс, на других тайлах этот человек может быть обрезан. В итоге у нас будет маленький бокс (например ноги) внутри другого, который побольше (весь человек). Здесь достаточно просто выбрасывать те боксы, которые находятся внутри другого почти целиком, например на 95% - работает неплохо (все на инференсе только, само собой). IoU хуже, так как меньший (внутренний) бокс может быть любого размера. Также была обнаружена большая проблема в фолс позитивах: всякие бочки, цветы и тд и тп детектятся, как люди. Я полагаю, это проблема малой вариативности датасета и несоответствие тренировочного и тестового датасетов, модель начинает любую пестрость воспринимать, как человека, потому что в трейне этих пестростей маловато. В любой случае, эту проблему мы решаем отдельным классификатором, который мы сделали уже после того, как убежал дедлайн. По поводу детекторов - я обучал йоло5, Слава - йолоХ, модели были жирные, результаты примерно сравнимы. Описывать игрища с гиперпараметрами смысла нет, там ничего особенного не происходило. Боксов в тайлах почти всегда целое число (иногда так нарезать невозможно), так что никакой хитрой постобработки во время тренировки я не делал. Постпроцессинг на инференсе описан выше.

5th place (reproduced) Ivan Ковыряюсь сейчас в https://github.com/vazhanio/Lacmus_5place (собственно, оно самое простое с точки зрения потенциального заката в прод и нормально оформлено, чтобы воспроизвести). А именно - пробую заинферить с весами из гита, и отдельно затренить и потом заинферить. Во втором варианте метрики выходят хуже ощутимо |yolo5_5th_place_retrain | 1984,1984 | 0.9067 | 0.9466 | 0.6837 | 0.8732 | 0.9404 | | |yolo5_5th_place_git_weights | 1984,1984 | 0.9578 | 0.9833 | 0.8192 | 0.9474 | 0.9799 | | Что-то делаю не так?

Vazhanio А конфиг обучения совпадает( в части аугментаций?) Посмотрел по wandb ( там все параметры логируются) параметры сети для тренировки точ в точ как у меня в репозитории и как скинули вы.

Ivan 6:12 PM :thinking_alot: Ну может, конечно, батч размером 8 всё так испортил, вроде такое может случатся (народ пишет). Поиграюсь ещё с этим. https://medium.com/mini-distill/effect-of-batch-size-on-training-dynamics-21c14f7a716e

Ivan 4:08 PM Ага. Трюк был в том, что надо на 50 эпох тренировку запустить, а не на 10, как в ноутбуке написано, тогда более-менее всё сходится. Уменьшение батча сильно не спасает (правда с батчем 2 на 50 эпох я не пускал, я состарюсь раньше).

Vazhanio 4:10 PM Канеш 10 эпох мало, 10 эпох стояло для примера обучения на колабе. Канеш на нём очень долго обучается