Представьте себе задачу: найти опухоль на КТ‑снимке любого органа — печени, почки, поджелудочной, легкого, лимфоузла. Снимок может прийти из любой больницы в мире. На всё про всё — 60 секунд и 4 ГБ видеопамяти. А еще половина снимков в реальной жизни — от здоровых людей, и на них модель должна сказать: «ничего нет».
Именно такие условия поставили перед участниками организаторы первой задачи на соревновании FLARE 2026, итоги которого были недавно подведены в рамках конференции MICCAI в Страсбурге. Наша модель под названием PANTHER оказалась лучшей по скорости среди всех конкурентов.
Далее рассказываем, как проект с Летней школы AIRI превратился в участие в престижном международном соревновании, почему половина датасета оказалась лучше целого, зачем мы снова позвали на работу «вышибалу» и как впихнуть ансамбль из пяти нейросетей в 11 секунд на снимок.
Как все началось: Летняя школа и «Аргус»
Каждое лето AIRI собирает студентов и аспирантов на Летнюю школу. На лекциях и практических занятиях можно потрогать руками VLA‑модели или прокачать харнесс своему агенту, а для глубокого погружения в науку участникам предлагают на выбор несколько десятков исследовательских проектов — от анализа эмоций у LLM до RL в компьютерных играх (подробнее о том, как прошла школа 2026 года, можно почитать здесь). Одним из проектов был «Аргус: поиск патологий на КТ», названный в честь стоглазого великана из греческих мифов, от которого ничто не могло ускользнуть. Его и выбрал Василий Баранов, студент на тот момент 4 курса ФПМИ МФТИ.
Изначальный замысел был понятный и амбициозный: научить модель находить патологии на компьютерной томографии так, чтобы она ничего не пропускала и при этом не «видела» болезнь там, где её нет. Это, кстати, прямое продолжение нашей прошлой истории — «Ты не пройдешь!», где мы учили нейросеть искать патологии на КТ грудной клетки, показывая ей только норму.
По ходу работы стало ясно, что идеи получаются неплохие: аккуратная работа с данными, ансамбль, который умеет промолчать, и статистический фильтр, обученный на здоровых снимках без единой метки опухоли. Возник логичный вопрос: а как это будет выглядеть на фоне сильных команд со всего мира? Ну, а мы что? Мы пошли — на FLARE 2026, соревноваться за Task 1.
Задача: найти рак за минуту на 4 гигабайтах
FLARE (Fast, Low‑resource, Accurate, Robust and Effectual medical image analysis) — серия соревнований, которая проводится с 2021 года и каждый год становится жёстче: от сегментации органов к обучению на неразмеченных данных и, наконец, к pan‑cancer — сегментации опухолей любой локализации.
Task 1 в 2026 году выглядела так:
Обучающая выборка: 17 575 размеченных КТ из более чем 50 источников (DeepLesion, KiTS, LiTS, MSD, autoPET, TotalSegmentator, LIDC и многие другие), как минимум шесть типов рака. Разметка частичная: в одном датасете размечены только опухоли печени, в другом — только почки, и что там происходит в остальных органах, никто не знает.
Неразмеченные данные: еще около 122 ГБ КТ, плюс 172 снимка здоровых пациентов — специально для оценки ложных срабатываний.
Валидация: 50 публичных КТ с разметкой, 100 скрытых (метрики через Codabench), а в финале — 500 КТ из центров, которых модель никогда не видела.
Ограничения инференса: 60 секунд на снимок, 4 ГБ GPU, 28 ГБ RAM, без интернета и без внешних предобученных весов.
И главное: половина итогового рейтинга — это скорость и экономичность. Учитывается, сколько секунд модель тратит на один снимок и сколько видеопамяти она при этом занимает — причем не только в пике, а на протяжении всей работы: грубо говоря, «мегабайты, умноженные на секунды». Модель, которая держит 3 ГБ десять секунд, получает худшую оценку, чем модель, которая держит 4 ГБ пять секунд.
Вторая половина — точность, и её оценивают двумя способами. Dice (DSC) показывает, насколько предсказанная маска опухоли совпадает с разметкой врача по объему: 1 — полное совпадение, 0 — ни одного общего вокселя. Normalized Surface Dice (NSD) смотрит на границу: какая доля поверхности опухоли у модели и у врача совпадает с точностью до 2 мм. Первая метрика отвечает на вопрос «нашли ли опухоль целиком», вторая — «насколько аккуратно обвели». А если снимок обрабатывается дольше 60 секунд, ему ставят DSC = 0. То есть медленная модель здесь не просто проигрывает в скорости — она проигрывает вообще всё.
Наша идея: PANTHER
Свой пайплайн мы назвали PANTHER — PAN‑cancer segmentation with Two‑tier Healthy‑scan Ensemble Rejection. Пантера — зверь быстрый и осторожный, нам понравилось. Под аббревиатурой спрятаны три гипотезы:
главный рычаг качества — не архитектура и не размер датасета, а его состав;
ансамбль сам по себе умеет отказываться от ответа на здоровых снимках, если его об этом правильно попросить;
остаточные ложные срабатывания можно отсечь по форме маски, выучив, как выглядит «мусор» на здоровых КТ, — без единой метки опухоли.

