- avito-floorplan-checkpoints
- RF-DETR-Seg (Medium)
- YOLO11m-seg
- Mask R-CNN (ResNet-50 FPN, MMDetection)
- SegFormer (b2)
- UNet-simple (внешняя модель, не часть основного сравнения)
- RF-DETR-Seg (Medium) — fullaug (данные коллеги, augmentation pipeline v2)
- YOLO-seg — fullaug (данные коллеги)
- Методологическая правка: ignore-регионы для UGC test (2026-08-01)
- Сводная таблица (UGC test, реальные фото, с ignore-region фиксом)
- Confidence-threshold sweep (2026-08-02): проверка, оптимален ли порог 0.1
- SAM fine-tuned — дообучение НЕ помогло (важный отрицательный результат)
- RF-DETR-Seg (Medium)
avito-floorplan-checkpoints
Чекпоинты instance-segmentation моделей из сравнительного исследования сегментации комнат на поэтажных планах (ResPlan_v2 + CubiCasa5K для обучения, реальные UGC-фото с Avito для теста). Код: см. основной проект.
Классы (везде одинаковые, id 1-7): living, bedroom, bathroom, kitchen, balcony, wall, opening.
Train/valid split: 80/20, seed=42, одинаковый для всех моделей.
Этот файл — журнал экспериментов по обучению моделей, методологии
оценки и confidence-threshold. Эксперименты с пост-процессингом
room/living/bedroom (заливка по границам, squareness-фильтр, mask-NMS
для RF-DETR — числа и коллажи) вынесены отдельно:
docs/room_postprocessing_experiments.md.
RF-DETR-Seg (Medium)
rfdetr_seg/checkpoint_best_ema.pth
- Модель:
RFDETRSegMedium(библиотекаrfdetr) - batch_size=2, grad_accum_steps=2 (эффективный batch 4), lr=1e-4
- Обучение остановлено по плану на эпохе 5 (компромисс время/бюджет на общем сервере) — веса из эпохи 4 (последняя посчитанная валидация)
- Валидация (эпоха 4): box mAP@50=0.900, mAP@50:95=0.826, segm mAP@50=0.834, segm mAP@50:95=0.560
- UGC test: segm AP@50=0.277, AP@50:95=0.175
YOLO11m-seg
yolo_seg/best.pt
- target epochs=100, batch=8, imgsz=640, early-stopping patience=30
- Обучение остановлено вручную на эпохе 53 (сервер понадобился для другого) — это НЕ финальный/дообученный чекпоинт, просто снимок на момент остановки
- Валидация (эпоха 53): box mAP@50=0.942, mAP@50:95=0.877, mask mAP@50=0.911, mask mAP@50:95=0.690
- UGC test: segm AP@50=0.260, AP@50:95=0.170 (было 0.249/0.163 на 2-эпочном чекпоинте)
Mask R-CNN (ResNet-50 FPN, MMDetection)
maskrcnn/best_coco_segm_mAP_epoch_1.pth
- Конфиг:
mask-rcnn_r50_fpn_1x_coco.py, дообучение с COCO-претрейна - batch_size=2 (train), lr=0.0025 (в 8 раз меньше стандартного — под маленький batch/transfer learning)
- Обучение шло через несколько запусков по 2 часа (общий сервер, разделяемые
GPU) с
--load-fromот предыдущего чекпоинта — эпохи считаются заново на каждом запуске, это НЕ единый непрерывный прогон на 24 эпохи из конфига - Текущий чекпоинт — лучший по
coco/segm_mAPна момент заливки: bbox mAP@50:95=0.683, bbox mAP@50=0.863, segm mAP@50:95=0.675, segm mAP@50=0.858 (значения на валидации на обучающих данных, НЕ на UGC) - UGC test (с ignore-region фиксом): segm AP@50=0.218, AP@50:95=0.142, IoU=0.126, Dice=0.202, Precision=0.404, Recall=0.241
SegFormer (b2)
segformer/best.pt
- Backbone:
nvidia/segformer-b2-finetuned-ade-512-512(HuggingFace, дообучен под наши 8 классов, включая background) - batch_size=8, lr=6e-5, target epochs=60, early-stopping patience=10
- Разметка семантическая (не instance) — на UGC test оценивается через connected-components (маска -> инстансы), что методологически невыгодно для этой модели по сравнению с "родными" instance-детекторами
- Обучение полностью завершено (все 60 эпох), best_val_mIoU=0.8626 (эпоха 60) — но по факту метрика плато на ~0.855-0.863 последние 8+ эпох, без устойчивого роста
- UGC test: segm AP@50=0.056, AP@50:95=0.021
UNet-simple (внешняя модель, не часть основного сравнения)
unet_baseline/best_model.pt
- Обучена ВНЕ этого исследования (см.
ResPlan-main/train_resplan_v2.pyв отдельном репозитории) — используется здесь только как референсный бейзлайн "простая семантическая сегментация без всего остального" - Архитектура: ванильный UNet (encoder-decoder, DoubleConv-блоки), base filters=64, 8 выходных классов
- 24 эпохи, val_iou=0.805 (на своих синтетических данных)
- batch size/lr — не отслеживались нами, обучение внешнее
- UGC test: segm AP@50=0.050, AP@50:95=0.022 — заметно хуже instance-детекторов (2346 сильно фрагментированных предсказаний из-за connected-components на зашумлённой семантической карте, без instance-aware head'а)
RF-DETR-Seg (Medium) — fullaug (данные коллеги, augmentation pipeline v2)
rfdetr_seg_fullaug/checkpoint_best_ema.pth, checkpoint_best_regular.pth
- Те же гиперпараметры, что у обычной RF-DETR-Seg, но train/valid —
combined_out_v2(доп. аугментации коллеги: сжатие/повороты/шум), 9-классовая таксономия (door+window_ext раздельно) ремаплена обратно в наши 7 классов (data_prep/remap_fullaug_v2.py, opening = door ∪ window_ext) - Обучение остановлено вручную на эпохе 8/100 (school1, shared GPU2): прирост на валидации уже вышел на плато (+0.023→+0.002 за 7 эпох, segm mAP@50:95 доехал до 0.578), а на UGC test модель уже была хуже обычной RF-DETR — продолжать 92 эпохи (~5-6 дней на общем сервере) ради вероятного дальнейшего расхождения с реальным доменом сочли нецелесообразным
- Валидация (эпоха 7, best EMA): segm mAP@50:95=0.578
- UGC test (EMA, эпоха 7): segm AP@50=0.200, AP@50:95=0.123 — хуже обычной RF-DETR, вероятный domain gap (переобучение под искусственные аугментации, не совпадающие с реальными UGC-дефектами)
YOLO-seg — fullaug (данные коллеги)
yolo_seg_fullaug/best.pt
- batch=32, imgsz=640, target epochs=150, patience=30, train/valid — та же
combined_out_v2(remapped), что и у RF-DETR fullaug выше - Обучение остановлено вручную на эпохе 54 (school14, GPU2) — специально для сравнимости со старой YOLO-seg (та тоже остановлена на 53-й в своё время)
- UGC test (эпоха 54, с room-фиксом): mask AP@50=0.240, AP@50:95=0.154, IoU=0.208, Dice=0.323, Precision=0.841 (!), Recall=0.227 — заметно выросла относительно снимка на эпохе 9 (AP@50:95 0.117→0.154), но recall низкий: модель стала очень консервативной (мало, но метко)
Методологическая правка: ignore-регионы для UGC test (2026-08-01)
Категории UGC room/coridor/hall/stairs/storage (нет аналога в нашей
7-классовой таксономии) раньше просто выбрасывались из GT при подготовке
test_coco.json — из-за этого предсказание living/bedroom/etc. именно в
такой зоне засчитывалось как false positive, хотя истинный тип "room" нам
неизвестен и предсказание может быть верным. Исправлено: геометрия таких
аннотаций сохраняется в ignore_regions (см. data_prep/prepare_ugc_test.py),
и предсказания, чей bbox перекрывается с ignore-регионом на ≥50% площади,
исключаются из подсчёта precision/recall/mAP ДО оценки (см.
eval/coco_eval_common.py:filter_predictions_in_ignore_regions). Все числа
ниже — уже с этим фиксом, включая Mask R-CNN (дообследовано на school19).
Сводная таблица (UGC test, реальные фото, с ignore-region фиксом)
IoU/Dice/Precision/Recall — с двумя правками (2026-08-01/02):
- Сырая UGC-разметка вообще не различает living/bedroom (там только общая
категория "room"). Предсказания НЕ переименовываются — модель показывает
ровно то, что предсказала (living/bedroom остаются своими классами). Но
для GT="room" правильным ответом считается ЛЮБОЕ из living/bedroom —
так реальная путаница (напр. living предсказан поверх настоящей bathroom)
не маскируется под "верный room-матч". См.
eval/compute_pixel_metrics.py,eval/compute_confusion_matrix.py. - Порог confidence унифицирован на 0.1 для всех моделей (честное
сравнение) — раньше у RF-DETR/YOLO стоял 0.1, у остальных 0.3.
⚠️ Для Mask R-CNN это не сработало: её сырые предсказания на school19
уже отфильтрованы на инференсе на ≥0.3 (нужен повторный запуск с
--score-thr 0.1, пока не переделан). - Mask-NMS (
eval/mask_nms.py, IoU>0.5, кросс-классовый) — на пороге 0.1 модели (особенно RF-DETR) выдают много перекрывающихся дублей одного и того же объекта; оставляем только самую уверенную маску из группы. - Добавлена F1 (2·P·R/(P+R)) — единая сводная метрика вместо разбора двух чисел по отдельности.
mAP-колонки НЕ учитывают ни одну из этих правок (там живёт своя, отдельная логика COCOeval, не завязанная на единый порог/NMS).
По моделям (агрегат по классам)
| Модель | IoU | Dice | Precision | Recall | F1 | mAP@50 | mAP@50:95 |
|---|---|---|---|---|---|---|---|
| YOLO-seg | 0.300 | 0.437 | 0.803 | 0.348 | 0.524 | 0.279 | 0.184 |
| RF-DETR fullaug | 0.254 | 0.386 | 0.759 | 0.305 | 0.463 | 0.200 | 0.123 |
| YOLO fullaug | 0.233 | 0.354 | 0.802 | 0.267 | 0.424 | 0.240 | 0.154 |
| UNet-simple (семантическая) | 0.212 | 0.330 | 0.280 | 0.482 | 0.396 | 0.053 | 0.023 |
| Mask R-CNN | 0.209 | 0.322 | 0.597 | 0.290 | 0.387 | 0.218 | 0.142 |
| RF-DETR-Seg (Medium) | 0.213 | 0.321 | 0.247 | 0.616 | 0.385 | 0.329 | 0.216 |
| SegFormer (семантическая) | 0.192 | 0.300 | 0.348 | 0.454 | 0.360 | 0.085 | 0.035 |
| SAM zero-shot (Grounded-SAM) | 0.022 | 0.041 | 0.040 | 0.099 | 0.082 | 0.002 | 0.002 |
| SAM fine-tuned | 0.011 | 0.021 | 0.022 | 0.037 | 0.042 | 0.001 | 0.000 |
По F1 лидирует YOLO-seg (лучший баланс precision/recall). По mAP (не зависит от единого порога, полноценно интегрирует всю P-R кривую) лидирует RF-DETR-Seg — но на фиксированном пороге 0.1 её F1 просаживается, т.к. у неё 3104 из 3387 сырых предсказаний имеют score < 0.3 (низкоуверенный шум, плохая калибровка confidence по сравнению с YOLO, где таких лишь 56 из 366).
По классам (F1)
| Модель | bathroom | kitchen | balcony | wall | opening | room |
|---|---|---|---|---|---|---|
| RF-DETR-Seg | 0.16 | 0.21 | — | 0.46 | 0.42 | 0.67 |
| RF-DETR fullaug | 0.31 | 0.48 | — | 0.54 | 0.45 | 0.54 |
| YOLO-seg | 0.64 | 0.38 | — | 0.58 | 0.48 | 0.55 |
| YOLO fullaug | 0.55 | 0.15 | — | 0.53 | 0.49 | 0.41 |
| Mask R-CNN | 0.38 | 0.32 | — | 0.17 | 0.42 | 0.64 |
| SegFormer | 0.16 | 0.26 | — | 0.56 | 0.31 | 0.51 |
| SAM zero-shot | — | — | 0.01 | — | 0.06 | 0.17 |
| SAM fine-tuned | — | — | 0.00 | — | 0.08 | 0.05 |
| UNet-simple | 0.26 | 0.30 | — | 0.51 | 0.34 | 0.57 |
— = в GT+предсказаниях этой модели вообще не было пикселей класса (не 0 —
"не оценивалось"). balcony пуст почти у всех — в GT слишком мало
инстансов для устойчивой оценки, кроме SAM (у неё столько лишних
предсказаний, что она случайно "накрывает" единичные balcony-пиксели).
Наблюдения:
- Провал между валидацией на синтетике (
0.6-0.9 mAP/mIoU) и UGC test (0.02-0.33 AP) у всех моделей — ожидаемый domain gap между чистыми планами и реальными фото объявлений. - Модели с нативным instance-head (RF-DETR, YOLO, Mask R-CNN) устойчиво сильнее моделей с чисто семантической сегментацией (SegFormer, UNet) по mAP, но по Recall семантические модели неожиданно ВЫШЕ (0.46-0.47 против 0.30-0.38) — они находят больше площади нужного класса, просто с гораздо худшей точностью границ/формы (Precision 0.20-0.21 против 0.47-0.55).
- Accuracy намеренно не приводим в сводке — при таком дисбалансе классов (фон/другие комнаты доминируют по площади) она уводит в среднем 0.95-0.98 у всех моделей независимо от реального качества и неинформативна.
- SAM zero-shot (без дообучения) практически бесполезен на этом домене — GroundingDINO не умеет искать комнаты на схематичных чертежах.
- Fullaug-модели (RF-DETR, YOLO) на ранних эпохах пока ХУЖЕ обычных на UGC, несмотря на явный рост качества на своей (синтетической) валидации — открытый вопрос, помогут ли аугментации коллеги в целом, или домен аугментаций слишком расходится с реальными UGC-дефектами.
Confidence-threshold sweep (2026-08-02): проверка, оптимален ли порог 0.1
Единый порог 0.1 выбран для честного кросс-модельного сравнения (см. выше), но сам по себе он не обязательно F1-оптимален для каждой модели отдельно. Прогнан sweep с шагом 0.05 (mask-NMS iou=0.5 применялся на каждом шаге, как в финальном пайплайне) для YOLO-seg и RF-DETR-Seg — двух моделей с самой разной калибровкой confidence (см. наблюдение выше про 3104/3387 детекций RF-DETR со score<0.3 против 56/366 у YOLO).
| thresh | YOLO mIoU | YOLO F1(macro) | YOLO room F1 | RF-DETR mIoU | RF-DETR F1(macro) | RF-DETR room F1 |
|---|---|---|---|---|---|---|
| 0.05 | 0.300 | 0.524 | 0.551 | 0.213 | 0.385 | 0.675 |
| 0.10 | 0.300 | 0.524 | 0.551 | 0.213 | 0.385 | 0.675 |
| 0.15 | 0.300 | 0.524 | 0.551 | 0.262 | 0.455 | 0.746 |
| 0.20 | 0.300 | 0.524 | 0.551 | 0.264 | 0.468 | 0.672 |
| 0.25 | 0.300 | 0.524 | 0.551 | 0.249 | 0.455 | 0.418 |
| 0.30 | 0.277 | 0.493 | 0.527 | 0.244 | 0.447 | 0.291 |
| 0.35 | 0.234 | 0.432 | 0.474 | 0.157 | 0.308 | 0.103 |
| 0.40 | 0.223 | 0.414 | 0.389 | 0.134 | 0.332 | 0.000 |
| 0.50 | 0.176 | 0.339 | 0.310 | 0.093 | 0.243 | 0.000 |
(полные данные с шагом 0.05 от 0.05 до 0.95 — см. историю разговора/логи; выше — определяющие точки, дальше обе модели монотонно теряют recall и F1 падает до нуля к порогу ~0.85-0.90, где не остаётся ни одного предсказания)
Выводы:
- YOLO-seg — на 0.05-0.25 метрики идентичны (0.524/0.551), т.е. в этом диапазоне у модели просто нет "шумных" детекций с низким score, которые портили бы точность — она изначально хорошо откалибрована. Внутреннего оптимума нет, порог 0.1 уже оптимален (совпадает с любой точкой плато), можно было выбрать даже 0.25 без потерь.
- RF-DETR-Seg — здесь порог реально важен, и оптимум различается по критерию: macro F1 максимален на 0.20 (0.468, против 0.385 на 0.1 — прирост +0.083), но room F1 максимален на 0.15 (0.746, против 0.675 на 0.1 и 0.672 на 0.20). На 0.20 recall room резко падает (0.525 против 0.736 на 0.05-0.10), т.к. отсекается много верных, но неуверенных living/bedroom-детекций — trade-off между общей точностью по всем классам и recall именно по приоритетному room.
- Единый порог 0.1 (взят ради честности кросс-модельного сравнения) — осознанный компромисс: для RF-DETR он НЕ F1-оптимален (theoretically можно было бы выиграть +0.08 macro F1 или +0.07 room F1 индивидуальной калибровкой), но подбор порога "под каждую модель отдельно" сделал бы сравнение моделей друг с другом нечестным (у каждой был бы свой лучший случай). Для итоговой сводной таблицы моделей везде используется 0.1; калибровка per-model — открытая возможность для продакшена, а не для сравнительного исследования.
SAM fine-tuned — дообучение НЕ помогло (важный отрицательный результат)
sam_finetuned/checkpoints/final.pt (mask_decoder, эпоха 19/20 — эпоха 20 не
досчиталась, процесс убит сторонним фактором на school14 без объяснения в
логах, сервер сильно загружен другими пользователями)
- Дообучали ТОЛЬКО mask_decoder (image_encoder/prompt_encoder заморожены), на новых fullaug-данных, batch=8, 20 эпох, val_loss монотонно снизился 0.0587 → 0.0393 — обучение прошло штатно и явно сошлось.
- Но AP@50:95 на UGC = 0.0002, IoU=0.010 — практически идентично zero-shot версии (0.0016 / 0.024). Дообучение decoder'а НЕ дало прироста.
- Причина: боксы для промпта по-прежнему берутся от GroundingDINO (намеренно —
чтобы сравнение zero-shot/finetuned было честным, см. docstring
finetune_sam.py), а GroundingDINO как обнаружено ранее почти не находит комнаты на этом домене вообще. Каким бы хорошим ни был decoder, если бокс промпта не попадает в комнату — маска будет неверной. Узкое место всей Grounded-SAM связки — детекция боксов, а не сегментация внутри бокса.