Пулінг і зменшення розмірності

Беремо максимум із чотирьох чисел і викидаємо три. Виглядає як найгрубіше спрощення в усій мережі — а насправді саме воно добудовує терпимість до зсуву, якої згортці бракувало.

У попередній темі ми зібрали згортковий шар: маленьке ядро ковзає по зображенню, ті самі ваги працюють у кожній точці, на виході — карта ознак. Мережа стала в рази меншою за повнозвʼязну й перестала вчити кожен піксель окремо. Але одна річ не змінилася зовсім: карта ознак завбільшки з саме зображення. І таких карт тепер не одна, а стільки, скільки ядер у шарі.

Ця тема — про третій прийом згорткової мережі. Перші два були в темах 06 і 07: локальність і спільні ваги. Третій зветься пулінг (pooling), і його майже завжди подають однією фразою: «беремо максимум у вікні, щоб чисел стало менше». Це правда, але це половина правди й найнудніша половина. Друга половина цікавіша, і вона відповідає на питання, яке тема 06 лишила відкритим: чому згорткова мережа, навчена на предметах по центру, все одно провалюється, коли предмет зсунули вбік.

Приклад той самий, що в усьому блоці: картинки 28×28 з фігурами, намальовані формулами. Класів тут три — коло, квадрат, ромб. Це свідомий вибір саме цієї теми: дослід про зсув нічого не втрачає від того, що фігур троє, зате всі числа лишаються дрібними й перевіряються руками. З трьох класів випливає й рубіж, з яким ми порівнюватимемо кожну точність нижче: випадкове вгадування = 1/3 ≈ 0.333. У темі 09 та сама конструкція працює на шести класах, і рубіж там інший — 1/6 ≈ 0.167; тому точності двох тем звіряють не між собою, а кожну зі своїм рубежем.

ПроблемаПроблема, що лишилася після згортки

Порахуємо, скільки чисел мережа тримає в памʼяті. Візьмімо не наші іграшкові 28×28, а звичайний вхід справжньої мережі: кольорове зображення 224×224. У ньому 224 × 224 × 3 = 150 528 чисел. Це десь 0.6 мегабайта, якщо кожне число займає чотири байти (звичайний float32).

Тепер перший згортковий шар. У реальних мережах у першому шарі десятки ядер; візьмімо 64 — так було в VGG і так лишилося в половині сучасних архітектур. Кожне ядро дає власну карту ознак того самого розміру, що вхід:

64 × 224 × 224 = 3 211 264 числа ≈ 12.8 МБ на одну картинку

Вхід був 0.6 МБ — після одного шару стало 12.8 МБ, у 21 раз більше. І це ще не все. Навчання йде пакетами: 32 картинки за раз — це вже 411 МБ на один шар. А шарів у мережі десятки, і всі проміжні карти доводиться тримати, поки не пройде зворотне поширення помилки: щоб порахувати градієнт ваг шару, потрібен його вхід.

Помножити 411 МБ на двадцять шарів не можна ніякою карткою. Отже, розмір карт має кудись дітися по дорозі — інакше мережа просто не поміститься.

Друга причина — обчислення. Згортка коштує приблизно «кількість вихідних клітинок × розмір ядра × кількість вхідних каналів»: зменшив карту вдвічі за кожною стороною — і наступний шар подешевшав учетверо. Третя причина найважливіша, але про неї в розділі 04.

Подивімось на нашу задачу, щоб числа були відчутні. Вхід — 28 × 28 = 784 числа. Перший згортковий шар із вісьмома ядрами дає 8 × 28 × 28 = 6272. Другий, з шістнадцятьма, дає 16 × 28 × 28 = 12 544. Далі карту треба розпрямити в один довгий вектор і подати в звичайний лінійний шар на три класи:

12 544 × 3 + 3 = 37 635 ваг лише в останньому шарі

У самих згорткових шарах ваг при цьому 80 і 1168 — разом 1248. Отже вся мережа важить 1248 + 37 635 = 38 883 ваги, і частку останнього шару видно прямим діленням:

37 635 / 38 883 = 0.968 → 97 % усіх ваг мережі

Знаменник тут — усі параметри цієї конкретної мережі: дві згортки плюс голова. Не «97 % чогось узагалі», а 97 % від 38 883. Тобто остання таблиця і є мережа, а згортки — дрібний додаток до неї. Ми пішли від повнозвʼязної мережі й повернулися до неї ж, тільки через задні двері.

