Kaggle NFL — Player Contact Detection (Часть 1)
Введение
Недавно прошло соревнование по определению столкновения между парами игроков американской футбольной лиги NFL. В нем я принял участие со своими коллегами. Хоть мы и не успели реализовать свои идеи, мы изучили топ-решения и поняли, что были на верном пути.
В этой статье мы рассмотрим некоторые из решений, которые принесли денежное вознаграждение и золотые медали участвовавшим в соревновании командам.
Задача
Цель — определить наличие/отсутствие столкновения между двумя игроками в конкретный момент времени в конкретной игре.
В соревновании использовалась метрика корреляции Мэтьюса (MCC) для оценки качества классификации столкновений между игроками. MCC позволяет учитывать все четыре возможных исхода классификации: верно-положительный (TP), верно-отрицательный (TN), ложно-положительный (FP) и ложно-отрицательный (FN).
Данные соревнования
Поскольку данных много (их особенностей еще больше), я кратко опишу самое важное. А остальное можно посмотреть тут или во вкладках (toggles) ниже.
Видео данные [train/test] mp4
Каждая игра имеет три видео с трех разных ракурсов. Видео sideline и endzone синхронизированы по времени. Для видео All29 синхронизация не гарантируется (не видел его использование, хотя его предоставляли для возможности обзора всех игроков на поле).
Примеры фреймов из видео
[train/test]_video_metadata.csv
game_play
: Уникальная комбинация игрового ключа и идентификатора игры для игры. (Unique game key and play id combination for the play )
game_key
: ID code игры(game).
play_id
: ID code для игрового розыгрыша(play).
view
: откуда снимали Sideline
or Endzone
start_time
: timestamp начала видео.
end_time
: timestamp конца видео.
snap_time
: timestamp когда сама игра начинается. Во всех видео составляет 5 секунд (300 фреймов) на всех видео.
train_labels.csv
contact_id
: Комбинация столбцов game_play, player_ids и step.
game_play
: уникальный идентификатор для play и игры.
nfl_player_id_1
:Идентификатор игрока с меньшим номером в контактной паре. Если контакт с землей, то просто player_id
nfl_player_id_2
: Идентификатор игрока с наибольшим номером в контактной паре. Если контакт с землей, то буква «G».
step
: Число, представляющее каждый временной шаг для каждого воспроизведения, начиная с 0 в момент начала воспроизведения и увеличиваясь на 1 каждые 0,1 секунды.
datetime
: Временная метка контакта, 10 Гц
contact
: Был контакт или нет
Больше деталей по данным с видео
Все видео содержат частоту кадров 59.94 HZ
Всего около 149 для train игр
среднее время игры 11 секунд, где 5 секунд игроки ждут свистка чтобы начать игру
В test есть видео которые были в train.
Tracking данные
Каждый игрок носит датчик, который позволяет определять его местонахождение и ориентацию на поле во времени. Важная деталь — расстояние между игроками. С помощью этой фичи можно отсеять далекие друг от друга пары игроков, ведь столкновения между ними не может быть.
Также эти данные собираются с частотой 10 Гц каждые 0,1 секунды.
[train/test]_player_tracking.csv
game_play
: Уникальная комбинация игрового ключа и идентификатора игры для игры.
game_key
: ID code для игры.
play_id
: ID code для игрового розыгрыша.
nfl_player_id
: ID code игрока.
datetime
: timestamp 10 Гц.
step
: временной интервал внутри игры относительно начала игры.
position
: позиция игрока на поле.
team
: команда игрока home или away.
jersey_number
: Номер игрока(игровой)
x_position:
положение игрока вдоль длинной оси поля.
y_position
: положение игрока вдоль короткой оси поля.
speed
: скорость игрока в yards/second.1 ярд (yard) = 0.9144 метра (meter).
distance
: расстояние, пройденное от предыдущей временной точки, в ярдах.
orientation
: ориентация игрока на поле(deg).
direction
: угол движения игрока (deg).
acceleration
: (magnitiude) величина общего ускорения в ярдах/секунду^2.
sa
: ускорение ярдов/секунд^2 в направлении, в котором движется игрок.
Шлемы игроков (bboxes)
Эти данные были предоставлены с прошлого соревнования от NFL. Хоть это и предсказания модели, почти всегда шлемы были определены достаточно точно и это не было проблемой. Всего было 3 таких соревнования. Собственно, в предыдущем соревновании надо было задетектить шлема игроков.
[train/test]_baseline_helmets.csv
game_play
: уникальный идентификатор для play и игры.
game_key
: ID code для game.
play_id
: ID code для play.
view
: откуда снимали Sideline
or Endzone
video
: имя видео к которому относятся bboxes.
frame
: фрейм из видео к которому относятся bboxes.
nfl_player_id
: предсказанный id игрока(точность не гарантируется).
player_label
: комбинация номера майки игрока и его команды(home или visitor).
[left/width/top/height]
: предсказанный bbox.
В заключение скажем, что предоставленные данные не идеальны, но достаточно для хорошего результата. Вот EDA , в нем можно посмотреть некоторые закономерности в данных.
Данных для решения задачи было много: около 60GB и при разбитии на фреймы около 373k файлов. Поэтому участники часто сталкивались с OOM ошибкой, и для обучения и сабмита приходилось использовать различные хитрости. Чаще всего модель обучали от 1 до 10 эпох.
Решение, занявшее 5-е место
Решение состоит из двух этапов: части нейронной сети (NN) и части с градиентным бустингом (GBDT). В этом обзоре мы сделаем упор на первую часть.
В первую очередь было необходимо подготовить данные для входа в NN.
Одна картинка состояла из:
- двух grey фреймов +-1 по времени первым и вторым каналом;
- масок bbox’ов на третьем канале тензора.
В итоге имеем тензор [f-1, f+1, f] (см. рис 4), где интересующая область вокруг целевых игроков была получена следующим образом:
- для пар игрок-игрок берется наибольшая сторона среднего bbox по кадрам игроков;
- затем она умножается на 3 для увеличения области и попадания туда не только шлема, но и игроков;
- далее она ресайзится до 128×128.
Выглядит это так: crop size = max(average bbox width, average bbox height) * 3.
Для пар игрок-земля размер после обрезки равен максимальному значению ширины bbox и высоты bbox, умноженному на 3 и также ресайз до 128×128: crop size = max(bbox width, bbox height) * 3.
Во время обучения используются последовательности кадров, содержащие хотя бы один кадр с расстоянием между игроками не менее 2х ярдов. Но в последовательности данные могут содержать также кадры с расстоянием более 2х ярдов.
В итоге входные данные представляются в виде двух тензоров:
- с размерами B x N x 10 для tracking data;
- с размерами (B x N) x 3 x 128 x 128 для фреймов, где B — batch size, N — последовательность кадров (например, 16, 32, 48, 64).
Во время обучения и инференса вырезаются последовательные кадры (N) с разным шагом. Для обучения не используются дублирующие кадры (stride == N), то есть без overlap. Для инференса же применяются дублирующие кадры (stride < N), и полученные значения дублирующих кадров усредняются.
Архитектура:
- Объединенные последовательности фреймов с sideLine и endzone подаются в CNN backbone с TSM(улучшает способность сети моделировать временную информацию в видео фреймах + оригинал статьи);
- Конкатенируются фичи с tracking data;
- BiLSTM слои + FC cлой.
Слой BiLSTM (за которым следует слой FC) обрабатывает последовательность кадров и создает последовательность скрытых состояний, которые отражают временные зависимости между кадрами. Затем слой FC принимает эти скрытые состояния в качестве входных данных и производит один выходной сигнал, представляющий всю последовательность кадров.
Проводились эксперименты c ResNet18, ResNet34, ResNet50, ResNeXt50, EfficientNet B0 и EfficientNet B1 с различной длиной последовательностей: 16, 32, 48 и 64.
Этап 2 (XGB, LGBM)
Этап с XGboost опустим, кратко оставим несколько заметок:
- Было две модели: XGB и LGBM, обученные на одних и тех же данных.
- В модели подавались фичи: самое важное — outputs с предыдущей модели(NN), сырые табличные данные, трекинг шлемов, некоторые комбинации фичей.
Тут можно потыкать в kaggle ноутбук для обучения XGB на данных этого соревнования.
Ансамбли
Частый прием в соревнованиях — использование предсказаний нескольких моделей. Это соревнование не стало исключением.
На табличке ниже можно увидеть комбинации моделей различных архитектур, последовательности кадров и результат на кросс-валидации (CV).
Для ансамблирования участники использовали метод Forward Selection OOF.
Forward Selection OOF (Out-of-Fold) — метод ансамбля, который включает в себя обучение нескольких моделей на разных подмножествах данных, а затем объединение прогнозов каждой модели Out-of-Fold для создания окончательного прогноза. Познакомиться с Forward Selection OOF Ensemble можно тут.
Советы от команды, занявшей пятое место, для избегания проблем с OOM и timeout:
- lru_cache увеличит скорости чтения изображений;
- PyTurboJPEG загрузит изображения быстрее, чем OpenCV;
- Polars поможет ускорить время сабмита. Polars — аналог Pandas, написанный на rust. Во многих базовых сценариях работает значительно быстрее.
Решение, занявшее 1-е место
Код: https://www.kaggle.com/competitions/nfl-player-contact-detection/discussion/392583 (training, inference)
У решения первого места довольно интересный подход. Оно состоит из:
- препроцессинг: небольшая модель XGB для исключения простых негативных семплов из данных;
- CNN для классификации контакта между игроками и CNN для классификации контакта между игроком и землей (казалось бы, сетка и так должна обобщиться на столкновение игрока с чем-либо, но были обучены две модели);
- еще один XGB в качестве постпроцессинга выходов сети.
3D CNN for Video Classification
- Для подготовки данных для модели игрок-игрок автор извлек 18 соседних фреймов из видео: {frame[-44], -37, -30, -24, -18, -13, -8, -4, -2, 0, 2, 4, 8, 13, 18, 24, 30, frame[37]}. Кадр[-44] представляет 44 кадра, предшествующих расчетному кадру текущей выборки. Берутся кадры до и после столкновения. Чем ближе к target фрейму, тем чаще мы получаем фреймы. Таким образом, модель видит больше кадров, близких к target фрейму.Можно заметить отсутствие 44 фрейма — он был удален, так как просто не помещался в память.Далее автор отрисовал на головах игроков большие черные и белые точки, как бы акцентируя внимание модели на нужных игроках. Рисовал он их не в дополнительном канале, а сразу на изображении и сделал это для того, чтобы оставить 3х канальный вход для предтренированной модели. Область с нужными игроками вырезалась в 10 раз больше среднего размера ббоксов в последовательности.А затем следует еще более странная, но одновременно крутая идея, улучшившая скор с 0.73 до 0.76 на CV.Заключается она в следующем: отрисовываются трекинг данные для каждого игрока на черном фоне между изображениями игроков. Сталкивающиеся игроки отмечены более яркими точками с большим радиусом. Два разных цвета — две разные команды.Ниже показан input в сеть. И нет, это не просто красивая визуализация. Это и есть данные на вход сетке.
- Подготовка данных для модели игрок-земля такая же, только фреймов 23 и последовательность длиннее: [-54, -48, -42, -36, -30, -24, -18, -13, -8, -4, -2, 0, 2, 4, 8, 13, 18, 24, 30, 36, 42, 48, 54].Также симуляции трекинг данных на изображении нет, так как этот подход не улучшил скор. Именно поэтому последовательность длиннее, просто теперь получается вместить больше данных на GPU.
Модель
Была выбрана resnet50-irCSN, поскольку это задача скорее action recognition , чем классическая 3D классификация. Лучший скор на бенчмарках (Kinetics-400 dataset) показывала именно эта модель.
Для изображений с sideline и endzone использовались аугментации и рандомный swap (sideline, tracking, endzone → endzone, tracking, sideline). Что касается tracking данных — применялись только горизонтальные и вертикальные флипы.
При обучении использовался linear scheduler для learning rate. Модель обучалась одну эпоху.
XGBoost Postprocessing
Автор применил ensemble probability из соседних временных шагов для повышения производительности модели. Ensemble probability — это вероятность, полученная путем объединения (ансамблирования) нескольких моделей или прогнозов в единую модель или прогноз.
Player-Player postprocessing
В данном случае постпроцессинг — обучение еще одной модели, но на выходах нейронки и xgboost предпроцессинга с определенной вероятностью. Ensemble probability для этого считался так: prob = 0.2pre_xgb_prob + 0.8cnn_prob.
Далее вероятности из 20ти соседних фреймов берутся как фичи для XGBoost модели: {prob(-10), prob(-9), …, prob(0), prob(1), …, prob(9)}, где prob(-10), что представляет собой вероятность появления одной и той же пары игроков на предыдущих 10 шагах.
Этот подход улучшил результат примерно на 0.005.
Player-Ground postprocessing
Для этой модели ensemble probability был таким:
prob = 0.15pre_xgb_prob + 0.85cnn_prob.
Для модели игрок-земля использовался примерно тот же подход, только ensemble probability был из 30-ти соседних временных шагов: {prob(-15), prob(-14), …, prob(0), prob(1), …, prob(14)}.
Выход с предпроцессинга XGBoost (pre_xgb_prob) и нейронной сети cnn_prob из 20-ти временных шагов. Этот подход улучшил предсказания игрок-земля на кросс-валидации (CV) и дал прирост к результату примерно на 0.04.
Выводы
Участие в соревновании требует много времени и усилий, но это однозначно бесценный опыт.
Всегда интересно посмотреть на решения других участников и изучить подходы к решению задачи под иным углом.
А теперь подведем итоги! В этой статье мы узнали:
- как можно подготовить данные для обучения в задаче видеоклассификации;
- какие существуют архитектуры и подходы для решения задачи с трекинг данными и последовательностью изображений;
- что такое Метрика корреляции Мэтьюса и Forward Selection OOF Ensemble.
Интересный факт: хост соревнования Rob Mulla — kaggle grandmaster и со своим YouTube каналом по DS.
Ссылки
- Соревнование:
https://www.kaggle.com/competitions/nfl-player-contact-detection/overview
- Первое место:
https://www.kaggle.com/competitions/nfl-player-contact-detection/discussion/391635
- Код:
https://www.kaggle.com/competitions/nfl-player-contact-detection/discussion/392583 (training, inference)
- Пятое место:
https://www.kaggle.com/competitions/nfl-player-contact-detection/discussion/392290
- Разбор соревнования прошлого года: