Двадцять дві теми відповідали на питання «що зображено». Навіть
CLIP із попередньої теми, який класифікує
реченнями, а не числами зі списку, дає одну відповідь на кадр. Тепер питання
міняється на «де саме» — і разом із ним міняється форма відповіді, спосіб її
перевірити й навіть те, що вважати помилкою. Ця тема не будує жодного детектора:
архітектури починаються з наступної.
Тут ми ставимо задачу й вчимося міряти. Це нудніша половина роботи, і водночас
та, у якій найлегше себе обдурити: число mAP@0.5 = 0.72 виглядає
переконливо, поки не спитаєш, що саме за ним стоїть.
ФормаВідповідь стає списком
Класифікатор влаштовано так, що його зручно перевіряти. На вході картинка, на виході вектор фіксованої довжини — по числу на клас. Береш найбільше, дістаєш мітку, порівнюєш із правильною. Відповідь або та, або не та; ділиш кількість влучань на кількість картинок і маєш точність. Уся ця простота тримається на одному: у відповіді рівно один елемент, і він стоїть на відомому місці.
Детектор віддає список. У кадрі може не бути жодного предмета, може бути один, може бути сорок. Модель не знає наперед скільки — і саме тому не може видати вектор фіксованої довжини. Кожен елемент списку — це чотири числа рамки, мітка класу і впевненість, тобто число від нуля до одиниці, наскільки модель вірить, що там справді предмет.
Довжини цих двох списків різні. Порядок елементів у них нічого не означає: детектор не зобовʼязаний віддавати предмети в тому самому порядку, у якому їх записав розмітник. Отже, порівняти «перший з першим, другий з другим» не можна навіть теоретично. Перш ніж рахувати будь-яку метрику, доведеться відповісти на питання, якого в класифікації просто не існувало: яка передбачена рамка про який справжній предмет.
Із цього одного факту випливає весь інший зміст теми. Потрібна міра схожості двох рамок — це IoU. Потрібне правило, яке з цієї міри робить рішення «зарахувати чи ні» — це поріг. Потрібен алгоритм, який розкладає передбачення по істинних рамках — це зіставлення. Потрібні метрики, які працюють зі списками різної довжини — це точність і повнота. І потрібен спосіб позбутися дублікатів, бо модель, яка передбачає з кожної точки кадру, неминуче видасть одну рамку кілька разів — це NMS.
ЗаписРамка й три її формати
Тема 02 уже вводила рамку: прямокутник зі сторонами, паралельними краям кадру, задається чотирма числами. Тут нас цікавить прикра дрібниця — що саме це за чотири числа. Бо однозначної відповіді немає, і в обігу три різні записи однієї й тієї самої рамки.
| формат | чотири числа | наш квадрат | де живе |
|---|---|---|---|
| xyxy | лівий-верхній і правий-нижній кут | 31, 40, 50, 59 | torchvision, Pascal VOC |
| xywh | лівий-верхній кут, ширина, висота | 31, 40, 19, 19 | COCO |
| cxcywh | центр, ширина, висота | 40.5, 49.5, 19, 19 | YOLO, DETR |
| нормовані | те саме, поділене на розмір кадру | 0.633, 0.773, 0.297, 0.297 | файли розмітки YOLO |
Це один і той самий квадрат із нашої першої перевірної сцени. У
torchvision переклад між форматами робить
box_convert(boxes, in_fmt, out_fmt) — три рядки, жодної математики
руками. Нормовані координати — окрема історія: вони не залежать від розміру
кадру, тому файл розмітки лишається чинним після будь-якого масштабування. За
це доводиться платити тим, що з чисел зникає одиниця виміру, і 0.297
не підказує, чи це 19 пікселів, чи 190.
Чому формати плутають
Тому що помилка тиха. Усі чотири записи — це чотири числа однакового
вигляду. Якщо передати xywh у функцію, що чекає xyxy,
жодного винятку не буде: бібліотека сумлінно порахує рамку з кутами (31, 40) і
(19, 19). Вона вийде вивернутою, з відʼємними шириною й висотою, IoU з чим
завгодно дорівнюватиме нулю, і в звіті просто буде поганий результат — без
натяку, звідки він.
Ловиться це трьома звичками, і жодна з них не коштує часу. Перша:
assert (boxes[:, 2] > boxes[:, 0]).all() одразу після
завантаження розмітки. Друга: подивитись на діапазон чисел — нормовані
координати не бувають більші за одиницю, піксельні не бувають дробовими на виході
розмітника. Третя й найнадійніша: намалювати перші пʼять рамок поверх
зображення й подивитися очима. Якщо вони лежать не там, це видно за секунду.
x2 − x1 + 1, COCO рахує x2 − x1. Для рамки в 19
пікселів різниця в площі — понад десять відсотків, і на маленьких предметах
вона добре видно в метриці. У нашому датасеті рамка береться як
xs.max() + 1, тобто за угодою COCO, і ширина дорівнює 19.ЗбігIoU: одне число на дві рамки
Щоб сказати, чи описують дві рамки один предмет, потрібне число. Це число — IoU (intersection over union, перетин, поділений на обʼєднання). Словами: поклади дві рамки одна на одну; частина площі належить обом — це перетин; уся площа, яку вони разом накривають, — це обʼєднання; IoU — перше, поділене на друге. Одиниця — рамки збіглися ідеально. Нуль — не торкаються.
Порахуймо руками на найменшому прикладі, який тільки можна вигадати. Рамка A має кути (10, 10) і (30, 30). Рамка B — (20, 20) і (40, 40). Обидві сторонами по 20 пікселів.
Ліва межа перетину — правіша з двох лівих меж: більше з чисел 10 і 20, тобто 20. Верхня межа — нижча з двох верхніх: теж 20.
Права межа перетину — лівіша з двох правих: менше з чисел 30 і 40, тобто 30. Нижня — так само 30.
Ширина перетину — 30 мінус 20, тобто 10. Висота так само 10. Якщо різниця
вийшла відʼємною, рамки не перетинаються й площа дорівнює нулю — тому в коді
завжди пишуть max(0, x2 − x1).
Кожна рамка має площу 20 × 20 = 400. Якщо просто скласти, спільну частину порахуємо двічі — тому її треба відняти один раз.
torchvision.ops.box_iou на тих самих двох рамках дає
0.142857 — збіг до шостого знака. Усередині бібліотеки саме ці пʼять
кроків і нічого більше.
IoU наживо
Бірюзова рамка нерухома, рожеву можна рухати й розтягувати повзунками. Перетин залито суцільним, обʼєднання обведено пунктиром. Праворуч — ті самі пʼять кроків, порахованих для поточного положення.
Чого IoU не каже
IoU стискає взаємне розташування двох прямокутників в одне число, а отже, неминуче щось викидає. Найважливіше з викинутого: IoU не розрізняє, у чому саме модель помилилась. Ось три рамки, кожна з яких дає з тим самим квадратом 40×40 рівно 0.5, і три зовсім різні помилки за цим числом.
| помилка | що зробила модель | IoU |
|---|---|---|
| менша | рамка на місці, але вдвічі менша за площею: сторона 28.3 замість 40 | 0.500 |
| зсунута | рамка того самого розміру, зсунута на 13.3 пікселя вбік | 0.500 |
| повернута | предмет лежить під 45°, і рамка навколо нього вдвічі більша за площею | 0.500 |
Для метрики це один і той самий результат. Для інженера — три різні діагнози: у першому випадку модель недооцінює розмір, у другому — промахується центром, у третьому взагалі впирається в межу самого формату, бо рамка зі сторонами вздовж кадру не вміє описати повернутий предмет. Жодну з цих причин mAP не назве.
Одне число, три різні помилки
Кнопки перемикають характер помилки, повзунок задає бажаний IoU. Розміри й зсув перераховуються так, щоб число лишалося тим самим — а картинка щоразу інша.
ЗіставленняЗіставлення передбачень з істиною
Тепер, коли схожість двох рамок вимірюється числом, повернімось до питання з першого розділу: яка передбачена рамка про який справжній предмет. Стандартна відповідь — жадібний алгоритм за спаданням упевненості. Слово «жадібний» означає, що на кожному кроці він бере найкраще з доступного зараз і ніколи не переглядає ухвалених рішень.
- Відсортуй усі передбачення за впевненістю, від найвпевненішого до найменш.
- Візьми перше. Знайди серед ще не зайнятих істинних рамок ту, з якою в нього найбільший IoU.
- Якщо цей IoU не менший за поріг — зарахуй передбачення як влучне (TP, true positive) і познач істинну рамку зайнятою. Інакше передбачення — хибне спрацювання (FP, false positive).
- Перейди до наступного передбачення й повтори.
- Істинні рамки, які лишились незайнятими, — це пропуски (FN, false negative).
Ключове тут — слова «ще не зайнятих». Одну істинну рамку не можна зарахувати двічі. Якби можна було, детектор із єдиною стратегією «видай сто копій однієї правильної рамки» отримав би сто влучань поспіль і виглядав би ідеальним. Правило «одна істина — одне влучання» перетворює зайві копії на хибні спрацювання, і саме через нього дублікати псують метрику. Тримай це в голові до розділу про NMS: NMS існує тому, що зіставлення влаштоване саме так.
Порядок за впевненістю теж не випадковий. Він робить алгоритм передбачуваним: найвпевненіше передбачення дістає першу спробу зайняти істинну рамку. Але жадібність — це угода, а не теорема. Вона не гарантує найкращого можливого розкладу: буває, що менш упевнена рамка зайняла б свою істину точніше, а тепер лишилась ні з чим. Оптимальний розклад дає угорський алгоритм, і саме він стоїть у навчанні DETR із теми 27. Але в оцінюванні всі — і COCO, і Pascal VOC — користуються жадібним, тому й ми рахуємо ним.
Хто з ким зіставився
Справжня сцена з перевірного набору: три предмети й 18 рамок, які видав наш детектор — усі, як є, без жодного прибирання. Повзунок міняє поріг IoU, за яким передбачення вважається влучним.
ДисбалансЧому «точність» тут безглузда
У класифікації є проста метрика: частка правильних відповідей. Спокуса перенести її на детекцію велика, і вона хибна одразу з двох боків.
Перший бік — ділити немає на що. Частка правильних відповідей потребує знаменника: скільки всього було питань. У детекції кількість передбачень — не властивість задачі, а рішення самої моделі. Опустиш поріг упевненості — рамок стане більше, і знаменник виросте. Метрика, якою можна керувати, крутячи ручку після навчання, нічого не міряє.
Другий бік — дисбаланс. Уяви, що ми все-таки поставили задачу так, щоб знаменник зʼявився: розбили кадр сіткою 8×8 і питаємо кожну з 64 клітинок, є в ній предмет чи ні. Тепер відповідей рівно 64, і частку правильних порахувати можна. Візьмімо одну сцену — ту саму, що на попередній фігурі, з трьома предметами, — і найсуворіше правило: предмет займає рівно ту клітинку, у якій лежить його центр. Тоді предметам належать три клітинки, а решта 61 — фон.
Модель, яка мовчки відповідає «предмета немає» на всі 64 клітинки, дістає 95.3 % «точності» й нуль користі. Вона не помиляється — вона просто нічого не знаходить, і сітка щедро зараховує їй кожну порожню клітинку. Це не софізм і не крайній випадок — це звичайна арифметика будь-якої сітки детектора.
Наш датасет улаштований трохи щедріше: позитивною вважається кожна клітинка, центр якої потрапив усередину рамки, тому на один предмет припадає в середньому 4.52 клітинки замість однієї. Друга різниця — рахуємо вже не одну сцену, а всі 400 навчальних, а в них предметів у середньому 2.06, а не три. Ось точні числа:
| що рахуємо | значення |
|---|---|
| клітинок усього (400 сцен × 64) | 25 600 |
| клітинок із предметом | 3 732 |
| клітинок фону | 21 868 |
| частка фону | 85.4 % |
| предметів на сцену в середньому | 2.06 |
| клітинок на один предмет | 4.52 |
Навіть у цьому щедрому варіанті мовчазна модель має 85.4 %. Два числа цього розділу — 95.3 % і 85.4 % — не суперечать одне одному й не заміняють одне одного: перше знято на одній сцені з трьома предметами за правилом «одна клітинка на предмет», друге — на всіх 400 навчальних сценах за правилом «центр клітинки в рамці». Щедріше правило й менше предметів на сцену тягнуть частку фону в різні боки, і різниця виходить у десять відсоткових пунктів. Тому будь-яка частка фону без назви сітки й набору — просто число.
А в справжніх детекторах, де сітка густіша й на кожну клітинку припадає кілька рамок-кандидатів, частка фону легко переходить за 99.9 %. Цей дисбаланс не лише ламає метрику — він ламає й навчання: якщо всі клітинки важать однаково, градієнт від фону затопить градієнт від предметів. Саме заради цієї проблеми вигадали focal loss, і про нього — тема 26.
Дві сітки — дві частки фону
Та сама сцена 64×64, розбита сіткою 8×8. Перемикач міняє правило, за яким клітинку вважають позитивною, повзунок — скільки предметів у сцені. Праворуч — скільки «правильних відповідей» дістає модель, яка на кожну клітинку каже «предмета немає».
accuracy) — скільки клітинок або
картинок модель класифікувала правильно з усіх. Уже в наступному розділі те саме
українське слово означатиме зовсім інше — precision, частку справжніх
предметів серед намальованих рамок. Це не недогляд перекладу, а усталений збіг:
у детекції accuracy як метрику якості не вживають саме тому, що
вона безглузда, тож слово «точність» без лапок далі завжди означає precision. Друга
частка — recall, повнота — теж чекає в наступному розділі.ПараТочність і повнота
Замість однієї частки правильних відповідей детекція користується парою чисел, і кожне з них відповідає на своє питання про список рамок.
Із рамок, які я намалював, скільки виявились справжніми? Це питання про сміття у відповіді.
Із предметів, які насправді були, скільки я знайшов? Це питання про пропущене.
Тут TP — кількість влучних передбачень, FP — хибних спрацювань, FN — пропущених предметів; усі три беруться із зіставлення з попереднього розділу. Знаменники в них різні, і в цьому вся суть: у точності — те, що видала модель, у повноті — те, що є в кадрі насправді.
Жодне з двох чисел саме по собі нічого не варте, і обдурити кожне окремо тривіально. Детектор, який малює одну-єдину найвпевненішу рамку, майже напевно матиме точність 1.0 — і повноту, близьку до нуля. Детектор, який засипає кадр тисячею рамок на всі випадки життя, матиме повноту 1.0 і точність, близьку до нуля. Отже, дивитись треба на обидва разом, і завжди питати, за якого порогу впевненості їх поміряли.
Поріг упевненості — це ручка, а не константа
Ось найважливіша річ у цьому розділі. Наш детектор навчено один раз. Його ваги зафіксовані. Але його точність і повнота міняються від 0.042 до 0.946 і від 0.988 до 0.773 відповідно — і жодне навчання при цьому не відбувається. Міняється тільки одне число: поріг, нижче за який ми викидаємо рамки, не дивлячись.
Усі числа таблиці нижче зняті на 120 перевірних сценах після притлумлення дублікатів із порогом 0.5 — того самого, про яке піде мова в розділі 09. Без нього рамок було б у кілька разів більше, і саме це число ми там і побачимо.
| поріг | рамок | точність | повнота |
|---|---|---|---|
| 0.0001 | 5 769 | 0.042 | 0.988 |
| 0.001 | 2 213 | 0.109 | 0.980 |
| 0.003 | 529 | 0.457 | 0.980 |
| 0.01 | 335 | 0.722 | 0.980 |
| 0.05 | 290 | 0.828 | 0.972 |
| 0.5 | 278 | 0.863 | 0.972 |
| 0.95 | 269 | 0.888 | 0.968 |
| 0.999 | 202 | 0.946 | 0.773 |
Зверни увагу на шкалу лівої колонки: цікаве відбувається не між 0.4 і 0.6, а між 0.0001 і 0.01. Це типово. Детектор, який добре навчився, ставить фоновим клітинкам не 0.3, а 0.000001, тому «природний» поріг 0.5 стоїть глибоко в пласкій частині, де майже нічого не міняється. Робочу точку нашого детектора ми взяли при 0.05: 290 рамок на 247 істинних, точність 0.828, повнота 0.972. Це означає 240 влучань, 50 хибних спрацювань і 7 пропущених предметів.
Ручка порога
Один і той самий навчений детектор. Повзунок міняє лише поріг упевненості; смуги показують точність і повноту, число під ними — скільки рамок лишилось у відповіді.
КриваКрива й площа під нею
Якщо кожне положення ручки дає свою пару чисел, то чесний опис детектора — не точка, а крива. Побудувати її просто: по горизонталі відкладаємо повноту, по вертикалі — точність, і проходимо всі пороги від найвищого до найнижчого. Починаємо з правого верхнього кута метрики — мало рамок, висока точність — і сповзаємо вправо-вниз: рамок більше, повнота росте, точність падає.
Дві криві порівнювати на око незручно, а звітувати кривою в таблиці неможливо. Тому беруть площу під нею — одне число від нуля до одиниці, яке зветься AP (average precision, середня точність). Ідея за площею проста: вона підсумовує поведінку моделі на всіх робочих точках одразу, а не на тій, яку автор звіту вибрав собі до смаку.
Спершу — вирівнювання сходинок
Сира крива не спадає рівно: вона пиляста. Причина механічна. Кожне наступне передбачення в порядку спадання впевненості або влучне, і тоді точність підстрибує, або хибне — і тоді падає. Перед інтегруванням цю пилку прибирають інтерполяцією: у кожній точці замість справжньої точності беруть найбільшу точність, досяжну праворуч, тобто при цій або більшій повноті.
Читається так: «інтерпольована точність при повноті r дорівнює найбільшій точності серед усіх точок, де повнота не менша за r». Змісту тут більше, ніж косметики: якщо, опустивши поріг, можна дістати і більшу повноту, і більшу точність одразу, то стара точка просто не варта уваги — вона гірша за наявну альтернативу за обома показниками.
Два способи взяти площу
Метод усіх точок (сучасний, COCO). Площу беруть по кожній сходинці кривої: на скільки виросла повнота, помножити на інтерпольовану точність у цій точці, і все це скласти. На нашому детекторі виходить AP@0.5 = 0.9314.
Одинадцятиточковий метод (Pascal VOC до 2010 року). Беруть рівно одинадцять значень повноти — 0, 0.1, 0.2, …, 1.0 — зчитують інтерпольовану точність у кожному й усереднюють. На тому самому детекторі — AP@0.5 = 0.8663.
Різниця 0.065 при однаковій кривій. Звідки вона? Наш детектор ніколи не дістає повноти вище 0.988, а одинадцятиточковий метод усе одно питає про повноту 1.0 — і зараховує туди нуль. Один цей нуль важить одну одинадцяту всієї суми, тобто 0.091. Решта десять точок дають майже однакові 0.95, і саме недосяжна остання точка зʼїдає різницю. Метод усіх точок про недосяжну повноту просто не питає.
Крива й площа
Повзунок веде поріг від найвищого до найнижчого, і крива добудовується на очах. Кнопка перемикає спосіб узяти площу: усі точки чи одинадцять.
УсередненняmAP: два усереднення
AP описує один клас при одному порозі IoU. Літера «m» на початку mAP — це mean, середнє. Усереднень насправді два, і плутають їх постійно.
Перше усереднення: по класах
Рахуємо AP окремо для кола, окремо для квадрата, окремо для трикутника, тоді беремо середнє арифметичне.
| клас | істинних рамок | AP@0.5 | AP@0.5:0.95 |
|---|---|---|---|
| коло | 84 | 0.9216 | 0.4459 |
| квадрат | 76 | 0.9620 | 0.5540 |
| трикутник | 87 | 0.9342 | 0.4700 |
| mAP | 247 | 0.9393 | 0.4900 |
Середнє тут просте, не зважене на кількість. Клас із десятьма рамками важить рівно стільки ж, скільки клас із десятьма тисячами. Це свідоме рішення COCO, і воно має неприємний наслідок: один поганий рідкісний клас тягне mAP униз сильніше, ніж підказує здоровий глузд. Якщо в задачі 80 класів і на трьох із них детектор сліпий, вони віднімуть від mAP до чотирьох відсоткових пунктів — навіть якщо в кадрах вони трапляються раз на тисячу.
Друге усереднення: по порогах IoU
Поріг 0.5 обрано колись довільно, і сам по собі він поблажливий. Наскільки — показує пряма арифметика. Візьми рамку зі стороною 40 пікселів і посунь її вбік; ось на скільки її можна зсунути, зберігши заданий IoU:
| потрібний IoU | допустимий зсув | частка сторони |
|---|---|---|
| 0.50 | 13.3 px | 33 % |
| 0.75 | 5.7 px | 14 % |
| 0.90 | 2.1 px | 5 % |
Тобто mAP@0.5 зараховує рамку, зсунуту на третину власної сторони. Це
дуже поблажливо. Щоб винагороджувати акуратність, COCO рахує AP при десяти
порогах — 0.50, 0.55, …, 0.95 — і бере середнє. Це і є
mAP@0.5:0.95, або просто mAP у сучасних статтях.
У таблиці нижче показано кожен другий поріг із десяти — 0.50, 0.60, 0.70, 0.80, 0.90; проміжні 0.55, 0.65, 0.75, 0.85 і 0.95 опущено, щоб таблиця читалась. Останній рядок усереднює всі десять, тож він менший за середнє пʼятьох показаних: пропущені пороги лежать нижче за своїх сусідів зліва.
| поріг IoU | коло | квадрат | трикутник | mAP |
|---|---|---|---|---|
| 0.50 | 0.922 | 0.962 | 0.934 | 0.939 |
| 0.60 | 0.879 | 0.915 | 0.847 | 0.880 |
| 0.70 | 0.475 | 0.729 | 0.605 | 0.603 |
| 0.80 | 0.162 | 0.403 | 0.126 | 0.230 |
| 0.90 | 0.001 | 0.015 | 0.000 | 0.005 |
| середнє по 10 порогах | 0.446 | 0.554 | 0.470 | 0.490 |
mAP@0.5 = 0.939 і mAP@0.5:0.95 = 0.490 — це
один і той самий детектор, на тих самих 120 сценах, з тими самими вагами.
Від першого числа до другого зникла майже половина. Перше каже «рамка приблизно
там, де предмет». Друге каже «рамка майже ідеально збігається з предметом». Коли
хтось показує тобі mAP, перше питання — яке з двох.Наш детектор передбачає рамку з клітинки 8×8 пікселів, тому 2-3 пікселі похибки для нього норма — і при порозі 0.9 від AP не лишається нічого. Для порівняння, цитовані числа з літератури на COCO: у типового сучасного детектора mAP@0.5 близько 0.6-0.7, а mAP@0.5:0.95 — близько 0.4-0.5. Пропорція та сама, що й у нас: суворіший поріг зрізає приблизно третину-половину.
ДублікатиNMS: прибирання дублікатів
Тепер про те, чому список передбачень узагалі виходить довшим за список предметів. Причина в будові виходу детектора. Голова рахує рамку з кожної клітинки сітки, а предмет накриває не одну клітинку, а кілька — у нашому датасеті в середньому 4.52. Кожна з них бачить той самий предмет і чесно видає свою рамку. Виходить купа майже однакових прямокутників на одному місці.
Наш детектор при порозі впевненості 0.05 віддає 1134 рамки на 120 сцен, у яких 247 предметів. Точність такого списку — 0.215, тобто чотири рамки з пʼяти зайві. І це не помилка навчання: усі вони правильні, просто повторюють одна одну.
Лікує це NMS (non-maximum suppression, притлумлення немаксимумів). Ідея в одному реченні: серед рамок, які сильно перекриваються, лиши найвпевненішу, а решту викинь.
- Відсортуй рамки за спаданням упевненості.
- Візьми найвпевненішу, поклади її у відповідь.
- Викинь із черги всі рамки, у яких IoU з нею більший за поріг.
- Повтори з наступною вцілілою, поки черга не спорожніє.
У torchvision це ops.nms(boxes, scores, iou_threshold).
Функція повертає індекси рамок, які треба лишити, і працює саме за цими чотирма
кроками — жодної додаткової хитрості всередині немає. Написати такий самий NMS
самотужки — це десяток рядків, і на однакових входах він дає той самий список
індексів; фігура нижче рахує його прямо в браузері.
| поріг NMS | рамок лишилось | точність | повнота |
|---|---|---|---|
| 0.1 | 220 | 0.973 | 0.866 |
| 0.2 | 229 | 0.956 | 0.887 |
| 0.3 | 244 | 0.939 | 0.927 |
| 0.5 | 290 | 0.828 | 0.972 |
| 0.7 | 485 | 0.501 | 0.984 |
| 0.9 | 1 024 | 0.238 | 0.988 |
| без NMS | 1 134 | 0.215 | 0.988 |
Тут видно і користь, і ціну. NMS із порогом 0.5 викидає 844 рамки з 1134 і піднімає точність із 0.215 до 0.828, віддавши за це лише 0.016 повноти. А жадібний поріг 0.1 піднімає точність до 0.973 — і забирає повноту з 0.988 аж до 0.866, тобто губить кожен восьмий предмет.
NMS на справжніх передбаченнях
Та сама сцена з трьома предметами й 18 рамками, які видав детектор. Повзунок міняє поріг NMS; вцілілі рамки суцільні, притлумлені — бліді.
МежаДе NMS ламається
Усе попереднє мовчки спиралось на припущення: дві рамки, що сильно перекриваються, описують один предмет. Це припущення не завжди правдиве, і коли воно хибне, NMS робить непоправну шкоду.
Візьми звичайну вуличну сцену: машина стоїть за машиною, людина йде за людиною. Два справжні, різні предмети, і їхні рамки перекриваються, бо задній предмет видно лише частково. Порахуймо, наскільки саме. Рамки 60×120 пікселів, задня зсунута вбік на кілька пікселів:
| зсув | IoU | поріг 0.3 | поріг 0.5 | поріг 0.7 |
|---|---|---|---|---|
| 10 px | 0.714 | загубили | загубили | загубили |
| 15 px | 0.600 | загубили | загубили | обидві |
| 20 px | 0.500 | загубили | обидві | обидві |
| 25 px | 0.412 | загубили | обидві | обидві |
Читай середню колонку. При загальноприйнятому порозі 0.5 два предмети, що стоять на відстані 10 або 15 пікселів один від одного, перетворюються на один: NMS викидає задній назавжди. Ніякий наступний етап його не поверне — рамки більше немає, і жоден шар про це не дізнається. У метриці це виглядатиме як звичайний пропуск, і причина пропуску в звіті не зʼявиться.
Тут же видно, чому просто підняти поріг не можна. Ми вже бачили це в таблиці попереднього розділу: поріг 0.9 повертає повноту 0.988, але точність падає до 0.238. Виходить вибір без доброї відповіді: низький поріг губить справжні предмети, високий лишає дублікати. NMS не має способу відрізнити одне від одного, бо дивиться тільки на геометрію.
Два справжні предмети під ножем NMS
Дві рамки 60×120 — це два різні предмети, обидва справжні. Повзунок розсуває їх, кнопки міняють поріг NMS. Вердикт каже, скільки з двох доживе до відповіді.
Спроба лікування: Soft-NMS
Найвідоміша спроба виправити це називається Soft-NMS і міняє один крок алгоритму. Замість викидати перекриту рамку, їй знижують упевненість — тим сильніше, чим більший IoU з переможцем. Рамка з IoU 0.95 отримує майже нульову впевненість і фактично зникає; рамка з IoU 0.6 лишається в списку з помітно меншим числом. Далі спрацьовує поріг упевненості: якщо задній предмет був розпізнаний упевнено, зниження його не вбʼє, і в відповідь він потрапить. Виграш на щільних сценах реальний, але невеликий, а плата — ще один гіперпараметр і повільніший прохід. Радикальніші відповіді на ту саму проблему дає DETR із теми 27, який позбувається NMS взагалі: угорське зіставлення під час навчання прямо забороняє двом виходам описувати один предмет, тому дублікатів немає й прибирати нічого.
МовчанняЧого метрики не кажуть
mAP — добра метрика. Вона зводить довгий список рамок до одного порівнюваного числа, не залежить від обраної робочої точки й однаково поводиться з класами різної частоти. Але одне число не може сказати всього, і корисно точно знати, про що саме воно мовчить.
Які саме предмети пропущено. mAP усереднює по класах, а не по важливості. Пропущений пішохід і пропущена поштова скринька віднімають від числа однаково. Для системи допомоги водієві це різниця між дефектом і катастрофою, і метрика її не бачить.
Чого коштує помилка. Хибне спрацювання й пропуск входять у формули симетрично. У медичному застосуванні пропущена пухлина коштує незрівнянно більше, ніж зайва рамка, яку лікар відкине за секунду. Хто хоче це врахувати, рахує метрику при фіксованій повноті — наприклад, «яка точність при повноті 0.99» — і на mAP не спирається.
Скільки це коштує часу. У mAP немає ані мілісекунд, ані мегабайтів. Детектор, який дає 0.52 за 8 мілісекунд, і детектор, який дає 0.54 за 300, у таблиці стоять поруч, а в житті вирішують різні задачі. Порівнювати треба парою «якість і швидкість», як робила тема 18.
Наскільки правильна сама розмітка. Метрика мовчазно вважає еталонну розмітку істиною. У нашому датасеті це справді так — рамка порахована з маски формулою. У справжніх даних розмітник ставив її рукою за 15 секунд, і різниця між двома розмітниками на тому самому предметі спокійно дає IoU 0.85. Це означає, що при порозі 0.9 метрика частково міряє не детектор, а тремтіння руки.
Яка крива стоїть за числом. Два детектори з однаковим mAP можуть мати зовсім різні криві: один рівний скрізь, другий чудовий при малій повноті й безпорадний при великій. Якщо тобі потрібна саме велика повнота, середнє по всій кривій обере не ту модель. Криву варто дивитися очима, а не лише її площу — і цим ми займемось у темі 28, де детектор доведеться не оцінювати, а запускати на реальних даних.
ПідсумокПідсумок і місток далі
Тема не побудувала жодної мережі, зате поставила задачу так, що її тепер можна чесно міряти. Коротко про те, що маємо.
| поняття | у чому суть |
|---|---|
| Список замість мітки | вихід невідомої довжини, тому перед метрикою потрібне зіставлення |
| IoU | перетин на обʼєднання; на наших рамках порахований руками — 0.142857 |
| Зіставлення | жадібне за впевненістю; одна істина — не більше одного влучання |
| Точність і повнота | дві частки з різними знаменниками; жодна сама по собі не працює |
| AP | площа під кривою точність-повнота; не залежить від обраного порога |
| mAP | середнє AP по класах, а часто ще й по десяти порогах IoU |
| NMS | післяобробка проти дублікатів; ламається на щільних сценах |
Головне число, яке варто винести: mAP@0.5 = 0.939 і
mAP@0.5:0.95 = 0.490 — це один детектор. Тепер, зустрівши в чужому
звіті mAP@0.5 = 0.72, ти знаєш чотири питання, які треба поставити:
який поріг NMS, який поріг упевненості, який метод площі й чи це середнє по
класах. Без відповідей на них число не порівнюване ні з чим.
Задачу поставлено, метрики є, залишилось збудувати те, що вони міряють. Наступна тема береться за перший робочий підхід до детекції — сімейство R-CNN, яке виграло детекційне змагання ImageNet і показало, що згорткові ознаки годяться не лише для класифікації. Ідея там проста до незручності: спершу знайти кілька тисяч місць, де може бути предмет, а потім класифікувати кожне окремо. Проста — і повільна; історія блоку 5 значною мірою і є історія боротьби з цією повільністю, від YOLO до одноетапних детекторів і DETR.