Число вийшло таким великим з однієї причини: карту ніхто не зменшував. На вхід голови йдуть 12 544 числа — шістнадцять карт 28×28 у повний зріст. Щойно карту почнуть стискати, той самий дріб дасть інше: у розділі 09 голова схудне до 2355 ваг, і це вже 65 % мережі, а в темі 09, де карту стискають тричі поспіль і на вхід голови приходить 288 чисел, найбільший шар голови важить 74.7 %. Пропорція «голова важча за тіло» тримається завжди — а конкретний відсоток каже рівно одне: наскільки стиснули карту перед нею.

Запамʼятай пропорцію. Згорткові шари дешеві за параметрами й дорогі за памʼяттю. Розпрямлення в кінці — навпаки: памʼяті майже не займає, зате зʼїдає майже всі ваги. Обидві проблеми лікуються тим самим прийомом — зменшенням.

Куди дівається 97 %

Три однакові мережі, різниця лише в тому, скільки разів карту зменшили перед головою. Довжина смуги — усі ваги мережі в одному масштабі; колір ділить її на тіло й голову.

Відсоток рахується від довжини всієї смуги. Тіло однакове в усіх трьох — 1 248 ваг, воно не залежить від розміру карти. Міняється лише голова, бо в неї рівно стільки ваг, скільки чисел їй подали: 12 544 · 3 + 3, потім 3 136 · 3 + 3, потім 784 · 3 + 3. Тому 97 % — це не властивість згорткових мереж, а властивість нестиснутої карти.

ІдеяОдне число з вікна

Найпростіше, що можна зробити з картою, — розрізати її на однакові квадратики й від кожного лишити одне число. Квадратик 2×2 — і карта зменшилася вдвічі за кожною стороною, тобто вчетверо за кількістю чисел.

Яке саме число лишити? Розумних варіантів два:

Порахуймо руками. Ось шматок карти ознак 4×4 — просто шістнадцять чисел:

1 3 │ 2 0 4 6 │ 1 2 ──────┼────── 0 2 │ 8 5 1 1 │ 3 7

Максимум у кожній чверті: 6, 2, 2, 8. Середнє в кожній чверті: (1+3+4+6)/4 = 3.5; (2+0+1+2)/4 = 1.25; (0+2+1+1)/4 = 1.0; (8+5+3+7)/4 = 5.75. Із шістнадцяти чисел лишилося чотири. Ось і весь пулінг.

Формально це те саме ковзне вікно, яке ми будували в темі 04, і той самий stride, який тема 07 ввела як параметр згортки — але без ваг. Вікно розміром k рухається з кроком s, і розмір виходу рахується тією самою формулою, що для згортки:

розмір виходу = ⌊(розмір входу − k) / s⌋ + 1

Тут k — сторона вікна (майже завжди 2), s — крок (майже завжди теж 2), а кутові дужки ⌊ ⌋ означають «округлити вниз до цілого». Для входу 28 і вікна 2 з кроком 2: (28 − 2) / 2 + 1 = 14. Для входу 7: (7 − 2) / 2 = 2.5, округлюємо вниз до 2, додаємо 1 — виходить 3. Останній непарний стовпчик просто не потрапляє в жодне вікно і викидається мовчки. Це типове джерело подиву, коли форма тензора не збігається з очікуваною.

Ще одна деталь, яку легко проґавити: пулінг працює окремо в кожному каналі. Якщо на вхід прийшло 16 карт ознак, на виході теж буде 16 карт — просто менших. Канали між собою не змішуються, бо змішувати їх — робота згортки, а не пулінгу.

Пулінг по кроках

Вікно 2×2 з кроком 2 обходить карту зліва направо, згори вниз. Тисни «крок» і дивись, як заповнюється результат. Перемикач змінює правило вибору числа.

правило
крок0 / 16
у вікні—
чисел було64
заповнено0
Вікна не перекриваються: крок дорівнює стороні вікна. Тому кожне вхідне число потрапляє рівно в одне вихідне, і карта 8×8 стає 4×4 — учетверо менше чисел. Перемкни правило: картинка максимумів світліша, бо максимум ніколи не менший за середнє.

ПараметриУ пулінгу нуль параметрів

Тепер найважливіша технічна властивість, через яку пулінг так довго був безальтернативним: у нього немає чого вчити. Ані ваг, ані зсувів. Правило «візьми максимум» зашите намертво й однакове для всіх задач, усіх каналів і всіх картинок.

Порівняй із єдиною очевидною альтернативою — згорткою з кроком 2, яка зменшує карту так само:

Спосіб зменшити карту 8 каналів удвічіПараметрівМножень на клітинку виходу
nn.MaxPool2d(2)00
nn.AvgPool2d(2)00
nn.Conv2d(8, 8, 3, stride=2)58472

584 — це 8 вихідних каналів × 8 вхідних × 9 клітинок ядра, плюс 8 зсувів. Пулінг же робить три порівняння на клітинку й не множить нічого. Різниця в обчисленнях — приблизно двадцятикратна, і на слабкому залізі це відчутно.

Із «нуля параметрів» випливає ще одна річ, яка збиває новачків. Пулінг не є шаром без градієнта. Градієнт крізь нього тече, просто ваг для оновлення немає. У максимумі градієнт потрапляє лише в те число, яке перемогло, а трьом іншим дістається нуль: вони на результат не вплинули, отже й на помилку не вплинули. У середньому навпаки — градієнт ділиться на чотири рівні частини.

Порахуймо це на вікні 0, 0, 9, 0. Хай згори, від наступного шару, прийшов градієнт 1.0 — тобто «вихід цього вікна треба змінити ось настільки». Далі його розкладають по чотирьох вхідних числах:

max : 0, 0, 1.0, 0 ← уся зміна лягає на девʼятку avg : 0.25, 0.25, 0.25, 0.25 ← порівну на всі, включно з нулями

В обох випадках роздане в сумі дорівнює тому, що прийшло: 0 + 0 + 1.0 + 0 = 1.0 і 4 × 0.25 = 1.0. Нічого не губиться й не додається — правило лише вирішує, кому дістанеться сигнал. Звідси наслідок для навчання: під максимумом вчиться той піксель, що переміг, під середнім — усе вікно потроху.

Чому це важливо для розуміння мережі. Пулінг зменшує обчислення, не додаючи ємності. Кожен інший спосіб зменшити карту або додає параметри (згортка з кроком), або втрачає більше інформації (просто викинути кожен другий піксель). Пулінг — рідкісний випадок, коли за економію не платять параметрами. Платять іншим, і про це розділ 05.

ЗсувГоловна користь: терпимість до зсуву

Тема 06 закінчилася чесним і незручним числом. Повнозвʼязна мережа, навчена на фігурах по центру, на зсунутих фігурах дала 0.360 — при трьох класах це рівно рівень вгадування, тобто вона не вміє нічого. Згорткова мережа з утринадцятеро меншою кількістю параметрів дала 0.607: помітно краще, але й близько не одиниця. Висновок звучав так: згортка дає часткову терпимість до зсуву, а не повну незалежність від нього.

Чому часткову? Ядро справді знаходить ознаку де завгодно — воно ж ковзає по всій картинці. Але результат воно кладе рівно туди, де знайшло. Зсунувся предмет на три пікселі — і вся карта ознак зсунулася на три пікселі, а розпрямляючи її в вектор, ми знову отримали інші числа на інших позиціях. Останній лінійний шар бачить чужий вектор і помиляється.

Ось тут і працює пулінг. Максимум у вікні 2×2 не змінюється, поки ознака рухається всередині цього вікна. Ознака була в лівому верхньому куті вікна, стала в правому нижньому — максимум той самий. Мережа отримала на цьому рівні повну байдужість до зсуву на один піксель. Склади три таких шари — і байдужість поширюється на вісім пікселів.

крок 1 · вікно

Хай у вікні 2×2 стоять числа 0, 0, 9, 0 — ознака знайшлася в третій клітинці. Максимум = 9.

крок 2 · зсув усередині вікна

Предмет зсунувся на піксель, і в вікні стало 0, 0, 0, 9. Максимум досі 9. Вихід не змінився взагалі.

крок 3 · зсув за межу вікна

Ще один піксель — і девʼятка перескочила в сусіднє вікно. Тепер у першому вікні максимум 0, у сусідньому 9. Вихід змінився різко, стрибком.

висновок

Пулінг дає не гладку стійкість, а сходинкову: усередині вікна — ідеальна, на межі вікна — розрив. Це і є межа терпимості, і вона дорівнює розміру вікна, помноженому на добуток усіх попередніх кроків.

Куди дівається зсув

Повзунок рухає світлу пляму по карті ознак. Унизу — вихід пулінгу й лічильник клітинок, що змінилися порівняно з нульовим зсувом.

правило
клітинок змінилось0 / 16
вихід вікна з ознакою1.00
Зсув на 1 не міняє нічого, зсув на 2 міняє все. Це і є сходинкова природа терпимості: пулінг прощає рух усередині вікна й не прощає перехід через його межу. Перемикач правила цього не змінює — змінює лише силу сигналу: максимум віддає 1.00, середнє 0.25. Обережно: ознака тут завширшки в один піксель. Розмита ознака дістає й сусідні вікна, і тоді точна сходинка стає приблизною.

Тепер найголовніше: чи справді це працює на живій мережі. Ми навчили дві згорткові мережі однакової глибини — по два згорткові шари, ті самі 8 і 16 ядер, те саме зерно випадковості, ті самі 12 епох. Різниця одна: перша після кожної згортки має MaxPool2d(2), друга не має нічого. Обидві вчилися на фігурах майже по центру (зсув ±1 піксель) і перевірялися на фігурах, зсунутих усе далі.

МережаПараметрівЗсув ±1Зсув ±2Зсув ±3Зсув ±6
без пулінгу38 8831.0000.8850.6170.313
з MaxPool2d(2)3 6031.0000.9820.8630.457

Читаємо результат. На тих картинках, які мережі бачили під час навчання, обидві дають рівно 1.000 — задача проста, різниці немає. Далі починається розходження. На зсуві три пікселі мережа з пулінгом дає 0.863, без нього — 0.617: плюс 0.246. На зсуві шість — 0.457 проти 0.313, тобто плюс 0.144, і це при тому, що мережа з пулінгом має в 10.8 раза менше параметрів.

Отже, відповідь на питання теми — так, пулінг справді додає терпимість до зсуву, і додає багато. Але друга половина відповіді така сама важлива: він не робить мережу інваріантною. На зсуві шість пікселів навіть із пулінгом лишається 0.457 при рівні вгадування 0.333. Три шари 2×2 прощають вісім пікселів у теорії, але наша мережа має лише два таких шари, тобто чотири пікселі — далі пляма ознаки виїжджає з вікна, і терпимість закінчується.

Число з теми 06 тут не збігається — і це нормально. Там згорткова мережа на зсуві ±6 давала 0.607, у нас без пулінгу виходить 0.313. Мережі різні: інша ширина шарів, інша голова, інший датасет-зразок. Порівнювати між темами абсолютні числа не можна — можна порівнювати пару, зміряну в одних і тих самих умовах. Наша пара — 0.313 і 0.457, і вона відрізняється рівно на пулінг.

Точність проти зсуву

Дві криві — з пулінгом і без. Повзунок обирає, наскільки далеко зсунуто предмет; праворуч видно, як саме виглядають фігури при цьому зсуві.

з пулінгом—
без пулінгу—
рівень вгадування0.333
Обидві мережі бачили тільки фігури майже по центру. Праворуч — три класи при вибраному зсуві: саме такі картинки подавали на перевірку. Числа взяті з навчання на 1200 прикладах при зафіксованому зерні — тому замір повторюваний.

ЦінаЧим ми за це платимо

Пулінг не безкоштовний, і його ціна — не «трохи розмиття». Він безповоротно викидає точне положення. Після вікна 2×2 ти знаєш, що ознака була десь у цьому квадратику, і більше нічого. Три шари пулінгу поспіль — і карта 28×28 перетворилася на 3×3.

784 можливих положення → 9 клітинок; точність координати падає з 1 пікселя приблизно до 9

Для класифікації це не втрата, а майже подарунок. Питання «що на картинці» відповіді про координати не потребує взагалі: якщо там квадрат, то він квадрат і в лівому куті, і в правому. Викинувши координати, ми викинули те, що заважає.

А тепер уяви іншу задачу. Тема 02 розкладала задачі зору за формою відповіді, і серед них були дві, де координати — це і є відповідь:

Саме тому мережі для цих задач влаштовані інакше. Вони або зменшують карту не так глибоко, або зменшують, а потім відновлюють розмір назад, ще й підглядаючи в ранні шари, де положення ще не втрачене. Як це роблять — теми блоків 5 і 6; тут важливо лише запамʼятати причину. Пулінг вигідний рівно настільки, наскільки задачі байдужі координати.

Є й друга, тонша ціна. Терпимість, яку дає пулінг, сходинкова — а це означає, що відповідь мережі може стрибнути від зсуву на один-єдиний піксель, якщо цей піксель випав саме на межу вікна. Мережа, стійка в середньому, у конкретній точці буває крихкою — і це варто памʼятати, коли модель дивно поводиться на майже однакових прикладах.

Max чи avgМаксимум чи середнє

Правило вибору просте:

Максимум відповідає на питання «чи є ця ознака в околі взагалі». Середнє — на питання «скільки її тут загалом».

Звідси все й випливає. Ознаки, які шукає згортка, зазвичай рідкісні: край, кут, штрих певного нахилу. У вікні 2×2 така ознака або є в одній клітинці, або її немає. Максимум цю одну клітинку зберігає повністю. Середнє ділить її на чотири — і сигнал слабшає рівно вчетверо щоразу.

Порахуємо. Хай у вікні три нулі й одна сімка — сильний відгук на край.

max(0, 0, 7, 0) = 7 ← сигнал цілий avg(0, 0, 7, 0) = 1.75 ← сигнал поділено на 4

Три шари підряд — і одиничний сплеск, що пройшов через середнє, зменшився в 4 × 4 × 4 = 64 рази. Він просто потоне в тому, що поруч. Тому в класифікаційних мережах історично переміг максимум.

Але це не робить середнє гіршим завжди. Там, де важлива не наявність, а кількість — скільки в цьому клапті волокон, наскільки густа текстура, яка частка площі зайнята — максимум усе зіпсує: він насититься на першому ж яскравому пікселі й перестане відрізняти рідке від густого. Числа на це є, і вони в розділі 10.

А ще середнє глушить шум: середнє чотирьох незалежних випадкових величин має вдвічі менший розкид, ніж кожна з них окремо. Максимум натомість шум підсилює — із чотирьох випадкових чисел він завжди бере найбільше й систематично зміщує карту вгору.

Максимум проти середнього

Три різні входи й два правила. Дивись не на картинку, а на два числа праворуч: скільки сигналу дійшло до виходу і скільки шуму разом із ним.

що на вході
правило
сигнал дійшов—
фон навколо—
Жодне правило не виграє скрізь. На сплеску максимум зберігає всі 100 % сигналу, а середнє лишає чверть. На двох текстурах — 3 % площі проти 23 % — максимум уже за один шар підтягнув рідку до 0.13, а густу до 0.66; ще шар, і обидві стануть однаково білими. Середнє показує ті самі 0.03 і 0.23, тобто густину зберігає точно. Шум максимум підсилює, середнє глушить.

На нашій задачі ми навчили дві однакові мережі, замінивши лише MaxPool2d(2) на AvgPool2d(2):

МережаПараметрівЗсув ±1Зсув ±3Зсув ±6
MaxPool2d(2)3 6031.0000.8630.457
AvgPool2d(2)3 6031.0000.7970.362

Параметрів порівну — обидва правила їх не мають. Максимум виграє скрізь, де предмет зсунуто: 0.863 проти 0.797 на трьох пікселях і 0.457 проти 0.362 на шести. Перевага невелика, але стабільна, і механізм її ми вже бачили в розділі 04: максимум не міняється, поки ознака рухається в межах вікна, а середнє міняється щоразу, бо в нього входять усі чотири числа. Терпимість до зсуву — властивість саме максимуму.

Не роби з цього правила «max завжди». На нашій задачі фігури — це суцільні білі плями на чорному, тобто наявність важить більше за кількість. Змінилася б задача — змінився б і висновок; розділ 10 показує, у який саме бік.

Поле зоруРецептивне поле росте вдвічі дешевше

Тема 07 ввела поняття рецептивного поля (receptive field) — це та ділянка вхідного зображення, від якої залежить одне число в карті ознак. Для ядра 3×3 у першому шарі поле дорівнює 3×3 пікселям: більше нейрон не бачить нічого.

Складати згортки одну за одною — спосіб повільний. Кожне наступне ядро 3×3 додає до сторони поля рівно 2 пікселі. Три згортки поспіль дають поле 7×7, десять згорток — 21×21. Щоб «побачити» предмет розміром 100 пікселів, знадобилося б півсотні шарів.

Пулінг ламає цю арифметику. Після зменшення вдвічі один піксель карти відповідає двом пікселям входу — і наступне ядро 3×3 накриває вже не три вхідні пікселі, а шість. Ще один пулінг — і дванадцять. Рецептивне поле починає рости не додаванням, а множенням.

Порахуймо наскрізь на стосі з трьох блоків «згортка 3×3 + пулінг 2×2». Уводимо дві величини: RF — сторона рецептивного поля в пікселях входу, і J — «крок» (jump), тобто скільки вхідних пікселів відповідає одному кроку по карті. На початку RF = 1, J = 1.

згортка 3×3 : RF = RF + (3 − 1) × J J лишається пулінг 2×2 : RF = RF + (2 − 1) × J J = J × 2
КрокКарта: канали × сторонаЧисел у картіRFJ
вхід1 × 28 × 2878411
згортка 1 · 8 ядер8 × 28 × 286 27231
пулінг 18 × 14 × 141 56842
згортка 2 · 16 ядер16 × 14 × 143 13682
пулінг 216 × 7 × 7784104
згортка 3 · 32 ядра32 × 7 × 71 568184
пулінг 332 × 3 × 3288228

Стос тут той самий, який збиратиме тема 09: канали ростуть 8 → 16 → 32, сторона падає 28 → 14 → 7 → 3.

Після трьох блоків одне число карти залежить від квадрата 22×22 пікселі — тобто майже від усього зображення 28×28. Ті самі три згортки без пулінгу дали б поле 7×7, тобто 49 пікселів площі проти 484 — майже вдесятеро менше. І при цьому чисел у карті було б 25 088 (32 × 28 × 28) замість 288.

Ось чому пулінг не просто «економія». Він одночасно зменшує памʼять і збільшує поле зору. Обидва ефекти — з однієї причини: після зменшення кожен крок по карті означає більший стрибок по зображенню.

Форма наскрізь

Повзунок веде по шарах стосу. Ліворуч видно, який квадрат входу «бачить» одне число карти; праворуч — розмір карти й скільки в ній чисел. Перемикач прибирає пулінг зі стосу.

стос
карта28 × 28
чисел784
рецептивне поле1 × 1
частка кадру0.1 %
Той самий стос, різниця лише в пулінгу. З ним поле доростає до 22 пікселів, а карта стискається до 3×3. Без нього поле зупиняється на 7 пікселях — мережа так і не побачить фігуру цілком, зате тягтиме 25 088 чисел до самого кінця.

КрокЗгортка з кроком замість пулінгу

А тепер частина, без якої тема застаріє. Від пулінгу поступово відмовляються. Мережі 2012–2015 років ставили MaxPool після кожного блоку не думаючи; сучасні часто не мають жодного, крім одного наприкінці. Замість нього — звичайна згортка з stride=2.

Логіка проста. Пулінг вирішує, що лишити, за жорстким правилом, придуманим людиною. Згортка з кроком вирішує це вагами, які вчаться. Якщо для задачі корисно брати максимум — мережа наблизить максимум сама; якщо корисно середнє — зробить середнє (це буквально згортка з однаковими вагами 0.25); якщо корисно щось третє, чого ніхто не придумав, — зробить і його. Зменшення перестає бути захардкодженим значенням і стає частиною моделі.

Другий довід — швидкість. Коли крок згорнуто в саму згортку, вона рахує відгук не в кожній точці, а в кожній другій: учетверо менше роботи. Схема «згортка на повній карті, потім пулінг» рахує все, а потім три чверті викидає.

Ми навчили ще дві мережі. Перша — ті самі два згорткові шари, ті самі 8 і 16 ядер, але замість MaxPool2d(2) стоїть stride=2 усередині самої згортки. Параметрів при цьому не змінюється взагалі: крок не додає ваг, він лише каже, де їх застосовувати. Друга — варіант, який частіше й мають на увазі: згортка лишається звичайною, а зменшує окремий згортковий шар із кроком, і оцей уже коштує ваг.

Щоб порівнювати обчислення чесно, беремо не секунди (вони залежать від того, чим ще зайнята машина), а кількість множень на одну картинку — це число рахується точно й у тебе вийде таке саме.

МережаПараметрівМножень на картинкуЗсув ±3Зсув ±6
згортка + MaxPool2d(2)3 603284 5920.8630.457
крок у самій згортці3 60372 9120.5500.267
окремий шар-зменшувач6 507510 3840.5600.295

Результат вийшов не той, якого чекаєш після абзацу про «сучасні мережі так роблять», і ховати його не будемо. На нашій задачі згортка з кроком програє пулінгу за терпимістю до зсуву, і програє помітно: 0.550 проти 0.863 на зсуві три пікселі. Зате вона в 3.9 раза дешевша за обчисленнями. Окремий шар-зменшувач додав 2904 ваги, став найдорожчим із трьох — і зсув витримав так само погано, як простий крок.

Чому так? Максимум дає терпимість задарма й одразу, самою своєю формулою. Згортка з кроком мусить цю терпимість вивчити, а вивчити її можна лише з даних, де зсув є. Наші мережі вчилися на фігурах майже по центру — звідки їм узяти, що зсув треба прощати? Пулінг цього знання не потребує, бо воно зашите в правило.

Звідси й практичний висновок. Сучасні мережі справді часто обходяться без пулінгу — але вони навчені на мільйонах зображень із важкою аугментацією (це тема 10), де зсуви, повороти й масштаби подані явно. На малих даних без аугментації жорстке правило пулінгу все ще виграє. «Від пулінгу відмовляються» — це твердження про великі мережі на великих даних, а не універсальна порада.

Пулінг проти згортки з кроком

Три способи зменшити карту вдвічі. Схема показує, що саме змінюється в стосі, табло — чим це обійшлося.

чим зменшуємо
параметрів—
множень—
зсув ±3—
зсув ±6—
Числа з реального навчання на 1200 прикладах, 12 епох, однакове зерно. Множення пораховані точно, а не заміряні секундоміром: секунди залежать від того, чим ще зайнята машина, а множення — ні. Найдешевший спосіб виявився й найгіршим за терпимістю до зсуву.

ГоловаГлобальне усереднення замість голови

Повернімося до числа з першого розділу: 97 % ваг нашої мережі лежали в останньому лінійному шарі, який зважував розпрямлену карту. Пулінг зменшив карту з 12 544 чисел до 784, тож голова схудла до 2355 ваг — це вже не 97 %, а 2355 / 3603 = 65 % мережі. Уже краще — але прийом, який добиває цю таблицю остаточно, інший, і зветься він глобальне усереднення (global average pooling, GAP).

Ідея гранично проста: не розпрямляти карту, а взяти середнє по всій площі кожного каналу. Була карта 16 × 7 × 7 — стало 16 чисел, по одному на канал. Це той самий average pooling, тільки вікно дорівнює всій карті.

16 × 7 × 7 = 784 числа → 16 чисел → лінійний шар 16 × 3 + 3 = 51 вага

Порівняй: 2355 ваг у звичайній голові проти 51 у голові з глобальним усередненням. Це в 46 разів менше — і зникає саме та частина мережі, яка найчастіше перенавчається, бо в ній найбільше ваг і найменше структури. Уся мережа схудла з 3603 параметрів до 1299.

Але економія — не головне. Головне — те, що з глобальним усередненням мережа перестає залежати від розміру входу. Розпрямлення жорстко фіксує його: лінійний шар на 784 входи приймає карту 7×7 і нічого іншого. Дай мережі зображення 40×40 — карта стане 10×10, це 1600 чисел, і шар просто впаде з помилкою розміру. Глобальне усереднення на це байдуже: з карти 10×10 воно так само дасть 16 чисел.

Ось звідки береться властивість, яку часто згадують мимохідь: сучасні класифікаційні мережі приймають зображення довільного розміру. Не тому, що там якась хитрість, а тому, що між тілом і головою стоїть глобальне усереднення.

Є й третій довід, змістовий. Кожне з 16 чисел означає «скільки цієї ознаки знайшлося на всьому зображенні» — майже готова відповідь класифікатора. На цій прозорості будують карти уваги, але це вже тема блоку 3.

Ціна теж є, і назвати її треба чесно: усереднення по всій площі викидає рештки просторової інформації остаточно, а коротка голова іноді просто не має чим розділити класи. Наші числа:

Голова мережіВаг у головіУсьогоЗсув ±1Зсув ±3Зсув ±6
Flatten + Linear2 3553 6031.0000.8630.457
глобальне усереднення511 2990.9570.9400.957

Вона видна в колонці «зсув ±1»: на тому розподілі, на якому мережа вчилася, звичайна голова дає 1.000, а коротка — 0.957. Чотири картинки зі ста тепер класифікуються неправильно, і це прямий наслідок того, що 784 числа стиснули до 16.

А тепер права колонка, і вона важливіша. На зсунутих предметах мережа з глобальним усередненням дає 0.957 — стільки ж, скільки на незсунутих. Проти 0.457 у звичайної голови. Крива не просто вища — вона рівна: 0.900, 0.957, 0.912, 0.940, 0.937, 0.938, 0.957 на зсувах від нуля до шести пікселів. Мережі стало байдуже, де саме стоїть фігура.

Причина проста, і вона підсумовує всю тему. Середнє по всій площі не залежить від того, у якому місці площі лежали числа: пересип їх як завгодно — сума та сама. Тобто глобальне усереднення — це пулінг, доведений до краю, а разом із ним до краю доведена й терпимість до зсуву: з часткової вона стає повною. Ми не додали жодного прийому, якого не було в розділі 02, — ми лише збільшили вікно до всієї карти.

І тут же межа. Повна інваріантність до зсуву означає повну втрату координат. Мережа з глобальним усередненням у принципі не може сказати, де предмет, — тільки чи він є. Для класифікації це ідеал; для детекції це вирок. Обидва факти — одне й те саме твердження, прочитане з різних боків.

Голова мережі

Одна й та сама карта ознак, дві голови. Повзунок міняє розмір вхідного зображення — і одна з голів це переживає, а друга ні.

голова
ваг у голові—
чисел на вході голови—
точність при зсуві ±1—
Розмір входу міняє все для розпрямлення й нічого для усереднення. Точність показана для навченої мережі на 28×28 — інші розміри ми не навчали, тому там стоїть прочерк; змінюється саме те, чи голова взагалі приймає таку карту.

МежаКоли пулінг шкодить

Досі ми його хвалили. Тепер два випадки, де він псує все.

Дрібний предмет розчиняється

Хай на зображенні 28×28 є світла точка 2×2 пікселі — далекий дорожній знак, дефект на деталі, зірка на знімку. Після трьох шарів середнього пулінгу вона усереднюється з площею 8×8 = 64 пікселі, з яких зайняті чотири:

яскравість 1.0 на 4 пікселях із 64 → 4 / 64 = 0.0625 на виході

Сигнал ослаб у 16 разів і опустився нижче звичайного рівня шуму. Максимум-пулінг у цьому випадку рятує — він донесе одиницю до кінця. Але й він не врятує від іншого: координата точки після трьох зменшень відома з точністю до 8 пікселів, тобто «десь у цій чверті кадру». Для класифікації нормально, для пошуку дефекту — ні.

Текстура: обидва правила псують, але по-різному

Тут цікаво, бо інтуїція підводить в обидва боки. Візьмімо дві текстури: рідкі точки (зайнято 5 % площі) і густі (зайнято 20 %). Після максимум-пулінгу з вікном 2×2 клітинка виходу світла, якщо в її чотирьох пікселях є хоч одна точка:

рідка : 1 − (1 − 0.05)⁴ = 0.19 світлих клітинок густа : 1 − (1 − 0.20)⁴ = 0.59 світлих клітинок

Після другого шару стає 0.57 і 0.97, після третього — 0.96 і 1.00. Тобто вже на третьому шарі обидві текстури стають суцільно білими й нерозрізненними. Максимум насичується: він рахує «чи є», а не «скільки».

Середнє тут працює бездоганно — воно дає рівно 0.05 і 0.20 на будь-якій глибині. Але й воно має свою сліпоту, дзеркальну. Візьмімо смужки шириною в один піксель: 0, 1, 0, 1… Середнє по вікну 2×2 дає 0.5 усюди — рівно те саме, що дала б рівна сіра заливка яскравістю 0.5. Дві геометрично різні картинки перетворилися на однакові числа без жодної можливості їх розрізнити далі.

Практичний висновок. Пулінг — це фільтр, який вирішує, що вважати неістотним. Максимум вважає неістотним усе, крім найсильнішого; середнє — усе, крім загальної кількості. Якщо твоя задача живе саме в тому, що правило викидає (густина, тонка структура, точна координата), пулінг зруйнує ознаку раніше, ніж мережа встигне її вивчити. Тоді зменшують обережніше: рідше, з кроком у самій згортці, або не зменшують узагалі.

ПідсумокТри частини зібрані

Тепер у нас є всі три складові згорткової мережі. Тема 06 показала, чому не годиться повнозвʼязна: вона вчить кожен піксель окремо й розсипається від зсуву. Тема 07 дала згортковий шар — локальність і спільні ваги. Ця тема дала третю частину: зменшення розмірності.

Що лишається з тобою:

Лишилося зібрати з трьох частин мережу цілком і подивитися, що з цього виходить: у якому порядку йдуть шари, чому канали множаться, коли карта стискається, скільки памʼяті це коштує на кожному кроці й де в підсумку лежать усі параметри. Це наступна тема.