Двоетапний детектор із попередньої теми влаштований як конвеєр: спершу окремий механізм пропонує місця, де щось може бути, потім кожне запропоноване місце окремо класифікується. Схема працює, дає високу якість — і має вбудовану ваду. Вона робить дві різні роботи двома різними частинами, і жодна з них не бачить картинку цілком. У 2016 році вийшла робота з назвою, що звучала як гасло: You Only Look Once, «дивишся лише раз». Ідея всередині була не про швидкість. Вона була про те, що детекцію можна не збирати з двох задач, а поставити як одну — і розвʼязувати одним проходом мережі.
ПостановкаІнша постановка, а не швидший конвеєр
Спершу згадаймо, як виглядає двоетапна схема. Є механізм кандидат-областей: він дивиться на зображення й видає кілька сотень або тисяч прямокутників, у яких може щось бути. Далі кожен такий прямокутник вирізається з карти ознак, приводиться до однакового розміру й подається в голову, яка каже, що там за клас і як підправити рамку. Дві частини, два навчання, два набори гіперпараметрів.
Тепер поставимо питання інакше. Уяви, що ти не шукаєш кандидатів, а просто заповнюєш анкету фіксованого розміру. Анкета розбита на клітинки — скажімо, сім на сім. У кожній клітинці кілька рядків: де центр предмета, який його розмір, наскільки я в цьому впевнений і що це за клас. Мережа дивиться на зображення один раз і заповнює всю анкету одразу. Ніяких кандидат-областей, ніякого вирізання, ніякого другого проходу.
Це і є одноетапна детекція. Формально: детекція як регресія. Вхід — зображення, вихід — один тензор фіксованої форми, і між ними одна мережа. Не «знайти, потім класифікувати», а «одразу передбачити все».
Побічний наслідок постановки — швидкість, і саме він зробив YOLO знаменитою. Але швидкість тут наслідок, а не мета. Мета — прибрати проміжну сутність під назвою «кандидат-область» й навчати все наскрізно, однією втратою.
СіткаСітка ділить відповідальність
Щойно ми сказали «анкета з клітинок», зʼявилось питання: а хто заповнює яку клітинку? Якщо на зображенні три предмети, а клітинок сорок девʼять, треба якесь правило, інакше всі клітинки почнуть описувати найпомітніший предмет.
Правило YOLO коротке до непристойності. Розділимо зображення на сітку
S × S. Клітинка відповідає за предмет, чий центр у неї
потрапив. Не «перетинається з рамкою», не «лежить усередині рамки» — саме
центр. Предмет може бути втричі більший за клітинку й накривати половину кадру;
відповідає за нього одна-єдина клітинка, у якій опинилась його середина.
Рамка задана кутами x1, y1, x2, y2. Центр — середина по
кожній осі.
Сторона клітинки — це розмір зображення, поділений на S. Номер
клітинки — це ціла частина від ділення координати на сторону клітинки. Знак
⌊ ⌋ означає «відкинути дробову частину».
Наше полотно — 64 пікселі, сітка 8 на 8, тобто клітинка 8 пікселів. Нехай
центр предмета в точці (46.5, 19.5). Тоді col = ⌊46.5 ÷ 8⌋ = 5
і row = ⌊19.5 ÷ 8⌋ = 2. Відповідає клітинка в рядку 2, стовпці 5.
Зверни увагу: обидва ділення цілочисельні, тож дробова частина координати
(0.5 пікселя) на вибір клітинки не впливає — вона знадобиться пізніше, у
розділі 04, коли ми записуватимемо, де саме всередині клітинки центр.
Уся простота правила окупається двічі. По-перше, воно не потребує жодного навчання: центр або в клітинці, або ні. По-друге, воно робить ціль однозначною — для кожного предмета є рівно один правильний адресат, тож мережа не отримує суперечливих сигналів від сусідніх клітинок. Порівняй із детектором теми 23: там позитивною була кожна клітинка, чий центр опинився всередині рамки, і на один предмет припадало по чотири-пʼять клітинок. Це теж працює, але й дублікатів породжує вчетверо більше.
Сітка й відповідальність
Сцена 64×64 з предметами. Повзунок міняє густину сітки: видно, як разом із нею змінюється те, яка саме клітинка відповідає за який предмет. Лінія веде від центра предмета до його клітинки.
ВихідЩо передбачає клітинка
Тепер запишемо анкету точно. Кожна клітинка передбачає B рамок і
C чисел класів. Кожна рамка — це пʼять чисел: x,
y, w, h і впевненість. Класи —
одні на всю клітинку, не на кожну рамку окремо; це особливість першої
YOLO, і в розділі 11 ми побачимо, як від неї відмовились.
Прочитаймо формулу словами. S × S — скільки клітинок. Множник
5 — це чотири числа рамки плюс одне число впевненості.
B · 5 — усе, що клітинка каже про свої рамки. Плюс C —
по одному числу на клас. Глибина не залежить від того, скільки предметів у кадрі:
вихід має фіксований розмір завжди, і в цьому вся суть постановки.
Підставимо числа першої YOLO: сітка 7 на 7, дві рамки на клітинку, двадцять класів набору Pascal VOC.
Тисяча чотириста сімдесят чисел — уся відповідь мережі на зображення. Для
порівняння, наша навчальна мережа працює на сітці 8 на 8 із трьома класами:
8 × 8 × 13 = 832 числа: 2 · 5 + 3 = 13 на клітинку,
шістдесят чотири клітинки.
Структура виходу
Три повзунки задають сітку, кількість рамок на клітинку й кількість класів. Угорі — вміст однієї клітинки по числах, унизу — весь тензор і його розмір.
КоординатиКоординати відносно клітинки
Тут ховається деталь, повз яку легко пройти, а вона визначає, чи мережа взагалі
навчиться. Числа x і y — це не координати в
пікселях. Це положення центра всередині своєї клітинки: нуль — лівий
верхній кут клітинки, одиниця — правий нижній. А w і h —
навпаки, частки від усього зображення.
| число | відносно чого | діапазон | чому саме так |
|---|---|---|---|
| x, y | своєї клітинки | 0…1 | голова однакова для всіх клітинок і не знає своїх координат |
| w, h | усього зображення | 0…1 | предмет буває більший за клітинку, тож у межах клітинки розмір не запишеш |
Друге пояснення варте окремого абзацу. Голова YOLO — це згортка 1×1: одні й ті самі ваги проходять по всіх клітинках. Така голова не має способу дізнатись, у якій клітинці вона зараз працює. Якби ми вимагали від неї абсолютну координату в пікселях, їй довелося б вивчити сорок девʼять різних відповідей на однаковий вхід — задача без розвʼязку. Вимагаючи зсув усередині клітинки, ми робимо задачу однаковою скрізь: «наскільки центр зміщений від лівого краю моєї клітинки». Номер клітинки додається вже після мережі, під час декодування.
Дві формули обертають одна одну, і це варто перевіряти не на слово, а
числом: закодувати всі рамки, одразу декодувати назад і порівняти з тим, що
було. На наших 247 істинних рамках перевірного набору таке кільце дало
найбільше розходження 9.5 · 10⁻⁷ пікселя — чиста похибка
округлення float32, тобто формули точні, а не «приблизно
зворотні».
Клітинка в рядку 3, стовпці 5, сторона клітинки 8 пікселів. Мережа видала
x = 0.25, y = 0.75. Тоді центр по горизонталі —
(5 + 0.25) · 8 = 42.0, по вертикалі — (3 + 0.75) · 8 = 30.0.
Прогони це в зворотний бік і перевір себе: 42.0 ÷ 8 = 5.25, ціла
частина 5 — той самий стовпець, дробова 0.25 — той самий x.
Координати: що саме передбачає мережа
Рухай рамку по сцені 64×64 й міняй її розмір. Праворуч — чотири числа, які мережа мусить видати для цієї рамки, і клітинка, від якої вони рахуються.
КоріньКорінь із ширини й висоти
У попередній таблиці w і h були просто частками від
розміру зображення. Насправді рання YOLO регресує не їх, а корені:
√w замість w. Виглядає як довільна витівка. Насправді це
виправлення цілком конкретної несправедливості.
Уяви дві квадратні рамки: одна стороною 20 пікселів, друга — 200. Мережа
обидві промахнула на 5 пікселів по кожній стороні — центр вгадала, а розмір
завищила. Квадратична помилка каже, що це однакова біда: 5² = 25
в обох випадках. А тепер подивись на IoU — метрику, заради якої все й робиться.
IoU — це площа перетину, поділена на площу обʼєднання (тема 23). Наша передбачена рамка накриває істинну цілком, тож перетин — це вся істинна рамка, а обʼєднання — вся передбачена. Для рамки 20 на 20, завищеної до 25 на 25:
Для рамки 200 на 200, завищеної до 205 на 205, той самий рахунок дає
40 000 ÷ 42 025 = 0.9518. Похибка в пікселях однакова, а
втрачена частка перекриття — 36 % проти 4.8 %, тобто в сім із
половиною разів більша на малій рамці.
| сторона рамки | (Δw)² | (Δ√w)² | IoU при похибці 5 px по кожній стороні |
|---|---|---|---|
| 20 px | 25.0 | 0.27864 | 0.6400 |
| 50 px | 25.0 | 0.11912 | 0.8264 |
| 100 px | 25.0 | 0.06098 | 0.9070 |
| 200 px | 25.0 | 0.03087 | 0.9518 |
Читаємо середню колонку проти правої. Без кореня штраф на рамці 20 пікселів і
на рамці 200 пікселів однаковий — відношення рівно 1 : 1. А шкода
різна: у першому випадку IoU падає до 0.64, у другому лишається
0.95, тобто помилки практично не видно. З коренем відношення штрафів стає
9.03 : 1 — маленька рамка кричить у девʼять разів голосніше за велику,
приблизно так само, як кричить IoU.
Що робить корінь зі штрафом
Перемикач обирає, що саме регресує мережа: сиру ширину чи корінь із неї. Повзунок задає похибку в пікселях. Стовпчики показують штраф для рамок різного розміру, зведений до найменшої.
ВпевненістьВпевненість — це не ймовірність класу
Пʼяте число рамки зветься впевненістю (confidence), і його зміст у YOLO незвичний. Це не «ймовірність, що тут кіт». Це добуток двох речей:
Перший множник — «чи тут узагалі щось є». Другий — «наскільки добре я поставив рамку». Перемножені, вони дають одне число, яке відповідає на питання «наскільки корисне це передбачення». Якщо предмета немає, впевненість має бути нулем. Якщо предмет є, але рамка поставлена криво, впевненість має бути невеликою — навіть попри те, що предмет справді там.
Найдивніше тут — що ціллю для навчання є сам IoU. Не одиниця, а фактичне значення перекриття, яке ця рамка щойно дала. Мережу вчать передбачати власну якість: «ось моя рамка, і ось наскільки, на мою думку, вона влучна».
оцінка = впевненість × P(клас | предмет). Саме ця оцінка йде
в NMS і в криву
точність-повнота. Розділення не косметичне: клітинка, яка впевнена, що предмет
є, але не знає, кіт це чи собака, поводиться інакше, ніж клітинка, яка нічого
не бачить.
Впевненість як добуток двох речей
Ліворуч — істинна рамка (бірюзова) і рамка, яку видала мережа (малинова); повзунок зсуває передбачену рамку, і IoU перераховується по площах. Другий повзунок задає, наскільки мережа впевнена, що предмет тут узагалі є. Праворуч від рамок — прямокутник, чия ширина дорівнює P(предмет), висота — IoU, а площа і є впевненість.
ВтратаФункція втрати та її ваги
Тепер зберемо все в одну втрату. Вона складається з чотирьох доданків, і головне в ній — де саме кожен доданок рахується. Не по всій сітці, а кожен по своїй частині.
| доданок | де рахується | вага |
|---|---|---|
| x, y | тільки у відповідальної рамки | λ_coord |
| √w, √h | тільки у відповідальної рамки | λ_coord |
| впевненість, коли предмет є | тільки у відповідальної рамки | 1 |
| впевненість, коли предмета немає | у всіх інших рамок | λ_noobj |
| класи | у клітинок із предметом | 1 |
Усі доданки — квадрати різниць, підсумовані. Це найпростіша можлива втрата, і автори прямо визнають, що обрали її за легкість оптимізації, а не за правильність: вона однаково важить помилку локалізації й помилку класифікації, хоча оптимізуємо ми зовсім не це.
Звідки взялися дві дивні ваги
Порахуймо, скільки в сітці рамок і скільки з них про щось звітують. У нашій мережі 8 × 8 клітинок по 2 рамки — це 128 рамок на сцену. Предметів у сцені один-три, тобто відповідальних рамок у середньому 2.05. Решта 126 — фон, який має сказати «мене немає».
Якщо всі доданки важать однаково, сума по 126 фонових рамках просто задавить суму по двох відповідальних. Це не здогад: розкладку втрати можна порахувати до будь-якого навчання — узяти свіжу, щойно ініціалізовану мережу, прогнати крізь неї партію з 32 сцен і скласти кожен доданок окремо. Ось що виходить:
| ваги | координати | предмет є | фон | класи | разом |
|---|---|---|---|---|---|
| 1 і 1 | 0.485 | 0.110 | 25.915 | 1.551 | 28.062 |
| частки | 1.7 % | 0.4 % | 92.3 % | 5.5 % | 100 % |
| 5 і 0.5 | 2.426 | 0.110 | 12.958 | 1.551 | 17.045 |
| частки | 14.2 % | 0.6 % | 76.0 % | 9.1 % | 100 % |
З рівними вагами 92.3 % усієї втрати — це крик фону. Градієнт майже
цілком складається з вимоги «мовчи», а на координати припадає 1.7 %.
Мережі буквально вигідніше не побачити нічого, ніж навчитися ставити рамку.
Канонічні ваги першої YOLO — λ_coord = 5 і
λ_noobj = 0.5 — піднімають координати вдесятеро відносно фону: частка
координат росте до 14.2 %, частка фону падає до 76.0 %.
mAP@0.5 = 0.9761, рівні — 0.9714. Різниця
0.0047, а розкид усередині однієї настройки сягає 0.0141 — тобто
різниця тоне в шумі, і на двох зернах із трьох канонічні ваги виграли, а на
третьому програли. На нашому датасеті ваги не вирішують нічого. Наші
сцени занадто легкі: три великі предмети на порожньому полотні, мережа
виїжджає й із поганим балансом. Не переноси цей результат на справжні дані —
переноси метод: перш ніж вірити в гіперпараметр, поміряй його на трьох зернах
і порівняй виграш із розкидом.
Ваги втрати
Два повзунки міняють ваги. Стовпчики — фактичні складники втрати свіжої мережі на нашій партії; числа під ними — те саме у відсотках. Дві точки, які ми справді навчили, підписані заміряним mAP.
МежаОбмеження сітки: чого YOLO не бачить у принципі
Настав час чесної частини. Правило «клітинка відповідає за предмет, чий центр у ній» має зворотний бік: клітинка відповідає щонайбільше за один предмет. Якщо центри двох предметів упали в одну клітинку, другий предмет просто не потрапляє в ціль. Мережа ніколи не отримає за нього градієнта й ніколи не навчиться його бачити. Це не поганий поріг, не брак даних і не помилка навчання — це властивість постановки.
Порахуємо, скільки це коштує. Замір іде по тисячі сцен двох видів — рідкі (один-три великі предмети) і щільні (чотири-шість дрібніших); для кожної сцени беремо істинні рамки, розкладаємо їх по клітинках і дивимось, скільки предметів не дісталось власної клітинки.
| сітка S | клітинка | рідкі: втрачено | щільні: втрачено | щільні: зіпсовано сцен |
|---|---|---|---|---|
| 4 × 4 | 16.0 px | 2.45 % | 8.95 % | 39.2 % |
| 7 × 7 | 9.1 px | 0.45 % | 1.71 % | 8.3 % |
| 8 × 8 | 8.0 px | 0.30 % | 1.30 % | 6.4 % |
| 13 × 13 | 4.9 px | 0.10 % | 0.12 % | 0.6 % |
Головне число тут — 8.95 %. На сітці 4 × 4 щільна сцена втрачає кожен одинадцятий предмет, а зіпсовано виявляється 39.2 % усіх сцен: у чотирьох із десяти кадрів мережа фізично не може знайти все. Дрібніша сітка лікує це швидко: на 13 × 13 втрата падає до 0.12 %.
Наші сцени рідкі, і на них ефект малий — це теж треба сказати прямо. Але справжня фотографія так себе не поводить. Чого чекати на щільній сцені, можна порахувати не генеруючи її. Задача та сама, що у відомому «парадоксі днів народження», і механізм у неї простий до банальності: клітинки закінчуються швидше, ніж здається.
Розкладаймо предмети по клітинках по одному. Нехай клітинок
n = S², а предметів k.
Він падає куди завгодно — вільні всі n клітинок із
n. Імовірність, що конфлікту ще немає: n ÷ n = 1.
Одна клітинка вже зайнята, вільних n − 1. Імовірність, що
він не влучив у зайняту: (n − 1) ÷ n.
Перед ним зайнято i − 1 клітинок, вільних
n − i + 1. Його частка — (n − i + 1) ÷ n, і вона
менша за попередню: кожен покладений предмет забирає клітинку в
наступного.
Щоб конфлікту не було жодного разу, мусять справдитись усі
k умов підряд. Кожну наступну ми вже рахували в припущенні, що
попередні справдились (саме тому вільних клітинок стає менше), а ймовірності
такого ланцюжка перемножуються. Отже ймовірність чистої сцени — це
добуток спадних часток, а ймовірність зіткнення — те, що лишилось до
одиниці.
Порахуймо руками найменший випадок — три предмети на сітці 4 × 4, тобто
n = 16, k = 3:
Це перше число таблиці нижче. І тут видно, чому далі все так швидко
псується: множники не просто менші за одиницю — вони спадають. При
n = 49 і двадцяти предметах останній множник дорівнює
30 ÷ 49 = 0.61, тобто двадцятий предмет має 39 % шансів
зіткнутись сам по собі, ще до того, як ми врахували перші девʼятнадцять. Двадцять
таких множників перемножуються — і від чистої сцени лишається один випадок зі
ста.
| предметів | S = 4 (16 кл.) | S = 7 (49) | S = 8 (64) | S = 13 (169) |
|---|---|---|---|---|
| 3 | 18.0 % | 6.0 % | 4.6 % | 1.8 % |
| 5 | 50.0 % | 19.0 % | 14.8 % | 5.8 % |
| 10 | 97.4 % | 62.6 % | 52.3 % | 23.8 % |
| 20 | 100.0 % | 98.9 % | 96.4 % | 69.0 % |
Ось відповідь на питання, чому першу YOLO лаяли за дрібні предмети. На фотографії з двома десятками обʼєктів сітка 7 × 7 майже напевно щось загубить — 98.9 % імовірності зіткнення. У статті це визнано прямо: модель погано працює з дрібними предметами, що зʼявляються групами, і як приклад названо зграю птахів.
S = 7, 20 предметів він дає 70.3 % зіпсованих
сцен замість 98.9 % — постав повзунки фігури нижче саме так і перевір. Обидва
числа правильні, просто вони про різні сцени: 98.9 % — це верхня межа
(найгірший, зовсім невпорядкований випадок), а 70.3 % — те, що виходить, коли
предмети займають місце. Напрямок обидві оцінки показують однаковий, і саме він
тут головний: чим більше предметів і чим грубша сітка, тим більше їх зникає ще
до навчання.
Конфлікт у клітинці
Головний замір теми. Ліворуч — одна сцена: предмети, чиї центри зіткнулись, перекреслені. Праворуч — стовпчики втрати по всіх сітках, порахованої тут же на 300 сценах. Другий повзунок міняє щільність сцени.
Дві рамкиДві рамки на клітинку — і навіщо
Якщо клітинка однаково відповідає за один предмет, навіщо їй дві рамки? Не для двох предметів — для спеціалізації за формою.
Під час навчання відповідальною призначається та з двох рамок, чий IoU з істинною рамкою більший саме зараз. Друга в цьому кроці не отримує градієнта по координатах узагалі. Через сотні кроків виходить розподіл праці: одна рамка поступово стає кращою на високих і вузьких предметах, друга — на широких і низьких. У статті це названо своїм іменем: кожен передбачувач стає кращим на певних розмірах, співвідношеннях сторін і класах, і від цього росте повнота.
Ціна теж є, і вона видна в арифметиці розділу 03: кожна додаткова рамка додає пʼять чисел до глибини виходу для кожної клітинки. Дві рамки на сітці 7 × 7 дають 98 рамок на зображення — саме стільки передбачала перша YOLO. Для порівняння, двоетапна схема розглядала кілька тисяч місць.
ШвидкістьШвидкість: наслідок постановки
Тепер про те, за що YOLO запамʼятали. Одноетапна схема коштує один прохід мережі. Класична R-CNN проганяла мережу по кожній кандидат-області окремо. Порівняймо це чесно, у двох варіантах.
Варіант перший — однакова ємність. Беремо наше тіло мережі й міряємо його двічі: один прохід по цілій сцені 64 × 64 проти ста проходів по вирізаних кандидат-областях 32 × 32. Той самий код, ті самі ваги, різна лише постановка.
| схема | проходів по вмісту | час | відношення |
|---|---|---|---|
| одноетапна | 1 | 1.43 мс | 1× |
| по 100 кандидат-областях | 100 | 26.4 мс | 18× |
Варіант другий — проти справжнього Faster R-CNN. Будуємо
fasterrcnn_resnet50_fpn без ваг і міряємо його прохід на тому самому
вході: 177 мс проти наших 1.43 мс, тобто 124 рази. Але тут
треба сказати вголос: у цій моделі 41 362 531 параметр проти наших 61 421, тобто
в 673 рази більше. Більша частина розриву — це розмір моделі, а не
постановка. Внесок самої постановки — це перша таблиця, вісімнадцять разів.
Швидша, але не краща
Ось те, чого не буває в рекламних графіках. Перша YOLO працювала на 45 кадрах за секунду й давала 63.4 mAP на Pascal VOC 2007. Faster R-CNN із тілом VGG-16 на тих самих даних давав 73.2 mAP — але на 7 кадрах за секунду. Полегшена Fast YOLO розганялась до 155 кадрів і падала до 52.7 mAP. Це числа з оригінальної статті, наведені як цитата, а не наш замір.
| модель (з літератури) | mAP, VOC 2007 | кадрів за секунду |
|---|---|---|
| Fast YOLO | 52.7 | 155 |
| YOLO | 63.4 | 45 |
| Fast R-CNN | 70.0 | 0.5 |
| Faster R-CNN VGG-16 | 73.2 | 7 |
Розрив у майже десять пунктів mAP — це не дрібниця. І він не рівномірний: розбір помилок у тій самій статті показав, що помилок локалізації в YOLO більше, ніж усіх інших її помилок разом, тоді як Fast R-CNN промахується рамкою значно рідше. Дзеркально: у Fast R-CNN 13.6 % найкращих передбачень — це фон, у якому взагалі немає предмета, і за цим показником він приблизно втричі гірший за YOLO.
Дві моделі помиляються по-різному, і це не риторична фігура: у статті їх поєднали — YOLO прибирала фонові спрацювання Fast R-CNN — і 71.8 mAP перетворилось на 75.0. Одна модель відповідала за точність рамки, друга — за відсутність привидів.
Один прохід проти багатьох
Повзунок задає, скільки кандидат-областей розглядає двоетапна схема. Час порахований із наших замірів: 1.43 мс на прохід по цілій сцені й 0.264 мс на одну кандидат-область тим самим тілом.
РозвитокЯк YOLO розвивалась: що саме змінили
Далі — короткий огляд без наших замірів. Важливо не «стало краще», а що конкретно замінили.
| версія | що саме змінилось |
|---|---|
| v1 | сітка 7 × 7, дві рамки на клітинку, класи одні на клітинку, координати з повнозвʼязних шарів, втрата — сума квадратів |
| v2 | прибрано повнозвʼязні шари, введено якорі; вхід 416 замість 448, щоб сітка вийшла 13 × 13 із непарним центром; форми якорів підібрані k-середніми по даних, а не руками; клас і обʼєктність передбачаються для кожного якоря окремо |
| v3 | багатомасштабність: передбачення на трьох рівнях різної роздільності, девʼять якорів розподілено по три на рівень; softmax по класах замінено на незалежні логістичні класифікатори, тобто предмет може мати кілька міток одночасно |
| v4, v5 | інженерія без зміни постановки: інше тіло, інша шия, важка аугментація (зокрема мозаїка з чотирьох зображень), нові прийоми навчання |
| v6-v8 | anchor-free: якорі прибрано зовсім, клітинка знову передбачає рамку прямо; голова розділена на дві гілки — окрему для рамки й окрему для класів; замість фіксованого правила «центр у клітинці» — навчене призначення відповідальності |
Два числа, які варто зіставити
Перехід до якорів у другій версії — рідкісний випадок, коли автори чесно показали, що метрика впала. Без якорів модель давала 69.5 mAP при повноті 81 %; із якорями — 69.2 mAP при повноті 88 %. Точність трохи гірша, зате знайдено на сім пунктів більше предметів, і саме цей запас дозволив рости далі. Числа цитовані зі статті про YOLOv2.
А ось замір, який можна зробити самому й офлайн. Бібліотека
ultralytics дозволяє зібрати архітектуру YOLOv8 без жодних ваг.
Подивимось на її голову й порівняймо з першою версією:
| YOLOv1 | YOLOv8n (зібрано офлайн) | |
|---|---|---|
| масштабів | 1 | 3 |
| позицій сітки | 49 | 8400 |
| чисел на позицію | 30 | 144 |
| чисел разом | 1470 | 1 209 600 |
Але цікавіше не розмір, а з чого складаються ці 144 числа: 80 класів плюс 4 × 16. Ані сліду впевненості. Окремого числа «тут є предмет» у YOLOv8 немає взагалі — його роль перебрала найбільша ймовірність класу. А четвірка помножена на 16 означає, що кожна сторона рамки передбачається не одним числом, а розподілом по шістнадцяти позиціях, з якого потім береться середнє. Голова складається з двох окремих гілок: одна рахує рамку, друга — класи. Усі ці числа видно з самої конфігурації моделі — навчені ваги для такого підрахунку не потрібні, досить зібрати архітектуру й подивитись на форму останніх згорток.
СпадокЩо з YOLO лишилось у сучасних детекторах
Від першої версії не лишилось майже нічого з деталей: ані сітки 7 × 7, ані кореня з ширини, ані двох ваг, ані спільних класів на клітинку. Лишилось три речі, і вони визначають вигляд усіх швидких детекторів сьогодні.
- Одноетапність. Немає окремого механізму кандидат-областей. Мережа дивиться на зображення один раз і одразу видає всі рамки. RetinaNet, SSD, FCOS, уся лінія YOLO — усі влаштовані так.
- Щільна голова. Передбачення робиться в кожній позиції карти ознак однією й тією самою згорткою 1×1. Позицій тепер тисячі, а не десятки, але принцип не змінився: однакова голова, застосована скрізь.
- Наскрізне навчання. Одна втрата на всю мережу, від пікселів до рамок. Немає окремого етапу, який треба навчати першим і від якого залежать решта.
Це і є справжня спадщина YOLO — не швидкість, а те, що детекцію перестали збирати з двох задач.
ПідсумокПідсумок і місток далі
| ідея | у чому суть |
|---|---|
| Регресія за один прохід | вихід фіксованої форми S × S × (B·5+C); у нас 832 числа, у YOLOv1 — 1470 |
| Сітка як розподіл ролей | клітинка відповідає за предмет, чий центр у ній |
| Координати відносно клітинки | інакше згортка 1×1 мусила б знати, де вона |
| Корінь із розміру | штраф на рамці 20 px стає в 9.03 раза більший, ніж на 200 px |
| Впевненість | P(предмет) × IoU — мережа передбачає власну якість |
| Ваги втрати | без них фон важить 92.3 % суми; на нашому датасеті це, утім, не змінило mAP |
| Ціна сітки | на щільних сценах сітка 4 × 4 губить 8.95 % предметів назавжди |
Головне число, яке варто винести: 8.95 %. Не «YOLO гірша на дрібних
предметах», а «стільки предметів не існує для моделі ще до початку навчання». І
головна пара чисел: 1.43 мс проти 26.4 мс при однаковій
ємності — приблизно вісімнадцять-двадцять разів лише за те, що тіло проганяється
один раз замість ста.
Одноетапна ідея дала швидкість, але принесла проблему, якої у двоетапних детекторів не було. Двоетапна схема мала фільтр: перший етап відбирав кілька сотень місць, і серед них співвідношення «предмет проти фону» було ще стерпним. Одноетапна голова дивиться всюди, і фон її топить. У темі 23 ми вже дістали це число на наших сценах: 85.4 % клітинок — чистий фон. У нашій YOLO-подібній мережі з двома рамками на клітинку співвідношення ще різкіше: відповідальних рамок 2.05 зі 128, тобто 1.6 %.
Витягувати сигнал із такої суміші вагами λ_noobj — спосіб грубий:
ми бачили, що на легких даних він нічого не дає, а підібрати його на важких
доводиться наосліп. Наступна тема
береться саме за це: як переписати саму втрату так, щоб легкі фонові приклади
затихали автоматично, і як позбутися якорів, які YOLO встигла завести й
почати від них відмовлятись. Focal loss і anchor-free — це продовження історії,
яку ми щойно почали.