Меньше — значит лучше: как половина датасета обыграла целый
Первым делом мы посмотрели, из чего состоит обучающая выборка. Картина была удручающей: КТ всего тела и КТ грудной клетки — примерно по 5700 снимков каждого типа, а снимков с раком пищевода, раком толстой кишки, раком эндометрия (слизистой тела матки) и опухолями надпочечников — всего 154, 126, 79 и 52. Если учить на всем подряд, модель станет экспертом по датасетам DeepLesion и LUNA и будет смутно догадываться, что где‑то бывают надпочечники.
Поэтому мы сделали самое простое, что можно было сделать: ограничили число снимков из каждого источника. Крупные источники обрезали, редкие взяли целиком. Получился Dataset500 — 8762 КТ из 28 датасетов в 11 анатомических группах.
Результат оказался сильным. С теми же гиперпараметрами модель на половине данных дала +0.060 DSC по сравнению с полным набором из 17 575 снимков. Для сравнения, замена plain U‑Net на residual‑энкодер ResEnc(M) — втрое больше параметров! — принесла +0.002, что меньше разброса между фолдами. Эффект состава выборки оказался на порядок больше эффекта архитектуры.
Охват важнее разрешения. Медианный спейсинг выборки — 2.5×0.78×0.78 мм, и автоконфигурация nnU‑Net предлагает оставить 0.78 мм в плоскости среза. Мы вручную загрубили сетку до 2.0×1.5×1.5 мм. Патч в 96×160×160 вокселей при этом покрывает 192×240×240 мм тела — вдвое больше в плоскости среза. Большие опухоли перестают «не влезать» в патч. Обратный эксперимент с изотропными 1.25 мм сжал охват патча до 120×200×200 мм и стоил нам −0.078 DSC.
Дьявол в деталях: Все снимки в соревновании приходят в формате NIfTI. Внутри такого файла лежат две вещи: сам трехмерный массив вокселей («кубиков», из которых состоит объем, со значениями плотности ткани) и короткий заголовок с геометрией — где этот массив находится в теле пациента, как он повернут и какого размера каждый воксель в миллиметрах. Без заголовка массив — просто куча чисел: непонятно, где голова, а где ноги, и сколько сантиметров в одной опухоли.
Главная часть этой геометрии — матрица , столбцы которой задают направления осей снимка, а их длины — размер вокселя (спейсинг). Направления осей обязаны быть взаимно перпендикулярны. В 13 из 8762 файлов это нарушалось на величину порядка
— банальная ошибка округления при записи. SimpleITK к таким вещам беспощаден и файл просто не читает.
Чинить пришлось аккуратно, чтобы не испортить спейсинг. Раскладываем на направления и масштабы:
где — спейсинг, а
— матрица направлений с единичными, но чуть‑чуть не ортогональными столбцами. Ближайшую к
ортогональную матрицу (по норме Фробениуса; это классическая ортогональная задача Прокруста) дает сингулярное разложение:
Спейсинг и начало координат остаются прежними, интенсивности вокселей мы не трогаем, а сдвиг геометрии — сотые доли миллиметра, гораздо меньше вокселя. Та же процедура стоит и в инференсе: в финальном тесте снимки придут из незнакомых больниц, и падение на одном файле в лучшем случае означает ноль на этом снимке.
Пять голов лучше одной: ансамбль, который умеет промолчать
Теперь о здоровых пациентах. Ложная «опухоль» на снимке здорового человека — это не просто плохая метрика, это реальный клинический риск: лишние обследования, нервы, деньги. Классический путь — обучить отдельный классификатор «норма/патология», но для этого нужна отдельная размеченная когорта. Второй путь — выкидывать маски меньше порогового объема. Мы попробовали, и он монотонно ухудшает DSC: маленькие настоящие опухоли улетают вместе с мусором.
Оказалось, что нужный механизм у нас уже есть — ансамбль. Пусть — вероятность класса «опухоль» от
‑го фолда. Усредняем и бинаризуем:
Чтобы воксель попал в маску, фолды должны в среднем проголосовать «да». Если один фолд увидел призрака, а четыре — нет, средняя вероятность падает ниже порога, и маска получается пустой. На 172 здоровых КТ одиночная модель нашла «опухоль» на всех 172 (да, на всех), а ансамбль промолчал на 52. Вместе с этим ансамбль дал +0.028 DSC на больных. Бесплатный сыр, который не в мышеловке.
Вышибала, вернись! Фильтр Махаланобиса по форме маски
Ансамбль промолчал на 52 здоровых снимках из 172, но на остальных 120 он все‑таки что‑то нашел. 70% ложных срабатываний — все еще много. Мы посмотрели на этот «мусор» глазами и заметили, что у него есть характерный почерк:
• это обычно несколько мелких кусочков, разбросанных по снимку;
• ни один кусочек не доминирует — самый крупный занимает маленькую долю общего объема;
• кусочки «рыхлые»: поверхности много, а объема мало.
Настоящая опухоль чаще выглядит иначе: один‑два плотных компактных очага.
Здесь снова пригодилась идея из нашей прошлой статьи про модель‑«вышибалу»: учиться на норме. Только теперь «нормой» были не снимки, а ошибки модели на здоровых людях. Для каждой предсказанной маски мы считаем пять простых чисел:
1. общий объем маски;
2. число отдельных кусочков (крупнее 3×3×3 вокселя);
3. объем самого крупного кусочка;
4. какую долю общего объема он занимает;
5. отношение площади поверхности к объему.
Эти пять чисел мы посчитали для всех 120 ложных масок на здоровых снимках и получили «портрет» типичной ошибки: средние значения и то, как признаки связаны между собой. Для новой маски остается понять, насколько она похожа на этот портрет. Для этого есть классический инструмент — расстояние Махаланобиса:
где — пять признаков новой маски (в логарифмической шкале, чтобы большие объемы не забивали всё остальное), а
и
— среднее и ковариация, посчитанные по ошибкам на здоровых. Интуитивно это обычное расстояние до «центра» облака ошибок, только с поправкой на то, что признаки коррелируют: большой объем и много кусочков часто идут вместе, и учитывать их дважды не нужно.
Дальше все просто: если маска близко к портрету ошибки (), значит, это скорее всего мусор, и мы ее стираем. Вышибала снова на посту: «Ты не пройдёшь!»
# Фильтр по форме маски (упрощённо) z = np.log1p(shape_features(mask, spacing)) # 5 признаков d2 = (z - mu) @ Sigma_inv @ (z - mu) # расстояние до "портрета ошибки" if d2 <= 7.0: mask[:] = 0 # похоже на мусор - стираем
Порог 7.0 мы подобрали так, чтобы лучше всего разделить 172 здоровых снимка и 50 снимков с опухолями из публичной валидации. Чем порог выше, тем строже вышибала: он выгоняет больше мусора, но начинает задевать и настоящие опухоли.
Итог: ложные срабатывания на здоровых падают с 70% до 8%, а точность на снимках с опухолями почти не меняется — средний DSC на публичной валидации теряет всего 0.004. На скрытой валидации фильтр вообще не тронул ни одной маски. Вся эта красота стоит пять чисел и одно маленькое умножение матриц, около секунды на CPU. Ни одной дополнительной нейросети и ни одной метки опухоли.
Как впихнуть пять нейросетей в 60 секунд
А теперь самая инженерная часть, ради которой статья и называется так, как называется. Сначала — как вообще работает инференс.
КТ‑снимок целиком в видеопамять не помещается, поэтому сеть смотрит на него по частям: «окно» размером с патч скользит по объему, сеть обрабатывает каждый кусок, а результаты сшиваются. Ансамбль из пяти фолдов — это пять таких проходов по одному снимку. Чем больше срезов в снимке, тем больше окон и тем дольше всё это идет. Вот что мы сделали, чтобы уложиться в лимиты:
Отказались от фоновых процессов. По умолчанию nnU‑Net запускает вспомогательные процессы, которые готовят данные параллельно и передают их через общую память. В Docker этой памяти по умолчанию всего 64 МБ, и процессы падают с ошибкой Background workers died. Мы перенесли всю работу в один процесс. Неожиданный бонус — стало еще и быстрее: на одном и том же снимке 6.7 с вместо 12 с.
Увеличили шаг окна. По умолчанию соседние окна перекрываются наполовину. Мы уменьшили перекрытие до 30% — окон на снимок стало примерно на 28% меньше, а качество не изменилось.
Отключили TTA (test‑time augmentation). Это прием, когда снимок дополнительно прогоняют через сеть в зеркально отраженных вариантах и усредняют ответы. Отражения по трем осям дают 8 вариантов — то есть в 8 раз больше проходов сети. Усреднение у нас и так есть — по пяти фолдам.
Ускорили изменение разрешения. Перед подачей в сеть снимок нужно привести к сетке 2.0×1.5×1.5 мм. Классический способ (сплайн‑интерполяция на CPU) на снимке всего тела занимал 38 с — больше половины лимита. Реализация на PyTorch из того же nnU‑Net делает это за 0.3 с. На ней же готовились и обучающие данные, так что модель видит ровно то, к чему привыкла.
Держим на GPU только одну сеть. Веса остальных четырех фолдов ждут своей очереди в оперативной памяти. В видеопамяти в каждый момент — одна сеть и один кусок снимка. Поэтому расход видеопамяти не зависит от размера снимка.
Последний пункт хорошо виден в Табл. 1: чем больше срезов, тем дольше обработка, а пиковая видеопамять почти не меняется.
Табл. 1: Скорость и память финального Docker‑образа на RTX 3090 для снимков разного размера. Последний столбец — «мегабайты, умноженные на секунды», по которым считается рейтинг.
Снимок |
Срезов |
Время, с |
Пик GPU, МБ |
GPU |
0001 |
55 |
7.6 |
2268 |
11,634 |
0051 |
100 |
11.3 |
2378 |
21,340 |
0019 |
215 |
12.8 |
2318 |
17,638 |
0099 |
334 |
18.4 |
2374 |
21,704 |
0063 |
448 |
23.3 |
2398 |
30,772 |
0029 |
554 |
29.3 |
2464 |
34,014 |
Все 50 снимков публичной валидации мы прогнали ровно так, как это делают организаторы (docker run --gpus device=0 -m 28G , без увеличения общей памяти), и ни один не упал.
Результат:
время на снимок: в среднем 11.1 с, медиана 9.2 с, максимум 29.3 с — больше чем двукратный запас до 60 с;
видеопамять: пик 2614 МБ при лимите 4 ГБ;
оперативная память: пик 6 ГБ при лимите 28 ГБ
И все это — полный ансамбль из пяти 3D U‑Net по 31 млн параметров каждый.
Что не сработало (и это тоже результат)
Хорошая статья на Хабре без раздела про грабли — как КТ без контраста. Вот идеи, которые выглядели разумно, но в финальное решение не попали.
Выкидывать маленькие маски. Самый очевидный способ бороться с ложными находками на здоровых: если найденное «что‑то» меньше заданного объема, считаем, что ничего нет. Ложных находок действительно становится меньше — со 120 до 52 при самом строгом пороге. Но вместе с мусором улетают и настоящие маленькие опухоли, и точность на больных падает на 3.5–6 пунктов DSC. Фильтр по форме из предыдущего раздела справляется с той же задачей гораздо лучше.
Выкидывать неуверенные кусочки. Идея: каждый найденный кусочек маски проверять на уверенность модели и удалять те, где средняя вероятность «опухоли» не выше 0.65. На публичной валидации это дало +0.010 DSC. Но на скрытой — ничего (75.37 против 75.38): там только снимки с опухолями, и на них ансамбль и так уверен. Зато для этой проверки приходится сохранять полную карту вероятностей в исходном разрешении, и на больших снимках время вырастает больше чем вдвое: 69.6 с вместо 29.3 с. Это уже за 60-секундной отсечкой, то есть ноль за снимок. Выключили.
Особая метка для неразмеченных органов. Разметка в данных частичная: в датасете про почки отмечены только опухоли почек, и если на том же снимке есть опухоль печени, она числится «фоном». Способ с этим бороться — помечать такие области как «неизвестно», чтобы сеть не училась на них ничему. В предварительных экспериментах прироста это не дало. Похоже, правильно подобранный состав выборки решает эту проблему лучше, чем хитрая обработка разметки.
Оставлять только самый крупный кусочек. Стандартный шаг постобработки в nnU‑Net: всё, кроме крупнейшего фрагмента маски, удаляется как шум. Для органов это хорошо — печень у человека одна. А опухолей бывает несколько: например, на одном из снимков валидации эталонная разметка состоит из восьми отдельных участков. Удаление кусочков по размеру только снижало DSC.
Неразмеченные данные. Еще 122 ГБ снимков без разметки мы сознательно не трогали. Обычный путь — разметить их своей же моделью и доучиться (псевдоразметка). Но среди этих снимков заведомо есть опухолевые, и те опухоли, которые модель пропустит, попадут в обучение как «здесь ничего нет». Так мы научили бы модель пропускать опухоли ещё увереннее. Чтобы отделить больных от здоровых, нужна вторая, независимая модель, а внешние предобученные веса правилами запрещены.
Где модель ошибается
Метрики — это хорошо, но врачу важнее понимать, как модель ошибается. Лучше всего PANTHER справляется с двумя типами опухолей. Первый — компактные очаги в печени и почках с четкой границей, которые на снимке заметно светлее или темнее окружающей ткани. Второй — крупные опухоли, если они целиком помещаются в патч. Хуже всего — с мелкими очагами: рядом с ними модель иногда «прихватывает» здоровую ткань органа, а самые маленькие находки по форме бывают неотличимы от шума, который фильтр отсекает на здоровых снимках. Четыре примера на рисунке ниже.

0001, DSC 0.927. Небольшой компактный очаг (7.7 мл) с четкой границей — идеальный случай для модели.
0057, DSC 0.950. Крупная опухоль из нескольких очагов (в разметке восемь отдельных участков, около 2 литров). Модель нашла их почти точно.
0011, DSC 0.026. Пять маленьких очагов общим объёмом всего 5.4 мл. Модель покрыла около трети их объема, но заодно выделила крупную область около 120 мл там, где разметки нет. При таком соотношении объемов одна лишняя находка обрушивает Dice почти до нуля.
0029, DSC 0. Маленькая размытая находка без четкой формы. Ансамбль её нашел, но по форме она оказалась похожа на типичный «мусор» со здоровых снимков, и фильтр её стер.
Последний пример — цена фильтра формы: группа мелких метастазов тоже может показаться ему мусором. Сейчас фильтр работает по принципу «всё или ничего»; мягкий вариант, который не стирает маску целиком, а лишь понижает к ней доверие, мы пока не проверяли.
Отсюда же объяснение, почему на публичной валидации DSC заметно ниже, чем на скрытой (54% против 75%). Публичные 50 снимков — трудные: в них много крупных опухолей, прорастающих в окружающие ткани. Скрытая валидация ближе по составу к обучающей выборке. Поэтому изменения меньше 0.01 DSC на публичной валидации мы не считали поводом что‑то менять.
Что в итоге? Пять фолдов и самое быстрое решение

Финальная проверка шла на закрытой выборке из 500 снимков, причем из больниц, которых не было в обучающих данных. Ни одного снимка из неё участники не видели, а запускали решения сами организаторы на своем оборудовании.
Главный итог: PANTHER — самое быстрое решение Task 1. На машине организаторов наш ансамбль обрабатывал снимок в среднем за 23.4 с, тогда как у остальных финалистов — от 30 до 51 с. И это при том, что внутри работают пять полноценных нейросетей, а не одна облегченная модель. На MICCAI 2026 организаторы FLARE отметили нашу работу наградой Meritorious Winner Award.
Что мы вынесли из этой истории
Первый инсайт: при жёстких ограничениях главное — не новая архитектура, а то, что вы показываете модели. Половина датасета, собранная с умом, дала +6 пунктов DSC по сравнению с полным. А замена сети на втрое более тяжелую — всего +0.2.
Второй инсайт: умение промолчать можно получить почти бесплатно. Согласие пяти фолдов плюс простой фильтр по форме маски — и ложные находки на здоровых снимках падают со 100% у одиночной модели до 8%. Без отдельного классификатора и без единой метки опухоли.
Третий инсайт: когда половина рейтинга — скорость, инженерия становится частью метода, а не тем, что «потом допилим». Одна неочевидная настройка Docker может уронить решение целиком, а перенос работы в один процесс — ускорить его почти вдвое.
Отдельно хочется сказать про формат. Летняя школа для студента — это существенно больше, чем просто возможность «повторить туториал». Это шанс дойти от постановки задачи до международного соревнования, рабочего Docker‑образа и статьи. Если вам предлагают проект в духе «Аргуса» — берите. Нет ничего круче, чем понимать, что твой код однажды может помочь врачу не пропустить опухоль.
Что дальше: дистилляция ансамбля в одну сеть (минус пять проходов), аккуратное использование неразмеченных данных с фильтрацией через MedSAM2, калибровка отказа в духе conformal prediction и увеличение размера патча для крупных опухолей.
В заключение хочется поблагодарить организаторов летней школы AIRI — без них бы проект даже не начался.
Состав команды: Евгения Пржездзецкая, Василий Баранов, Мария Хазова, Виктор Гомболевский.