Mundarija (21)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. MaxPool va AvgPool
- 2.2. Stride bilan o'lcham kamaytirish
- 2.3. Global average pooling
- 2.4. Siljishga kichik invariantlik
- 2.5. Pooling va stride=2 konvolyutsiya
- 2.6. Xususiyat xaritasi o'lchamlari zanjiri
- 2.7. Tuzoqlar
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — MaxPool va AvgPool ichidan
- Misol 2 — Global average pooling
- Misol 3 — Siljishga invariantlikni o'lchash
- Misol 4 — O'lchamlar zanjiri va pooling bilan stride=2
- 5. To'g'ri va noto'g'ri tushunishlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8. Eng yaxshi amaliyotlar
- 9. Amaliy topshiriq
- Xulosa
22.4-dars: Pooling
22-QISM — KOMPYUTER KO'RISH · 4-dars
1. Kirish va motivatsiya
22.3-darsda ko'rdik: nn.Conv2d siljishga ekvivariant — ob'ekt siljisa, xususiyat xaritasi ham siljiydi. Bu detektor uchun yaxshi: "burchak qayerda?" degan savolga javob beradi. Lekin tasniflash boshqa savol beradi: "rasmda nima bor?" Mushuk chapda turadimi yoki o'ngda — javob bir xil bo'lishi kerak. Bizga invariantlik kerak.
Ikkinchi muammo — o'lcham. 224×224 rasmda 64 kanalli xususiyat xaritasi 3.2 million son. Har qatlam shu o'lchamda ishlasa, hisob juda qimmat, retseptiv maydon esa sekin o'sadi. Xaritani asta-sekin kichraytirish kerak.
Pooling ikkala muammoga oddiy javob beradi. Oyna ichidagi qiymatlarning maksimumi (MaxPool) yoki o'rtachasi (AvgPool) olinadi — parametrsiz, har kanal alohida. 2×2 oyna va stride=2 xaritani to'rt barobar kichraytiradi. Tarmoq oxiridagi global pooling esa har kanalni bitta songa aylantiradi: joy haqidagi ma'lumot butunlay yo'qoladi, "nima bor" qoladi.
Lekin pooling haqida keng tarqalgan afsona bor: "MaxPool tarmoqni siljishga invariant qiladi". Bu darsda buni raqam bilan tekshiramiz — va natija kutilganidan ancha kamtarroq chiqadi.
Real vaziyat. Jamoa mahsulot rasmlari tasniflagichini 224×224 da o'rgatdi, keyin ishlab chiqarishda kameralar 320×320 rasm bera boshladi. Oxirgi qatlam Flatten + Linear(512 * 7 * 7, 1000) edi — 320×320 da xarita 10×10 bo'ldi va model RuntimeError bilan to'xtadi. AdaptiveAvgPool2d(1) ga o'tish bitta qatorlik o'zgarish bo'ldi va bosh parametrlari 49 barobar kamaydi.
Bu darsda pooling ni ichidan ko'ramiz va uning invariantligini o'lchaymiz.
Bu darsda:
-
MaxPoolvaAvgPool - Stride bilan o'lchamni kamaytirish
- Global average pooling
- Siljishga kichik invariantlik — o'lchov
- Pooling va
stride=2konvolyutsiya - Xususiyat xaritasi o'lchamlari zanjiri
- Tuzoqlar
ℹ Misollar real torch/numpy bilan (Python 3.14, torch 2.14 CPU).
2. Nazariya — chuqur tushuntirish
2.1. MaxPool va AvgPool
OYNA k x k, QADAM s (odatda k = s = 2):
MaxPool: y[i, j] = max(oyna)
AvgPool: y[i, j] = mean(oyna)
MISOL (4x4 -> 2x2):
1 3 | 2 0 max: 6 2 avg: 3.75 1.25
5 6 | 1 2 7 9 2.50 6.00
----+----
7 2 | 9 4
0 1 | 3 8
XUSUSIYATLARI:
parametrlar: 0 (hech narsa o'rganmaydi)
har kanal ALOHIDA: (N, C, H, W) -> (N, C, H/2, W/2), C o'zgarmaydi
GRADIENT:
max: faqat maksimum turgan joyga (qolganlari 0) - "g'olib oladi"
avg: oyna bo'ylab teng (1 / k^2)
MA'NOSI:
max - "shu sohada xususiyat BORMI" (eng kuchli javob)
avg - "shu sohada xususiyat QANCHA" (silliqlaydi)Pooling — parametrsiz, kanal bo'yicha alohida; max "bor-yo'qligini", avg "qanchaligini" saqlaydi.
2.2. Stride bilan o'lcham kamaytirish
FORMULA - konvolyutsiya bilan bir xil (22.2-dars):
H_chiq = floor((H + 2p - k) / s) + 1
MaxPool2d(2): 32 -> 16, 7 -> 3 (oxirgi qator tashlanadi)
MaxPool2d(2, ceil_mode=True): 7 -> 4
MaxPool2d(3, 2, padding=1): 32 -> 16 (ustma-ust oynalar, ResNet boshida)
NIMA BERADI:
hisob: keyingi qatlamlar 4 barobar arzon
retseptiv maydon: jump 2 barobar -> keyingi 3x3 ikki barobar keng ko'radi
kanallar odatda ko'paytiriladi: 32x32x16 -> 16x16x32
("qayerda" aniqligi -> "nima" boyligi)
TIPIK ZANJIR (32x32 kirish):
conv 32x32x16 -> pool 16x16x16 -> conv 16x16x32 -> pool 8x8x32
-> conv 8x8x64 -> pool 4x4x64 -> global pool 64 -> LinearPooling o'lchamni kamaytiradi, kanallar esa ko'payadi — fazoviy aniqlik ma'noga almashtiriladi.
2.3. Global average pooling
GAP: har kanal -> bitta son (butun xarita o'rtachasi)
(N, C, H, W) -> (N, C, 1, 1) -> flatten -> (N, C)
nn.AdaptiveAvgPool2d(1) == x.mean(dim=(2, 3))
global max: nn.AdaptiveMaxPool2d(1) == x.amax(dim=(2, 3))
BOSH (klassifikator) TAQQOSLASH, 1000 sinf:
Flatten + Linear GAP + Linear
512 x 7 x 7 25 089 000 513 000
2048 x 7 x 7 100 353 000 2 049 000
AFZALLIKLARI:
1. parametrlar H*W marta kam -> ortiqcha moslashish kam
2. ISTALGAN kirish o'lchami ishlaydi
3. siljishga invariant (ob'ekt chetdan chiqmaguncha)
ADAPTIVE POOLING: chiqish o'lchami beriladi, oyna o'zi tanlanadi
AdaptiveAvgPool2d((2, 2)): 7x7, 10x10, 13x13 -> hammasi 2x2
NARXI: "qayerda" ma'lumoti butunlay yo'qoladi
-> aniqlash va segmentatsiyada global pooling ishlatilmaydiGAP — har kanalni bitta songa; o'lchamdan ozod, parametr kam, joy esa unutiladi.
2.4. Siljishga kichik invariantlik
AFSONA: "MaxPool tarmoqni siljishga invariant qiladi"
HAQIQAT:
MaxPool 2x2 - faqat oyna ICHIDAGI siljishni "yutadi"
maksimum oynadan chiqib ketmasa - chiqish o'zgarmaydi
oyna chegarasidan o'tsa - boshqa oynaga tushadi
siljish oyna o'lchamiga yetganda foyda deyarli yo'qoladi
juft siljish (2 piksel) va 2x2 pool:
chiqish ANIQ 1 ga siljiydi - bu ekvivariantlik, invariantlik emas
O'LCHOV:
nisbiy o'zgarish = ||f(siljit(x)) - f(x)|| / ||f(x)||
0 - to'liq invariant, pooling siz qiymat bilan solishtiriladi
TO'LIQ INVARIANTLIK:
faqat GLOBAL pooling (GAP/GMP) - ob'ekt xaritadan chiqmaguncha
qo'shimcha: augmentatsiya (tasodifiy siljitish, 21-qism)Mahalliy pooling siljishga faqat qisman chidamli; to'liq invariantlik — global pooling dan.
2.5. Pooling va stride=2 konvolyutsiya
IKKI USUL O'LCHAMNI 2 BAROBAR KAMAYTIRADI:
MaxPool2d(2) Conv2d(C, C, 3, stride=2, p=1)
parametrlar 0 C*C*9 + C
o'rganadi yo'q ha
kanallarni aralashtirmaydi aralashtiradi
qaysi arxitektura LeNet, VGG ResNet (qisman), zamonaviy tarmoqlar
AMALDA:
kichik vazifalarda farq ko'pincha shovqin ichida
stride conv - ko'proq parametr, "qanday kichraytirishni" o'rganadi
pooling - arzon, sodda, yaxshi boshlang'ich nuqta
QOIDA: bitta seed bilan emas, bir necha seed va SE bilan taqqoslang (18-qism) Pooling — bepul kichraytirish, stride=2 konvolyutsiya — o'rganiladigan; tanlovni o'lchov hal qiladi.
2.6. Xususiyat xaritasi o'lchamlari zanjiri
HAR QATLAMDAN KEYIN SHAKLNI BILISH SHART:
Conv2d(1, 16, 3, p=1): (N, 1, 8, 8) -> (N, 16, 8, 8)
MaxPool2d(2): -> (N, 16, 4, 4)
Conv2d(16, 32, 3, p=1): -> (N, 32, 4, 4)
MaxPool2d(2): -> (N, 32, 2, 2)
AdaptiveAvgPool2d(1): -> (N, 32, 1, 1)
Flatten: -> (N, 32)
Linear(32, 10): -> (N, 10)
TEKSHIRISH USULI:
for q in model: x = q(x); print(type(q).__name__, x.shape)
- bitta kichik batch bilan, o'rgatishdan OLDIN
CHEKLOV: 2x2 pool har safar o'lchamni ikkiga bo'ladi
8x8 rasmda ikki marta - 2x2; uchinchisi 1x1
kichik rasmda pooling sonini cheklang Shakllar zanjirini o'rgatishdan oldin chop eting — Linear ga kirish o'lchami shu yerda aniqlanadi.
2.7. Tuzoqlar
Asosiy tuzoqlar: pooling ni to'liq siljish invariantligi deb o'ylash; Flatten + Linear boshini qattiq o'lchamga bog'lab, boshqa o'lchamdagi rasmda RuntimeError olish; toq o'lchamda floor tufayli oxirgi qatorni yo'qotish; kichik rasmda juda ko'p pooling (1×1 gacha qisqarish); aniqlash yoki segmentatsiyada global pooling bilan joyni yo'qotish; MaxPool gradienti faqat bitta joyga borishini unutish; pooling ni stride conv bilan bitta seed natijasida taqqoslash; AvgPool va GAP ni aralashtirish.
3. Tez ma'lumotnoma
import torch
import torch.nn as nn
class KichikCNN(nn.Module):
def __init__(self, n_sinf=10):
super().__init__()
self.xususiyat = nn.Sequential(
nn.Conv2d(1, 16, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
nn.Conv2d(16, 32, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
nn.Conv2d(32, 64, 3, padding=1), nn.ReLU())
self.gap = nn.AdaptiveAvgPool2d(1) # istalgan o'lcham
self.bosh = nn.Linear(64, n_sinf)
def forward(self, x):
return self.bosh(self.gap(self.xususiyat(x)).flatten(1))
def shakllar(model, x):
for q in model.xususiyat:
x = q(x)
print(f"{type(q).__name__:<12} {tuple(x.shape)}")Pooling xulosasi
MaxPool2d(2): (N, C, H, W) -> (N, C, H/2, W/2), parametr 0
max - "bormi", avg - "qancha"; gradient: max -> bitta joyga
GAP: AdaptiveAvgPool2d(1) == mean(dim=(2, 3)); o'lchamdan ozod
mahalliy pooling - qisman chidamli; global pooling - invariant
stride=2 conv - o'rganiladigan alternativa, ko'proq parametr4. Batafsil misollar
Misollar real torch/numpy bilan (Python 3.14, torch 2.14 CPU).
Misol 1 — MaxPool va AvgPool ichidan
"""MaxPool va AvgPool: qo'lda, torch bilan, o'lcham va gradient."""
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
def pool_qolda(x, k=2, s=2, turi="max"):
h_ch = (x.shape[0] - k) // s + 1
w_ch = (x.shape[1] - k) // s + 1
y = np.zeros((h_ch, w_ch))
for i in range(h_ch):
for j in range(w_ch):
oyna = x[i * s:i * s + k, j * s:j * s + k]
y[i, j] = oyna.max() if turi == "max" else oyna.mean()
return y
def jadval(m):
for qator in m:
print(" " + " ".join(f"{v:>5.2f}" for v in qator))
def main() -> None:
x = np.array([[1, 3, 2, 0],
[5, 6, 1, 2],
[7, 2, 9, 4],
[0, 1, 3, 8]], dtype=np.float64)
xt = torch.tensor(x).view(1, 1, 4, 4)
print("=== 1. 2x2 oynalar, stride=2 ===")
jadval(x)
for turi in ["max", "avg"]:
q = pool_qolda(x, turi=turi)
t = (F.max_pool2d(xt, 2) if turi == "max"
else F.avg_pool2d(xt, 2))[0, 0].numpy()
print(f" {turi}_pool:")
jadval(q)
print(f" torch bilan teng: {np.array_equal(q, t)}")
print("\n=== 2. Parametrlar yo'q, kanallar alohida ===")
mp = nn.MaxPool2d(2)
print(f" {mp}")
print(f" parametrlar soni: {sum(p.numel() for p in mp.parameters())}")
torch.manual_seed(0)
z = torch.randn(4, 16, 32, 32)
print(f" (4, 16, 32, 32) -> {tuple(mp(z).shape)} "
f"(kanallar soni o'zgarmaydi)")
alohida = torch.stack([F.max_pool2d(z[:, c:c + 1], 2)[:, 0]
for c in range(16)], dim=1)
print(f" har kanalni alohida pool qilish bilan teng: "
f"{torch.equal(alohida, mp(z))}")
print("\n=== 3. O'lchamlar: kernel, stride, padding, ceil_mode ===")
print(f" {'H':>3} {'k':>3} {'s':>3} {'p':>3} {'ceil':>5} "
f"{'formula':>8} {'torch':>6}")
for h, k, s, p, ceil in [(32, 2, 2, 0, False), (7, 2, 2, 0, False),
(7, 2, 2, 0, True), (32, 3, 2, 1, False),
(28, 3, 1, 1, False), (13, 3, 2, 0, False)]:
kasr = (h + 2 * p - k) / s + 1
f = int(np.ceil(kasr - 1) + 1) if ceil else int(np.floor(kasr - 1) + 1)
t = F.max_pool2d(torch.zeros(1, 1, h, h), k, s, p,
ceil_mode=ceil).shape[-1]
print(f" {h:>3} {k:>3} {s:>3} {p:>3} {str(ceil):>5} {f:>8} {t:>6}")
print(" formula konvolyutsiya bilan bir xil: floor((H + 2p - k)/s) + 1")
print("\n=== 4. Gradient qayerga boradi ===")
for turi in ["max", "avg"]:
xg = torch.tensor(x).view(1, 1, 4, 4).requires_grad_()
y = F.max_pool2d(xg, 2) if turi == "max" else F.avg_pool2d(xg, 2)
y.sum().backward()
print(f" {turi}_pool gradienti:")
jadval(xg.grad[0, 0].numpy())
print(" max: gradient faqat maksimumga (1), qolganlari 0")
print(" avg: gradient teng bo'linadi (1/4)")
print("\n=== 5. Max va avg nimani saqlaydi ===")
tekis = torch.zeros(1, 1, 8, 8)
tekis[0, 0, 2, 5] = 1.0 # bitta yorqin nuqta
print(" 8x8 da bitta yorqin nuqta (qiymat 1):")
print(f" max_pool 4x4 -> maks {F.max_pool2d(tekis, 4).max():.4f}")
print(f" avg_pool 4x4 -> maks {F.avg_pool2d(tekis, 4).max():.4f}")
print(" max - 'bor-yo'qligini' saqlaydi, avg - 'qanchaligini' (xiralaydi)")
print(" ⭐ Pooling - parametrsiz, kanal bo'yicha alohida, o'lchamni kichraytiradi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. 2x2 oynalar, stride=2 ===
1.00 3.00 2.00 0.00
5.00 6.00 1.00 2.00
7.00 2.00 9.00 4.00
0.00 1.00 3.00 8.00
max_pool:
6.00 2.00
7.00 9.00
torch bilan teng: True
avg_pool:
3.75 1.25
2.50 6.00
torch bilan teng: True
=== 2. Parametrlar yo'q, kanallar alohida ===
MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
parametrlar soni: 0
(4, 16, 32, 32) -> (4, 16, 16, 16) (kanallar soni o'zgarmaydi)
har kanalni alohida pool qilish bilan teng: True
=== 3. O'lchamlar: kernel, stride, padding, ceil_mode ===
H k s p ceil formula torch
32 2 2 0 False 16 16
7 2 2 0 False 3 3
7 2 2 0 True 4 4
32 3 2 1 False 16 16
28 3 1 1 False 28 28
13 3 2 0 False 6 6
formula konvolyutsiya bilan bir xil: floor((H + 2p - k)/s) + 1
=== 4. Gradient qayerga boradi ===
max_pool gradienti:
0.00 0.00 1.00 0.00
0.00 1.00 0.00 0.00
1.00 0.00 1.00 0.00
0.00 0.00 0.00 0.00
avg_pool gradienti:
0.25 0.25 0.25 0.25
0.25 0.25 0.25 0.25
0.25 0.25 0.25 0.25
0.25 0.25 0.25 0.25
max: gradient faqat maksimumga (1), qolganlari 0
avg: gradient teng bo'linadi (1/4)
=== 5. Max va avg nimani saqlaydi ===
8x8 da bitta yorqin nuqta (qiymat 1):
max_pool 4x4 -> maks 1.0000
avg_pool 4x4 -> maks 0.0625
max - 'bor-yo'qligini' saqlaydi, avg - 'qanchaligini' (xiralaydi)
⭐ Pooling - parametrsiz, kanal bo'yicha alohida, o'lchamni kichraytiradiNima ko'rsatdi: 2.1, 2.2-bo'limlar.
Misol 2 — Global average pooling
"""Global average pooling: mean ga tengligi, istalgan o'lcham, bosh parametrlari."""
import torch
import torch.nn as nn
class FlattenBosh(nn.Module):
"""Xususiyat xaritasini yoyib, Linear ga beradi - o'lcham qat'iy."""
def __init__(self, c, h, w, n_sinf=10):
super().__init__()
self.lin = nn.Linear(c * h * w, n_sinf)
def forward(self, f):
return self.lin(f.flatten(1))
class GAPBosh(nn.Module):
"""Har kanalni bitta songa o'rtachalaydi - o'lcham erkin."""
def __init__(self, c, n_sinf=10):
super().__init__()
self.gap = nn.AdaptiveAvgPool2d(1)
self.lin = nn.Linear(c, n_sinf)
def forward(self, f):
return self.lin(self.gap(f).flatten(1))
def main() -> None:
torch.manual_seed(0)
f = torch.randn(4, 64, 7, 7)
print("=== 1. AdaptiveAvgPool2d(1) = mean(dim=(2, 3)) ===")
gap = nn.AdaptiveAvgPool2d(1)(f)
print(f" (4, 64, 7, 7) -> {tuple(gap.shape)}")
print(f" mean bilan teng: "
f"{torch.allclose(gap.flatten(1), f.mean(dim=(2, 3)))}")
gmp = nn.AdaptiveMaxPool2d(1)(f)
print(f" AdaptiveMaxPool2d(1) = amax(dim=(2, 3)): "
f"{torch.equal(gmp.flatten(1), f.amax(dim=(2, 3)))}")
print("\n=== 2. Istalgan kirish o'lchami ===")
xususiyat = nn.Sequential(nn.Conv2d(3, 16, 3, padding=1), nn.ReLU(),
nn.MaxPool2d(2),
nn.Conv2d(16, 32, 3, padding=1), nn.ReLU(),
nn.MaxPool2d(2))
gap_bosh = GAPBosh(32)
flat_bosh = FlattenBosh(32, 8, 8) # 32x32 kirish uchun
print(f" {'kirish':>10} {'xususiyat':>16} {'GAP bosh':>10} "
f"{'Flatten bosh':>14}")
for h in [32, 48, 64, 33]:
x = torch.randn(2, 3, h, h)
fx = xususiyat(x)
g = tuple(gap_bosh(fx).shape)
try:
fl = str(tuple(flat_bosh(fx).shape))
except RuntimeError:
fl = "RuntimeError"
print(f" {f'{h}x{h}':>10} {str(tuple(fx.shape[1:])):>16} "
f"{str(g):>10} {fl:>14}")
print("\n=== 3. Bosh parametrlari ===")
print(f" {'xususiyat xaritasi':<20} {'Flatten+Linear':>15} "
f"{'GAP+Linear':>11}")
for c, h in [(32, 8), (64, 7), (512, 7), (2048, 7)]:
fl = sum(p.numel() for p in FlattenBosh(c, h, h, 1000).parameters())
gp = sum(p.numel() for p in GAPBosh(c, 1000).parameters())
print(f" {f'{c}x{h}x{h}':<20} {fl:>15,} {gp:>11,}")
print(" GAP bosh parametrlari H*W marta kam (bias dan tashqari)")
print("\n=== 4. Adaptive pooling - chiqish o'lchami beriladi ===")
for chiq in [(1, 1), (2, 2), (3, 3)]:
for h in [7, 10, 13]:
y = nn.AdaptiveAvgPool2d(chiq)(torch.randn(1, 8, h, h))
print(f" AdaptiveAvgPool2d({chiq}) {h}x{h} -> "
f"{tuple(y.shape[2:])}")
print("\n=== 5. GAP joyni unutadi ===")
a = torch.zeros(1, 1, 8, 8)
b = torch.zeros(1, 1, 8, 8)
a[0, 0, 1, 1] = 1.0 # chap-yuqori burchakda
b[0, 0, 6, 5] = 1.0 # o'ng-pastda
ga = nn.AdaptiveAvgPool2d(1)(a).item()
gb = nn.AdaptiveAvgPool2d(1)(b).item()
print(f" nuqta (1, 1) da: GAP {ga:.4f}; nuqta (6, 5) da: GAP {gb:.4f}")
print(f" teng: {ga == gb} - 'nima bor' qoladi, 'qayerda' yo'qoladi")
print(" ⭐ GAP: har kanal -> bitta son; o'lchamdan ozod, parametr kam")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. AdaptiveAvgPool2d(1) = mean(dim=(2, 3)) ===
(4, 64, 7, 7) -> (4, 64, 1, 1)
mean bilan teng: True
AdaptiveMaxPool2d(1) = amax(dim=(2, 3)): True
=== 2. Istalgan kirish o'lchami ===
kirish xususiyat GAP bosh Flatten bosh
32x32 (32, 8, 8) (2, 10) (2, 10)
48x48 (32, 12, 12) (2, 10) RuntimeError
64x64 (32, 16, 16) (2, 10) RuntimeError
33x33 (32, 8, 8) (2, 10) (2, 10)
=== 3. Bosh parametrlari ===
xususiyat xaritasi Flatten+Linear GAP+Linear
32x8x8 2,049,000 33,000
64x7x7 3,137,000 65,000
512x7x7 25,089,000 513,000
2048x7x7 100,353,000 2,049,000
GAP bosh parametrlari H*W marta kam (bias dan tashqari)
=== 4. Adaptive pooling - chiqish o'lchami beriladi ===
AdaptiveAvgPool2d((1, 1)) 7x7 -> (1, 1)
AdaptiveAvgPool2d((1, 1)) 10x10 -> (1, 1)
AdaptiveAvgPool2d((1, 1)) 13x13 -> (1, 1)
AdaptiveAvgPool2d((2, 2)) 7x7 -> (2, 2)
AdaptiveAvgPool2d((2, 2)) 10x10 -> (2, 2)
AdaptiveAvgPool2d((2, 2)) 13x13 -> (2, 2)
AdaptiveAvgPool2d((3, 3)) 7x7 -> (3, 3)
AdaptiveAvgPool2d((3, 3)) 10x10 -> (3, 3)
AdaptiveAvgPool2d((3, 3)) 13x13 -> (3, 3)
=== 5. GAP joyni unutadi ===
nuqta (1, 1) da: GAP 0.0156; nuqta (6, 5) da: GAP 0.0156
teng: True - 'nima bor' qoladi, 'qayerda' yo'qoladi
⭐ GAP: har kanal -> bitta son; o'lchamdan ozod, parametr kamNima ko'rsatdi: 2.3-bo'lim.
Misol 3 — Siljishga invariantlikni o'lchash
"""Siljishga kichik invariantlik: pooling dan oldin va keyin o'lchash."""
import torch
import torch.nn as nn
import torch.nn.functional as F
from sklearn.datasets import load_digits
def nisbiy_ozgarish(a, b):
"""Har rasm uchun ||a - b|| / ||a||, keyin o'rtacha."""
a, b = a.flatten(1), b.flatten(1)
return ((a - b).norm(dim=1) / a.norm(dim=1).clamp_min(1e-8)).mean().item()
def main() -> None:
torch.manual_seed(0)
d = load_digits()
x = torch.tensor(d.images[:500], dtype=torch.float32).unsqueeze(1) / 16
x = F.pad(x, (4, 4, 4, 4)) # 16x16, raqam markazda
print(f" rasmlar: {tuple(x.shape)} (8x8 raqam 16x16 maydon markazida)")
conv = nn.Conv2d(1, 8, 3, padding=1)
with torch.no_grad():
f0 = F.relu(conv(x)) # xususiyat xaritalari
bosqichlar = {
"xarita (pooling yo'q)": lambda f: f,
"MaxPool 2x2": lambda f: F.max_pool2d(f, 2),
"AvgPool 2x2": lambda f: F.avg_pool2d(f, 2),
"MaxPool 4x4": lambda f: F.max_pool2d(f, 4),
"global max (GMP)": lambda f: f.amax(dim=(2, 3)),
"global avg (GAP)": lambda f: f.mean(dim=(2, 3)),
}
siljishlar = [(0, 1), (1, 1), (0, 2), (2, 2), (3, 3)]
print("\n=== 1. Nisbiy o'zgarish: ||f(siljit(x)) - f(x)|| / ||f(x)|| ===")
sarlavha = " ".join(f"{f'({a},{b})':>7}" for a, b in siljishlar)
print(f" {'bosqich':<22} {sarlavha}")
natija = {}
with torch.no_grad():
for nom, fn in bosqichlar.items():
asl = fn(f0)
qator = []
for a, b in siljishlar:
xs = torch.roll(x, shifts=(a, b), dims=(2, 3))
qator.append(nisbiy_ozgarish(asl, fn(F.relu(conv(xs)))))
natija[nom] = qator
print(f" {nom:<22} " + " ".join(f"{v:>7.3f}" for v in qator))
print("\n=== 2. Pooling yo'q holatga nisbatan kamayish ===")
xarita = natija["xarita (pooling yo'q)"]
print(f" {'bosqich':<22} {sarlavha}")
for nom in list(bosqichlar)[1:]:
kam = [1 - v / x0 for v, x0 in zip(natija[nom], xarita)]
print(f" {nom:<22} " + " ".join(f"{v:>7.0%}" for v in kam))
mp2 = [1 - v / x0 for v, x0 in zip(natija["MaxPool 2x2"], xarita)]
print(f" MaxPool 2x2: 1 pikselda {mp2[0]:.0%}, 2 pikselda {mp2[2]:.0%}, "
f"(3,3) da {mp2[4]:.0%}")
if mp2[0] > mp2[2]:
print(" siljish kattalashgan sari mahalliy pooling foydasi yo'qoladi")
if max(natija["global avg (GAP)"]) < 1e-5:
print(" GAP hamma siljishda o'zgarmas (raqam chetdan chiqmaguncha)")
print("\n=== 3. Siljish grid bilan mos kelsa ===")
with torch.no_grad():
p0 = F.max_pool2d(f0, 2)
xs = torch.roll(x, shifts=(2, 2), dims=(2, 3))
p2 = F.max_pool2d(F.relu(conv(xs)), 2)
p2_qaytarilgan = torch.roll(p2, shifts=(-1, -1), dims=(2, 3))
print(f" (2,2) siljish, MaxPool 2x2 chiqishini (1,1) orqaga surilsa: "
f"nisbiy farq {nisbiy_ozgarish(p0, p2_qaytarilgan):.1e}")
print(" juft siljish - chiqish ham aniq siljiydi (ekvivariant),")
print(f" lekin joyma-joy taqqoslasa o'zgarish "
f"{natija['MaxPool 2x2'][3]:.3f} (invariant emas)")
print(" ⭐ Pooling kichik siljishga qisman chidamli; to'liq - faqat global pooling")
if __name__ == "__main__":
main()Natijaning muhim qismi:
rasmlar: (500, 1, 16, 16) (8x8 raqam 16x16 maydon markazida)
=== 1. Nisbiy o'zgarish: ||f(siljit(x)) - f(x)|| / ||f(x)|| ===
bosqich (0,1) (1,1) (0,2) (2,2) (3,3)
xarita (pooling yo'q) 0.363 0.462 0.490 0.537 0.569
MaxPool 2x2 0.317 0.401 0.473 0.532 0.587
AvgPool 2x2 0.225 0.302 0.358 0.416 0.477
MaxPool 4x4 0.238 0.343 0.367 0.476 0.589
global max (GMP) 0.000 0.000 0.000 0.000 0.000
global avg (GAP) 0.000 0.000 0.000 0.000 0.000
=== 2. Pooling yo'q holatga nisbatan kamayish ===
bosqich (0,1) (1,1) (0,2) (2,2) (3,3)
MaxPool 2x2 13% 13% 3% 1% -3%
AvgPool 2x2 38% 35% 27% 23% 16%
MaxPool 4x4 34% 26% 25% 11% -3%
global max (GMP) 100% 100% 100% 100% 100%
global avg (GAP) 100% 100% 100% 100% 100%
MaxPool 2x2: 1 pikselda 13%, 2 pikselda 3%, (3,3) da -3%
siljish kattalashgan sari mahalliy pooling foydasi yo'qoladi
GAP hamma siljishda o'zgarmas (raqam chetdan chiqmaguncha)
=== 3. Siljish grid bilan mos kelsa ===
(2,2) siljish, MaxPool 2x2 chiqishini (1,1) orqaga surilsa: nisbiy farq 0.0e+00
juft siljish - chiqish ham aniq siljiydi (ekvivariant),
lekin joyma-joy taqqoslasa o'zgarish 0.532 (invariant emas)
⭐ Pooling kichik siljishga qisman chidamli; to'liq - faqat global poolingNima ko'rsatdi: 2.4-bo'lim.
Misol 4 — O'lchamlar zanjiri va pooling bilan stride=2
"""O'lchamlar zanjiri va MaxPool bilan stride=2 konvolyutsiyani taqqoslash."""
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
def pool_tarmoq():
return nn.Sequential(
nn.Conv2d(1, 16, 3, padding=1), nn.ReLU(),
nn.MaxPool2d(2), # 8 -> 4
nn.Conv2d(16, 32, 3, padding=1), nn.ReLU(),
nn.MaxPool2d(2), # 4 -> 2
nn.Conv2d(32, 32, 3, padding=1), nn.ReLU(),
nn.AdaptiveAvgPool2d(1), nn.Flatten(), nn.Linear(32, 10))
def stride_tarmoq():
return nn.Sequential(
nn.Conv2d(1, 16, 3, padding=1), nn.ReLU(),
nn.Conv2d(16, 16, 3, stride=2, padding=1), nn.ReLU(), # 8 -> 4
nn.Conv2d(16, 32, 3, padding=1), nn.ReLU(),
nn.Conv2d(32, 32, 3, stride=2, padding=1), nn.ReLU(), # 4 -> 2
nn.Conv2d(32, 32, 3, padding=1), nn.ReLU(),
nn.AdaptiveAvgPool2d(1), nn.Flatten(), nn.Linear(32, 10))
def qisqa(q):
if isinstance(q, nn.Conv2d):
return (f"Conv2d({q.in_channels}, {q.out_channels}, "
f"k={q.kernel_size[0]}, s={q.stride[0]})")
if isinstance(q, nn.MaxPool2d):
return f"MaxPool2d({q.kernel_size})"
if isinstance(q, nn.Linear):
return f"Linear({q.in_features}, {q.out_features})"
return type(q).__name__
def zanjir(model, x):
print(f" {'qatlam':<26} {'chiqish shakli':>16} {'param':>7}")
print(f" {'kirish':<26} {str(tuple(x.shape)):>16} {'':>7}")
for q in model:
x = q(x)
if isinstance(q, nn.ReLU):
continue
p = sum(t.numel() for t in q.parameters())
print(f" {qisqa(q):<26} {str(tuple(x.shape)):>16} {p:>7}")
def tayyorla():
d = load_digits()
x = torch.tensor(d.images, dtype=torch.float32).unsqueeze(1) / 16
y = torch.tensor(d.target)
idx_tr, idx_te = train_test_split(np.arange(len(y)), test_size=0.4,
stratify=d.target, random_state=0)
return x[idx_tr], y[idx_tr], x[idx_te], y[idx_te]
def orgat(model, x, y, davrlar=30, seed=0):
opt = torch.optim.Adam(model.parameters(), lr=0.003)
g = torch.Generator().manual_seed(seed)
for _ in range(davrlar):
model.train()
tartib = torch.randperm(len(y), generator=g)
for i in range(0, len(y), 64):
idx = tartib[i:i + 64]
opt.zero_grad()
F.cross_entropy(model(x[idx]), y[idx]).backward()
opt.step()
return model
def aniqlik(model, x, y):
model.eval()
with torch.no_grad():
return (model(x).argmax(1) == y).float().mean().item()
def main() -> None:
x_tr, y_tr, x_te, y_te = tayyorla()
print(f" load_digits 8x8: o'quv {tuple(x_tr.shape)}, "
f"test {len(y_te)}")
print("\n=== 1. O'lchamlar zanjiri: MaxPool bilan ===")
torch.manual_seed(0)
zanjir(pool_tarmoq(), x_tr[:8])
print("\n=== 2. O'lchamlar zanjiri: stride=2 konvolyutsiya bilan ===")
zanjir(stride_tarmoq(), x_tr[:8])
print("\n=== 3. O'rgatish (3 seed, 30 davr) ===")
print(f" {'seed':>5} {'MaxPool':>9} {'stride=2':>9}")
a, b = [], []
for seed in range(3):
torch.manual_seed(seed)
m1 = orgat(pool_tarmoq(), x_tr, y_tr, seed=seed)
torch.manual_seed(seed)
m2 = orgat(stride_tarmoq(), x_tr, y_tr, seed=seed)
a.append(aniqlik(m1, x_te, y_te))
b.append(aniqlik(m2, x_te, y_te))
print(f" {seed:>5} {a[-1]:>9.4f} {b[-1]:>9.4f}")
a, b = np.array(a), np.array(b)
p1 = sum(p.numel() for p in pool_tarmoq().parameters())
p2 = sum(p.numel() for p in stride_tarmoq().parameters())
print(f" o'rtacha: MaxPool {a.mean():.4f}, stride=2 {b.mean():.4f}")
print(f" parametrlar: MaxPool {p1}, stride=2 {p2} (+{p2 - p1})")
farq = b - a
se = farq.std(ddof=1) / np.sqrt(len(farq))
print(f" farq (stride - MaxPool): {farq.mean():+.4f}, SE {se:.4f}")
if abs(farq.mean()) <= 2 * se or abs(farq.mean()) < 0.005:
print(" QAROR: farq shovqin ichida - bu vazifada ikkalasi teng")
elif farq.mean() > 0:
print(" QAROR: stride=2 konvolyutsiya bu vazifada yaxshiroq")
else:
print(" QAROR: MaxPool bu vazifada yaxshiroq")
print(" ⭐ Pooling - bepul kichraytirish; stride=2 conv - o'rganiladigan")
if __name__ == "__main__":
main()Natijaning muhim qismi:
load_digits 8x8: o'quv (1078, 1, 8, 8), test 719
=== 1. O'lchamlar zanjiri: MaxPool bilan ===
qatlam chiqish shakli param
kirish (8, 1, 8, 8)
Conv2d(1, 16, k=3, s=1) (8, 16, 8, 8) 160
MaxPool2d(2) (8, 16, 4, 4) 0
Conv2d(16, 32, k=3, s=1) (8, 32, 4, 4) 4640
MaxPool2d(2) (8, 32, 2, 2) 0
Conv2d(32, 32, k=3, s=1) (8, 32, 2, 2) 9248
AdaptiveAvgPool2d (8, 32, 1, 1) 0
Flatten (8, 32) 0
Linear(32, 10) (8, 10) 330
=== 2. O'lchamlar zanjiri: stride=2 konvolyutsiya bilan ===
qatlam chiqish shakli param
kirish (8, 1, 8, 8)
Conv2d(1, 16, k=3, s=1) (8, 16, 8, 8) 160
Conv2d(16, 16, k=3, s=2) (8, 16, 4, 4) 2320
Conv2d(16, 32, k=3, s=1) (8, 32, 4, 4) 4640
Conv2d(32, 32, k=3, s=2) (8, 32, 2, 2) 9248
Conv2d(32, 32, k=3, s=1) (8, 32, 2, 2) 9248
AdaptiveAvgPool2d (8, 32, 1, 1) 0
Flatten (8, 32) 0
Linear(32, 10) (8, 10) 330
=== 3. O'rgatish (3 seed, 30 davr) ===
seed MaxPool stride=2
0 0.9722 0.9680
1 0.9666 0.9722
2 0.9750 0.9694
o'rtacha: MaxPool 0.9713, stride=2 0.9699
parametrlar: MaxPool 14378, stride=2 25946 (+11568)
farq (stride - MaxPool): -0.0014, SE 0.0035
QAROR: farq shovqin ichida - bu vazifada ikkalasi teng
⭐ Pooling - bepul kichraytirish; stride=2 conv - o'rganiladiganNima ko'rsatdi: 2.5, 2.6-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "MaxPool tarmoqni siljishga invariant qiladi" | Faqat oyna ichidagi kichik siljishga, qisman |
| "Pooling qatlami o'rganadi" | Parametrlari 0 |
| "Pooling kanallarni aralashtiradi" | Har kanal alohida |
| "MaxPool gradienti hamma joyga boradi" | Faqat maksimum joyiga |
"Flatten + Linear — yagona bosh" |
GAP bosh — o'lchamdan ozod va ancha kichik |
| "GAP ma'lumotni yo'qotmaydi" | "Qayerda" butunlay yo'qoladi |
"stride=2 conv doim pooling dan yaxshi" |
Kichik vazifada farq shovqin ichida bo'lishi mumkin |
| "Pooling qancha ko'p — shuncha yaxshi" | Kichik rasm 1×1 gacha qisqarib qoladi |
6. Keng tarqalgan xatolar va yechimlari
1. Qattiq o'lchamli bosh
nn.Sequential(..., nn.Flatten(), nn.Linear(32 * 8 * 8, 10)) # ⚠️ faqat 32x32
nn.Sequential(..., nn.AdaptiveAvgPool2d(1), nn.Flatten(), nn.Linear(32, 10)) # ✅2. Toq o'lchamda oxirgi qatorni yo'qotish
nn.MaxPool2d(2)(torch.rand(1, 8, 7, 7)) # -> 3x3, 7-qator tashlandi # ⚠️
nn.MaxPool2d(2, ceil_mode=True) # -> 4x4 # ✅3. Kichik rasmda ortiqcha pooling
# 8x8 kirish, 4 ta MaxPool2d(2): 8 -> 4 -> 2 -> 1 -> RuntimeError # ⚠️
# 8x8 kirish: 2 ta pooling, keyin global pooling # ✅4. Invariantlikni pooling dan kutish
model = cnn_maxpool_bilan # "siljishga chidamli bo'ladi" # ⚠️
# augmentatsiya (tasodifiy siljitish) + global pooling # ✅5. GAP ni aniqlashda ishlatish
bbox = nn.Linear(64, 4)(gap(xarita).flatten(1)) # joy yo'qolgan # ⚠️
# joy kerak bo'lsa - xaritani fazoviy saqlang (aniqlash mavzusida) # ✅6. mean ning noto'g'ri o'qlari
f.mean(dim=(1, 2)) # kanallar ustidan - xato # ⚠️
f.mean(dim=(2, 3)) # H, W ustidan - GAP # ✅7. Bitta seed bilan qaror
# "stride conv 0.3% yaxshi chiqdi" - bitta o'rgatish # ⚠️
# 3+ seed, juftlashgan farq va SE (18-qism) # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 18-qism (o'tilgan): Juftlashgan taqqoslash, SE
- 21-qism (o'tilgan): Augmentatsiya — invariantlikning asosiy manbai
- 22.3-dars (o'tilgan): Ekvivariantlik va retseptiv maydon
- Keyingi dars: Birinchi to'liq CNN — conv, pool, GAP bir joyda
- CNN arxitekturalari mavzusida: VGG (MaxPool), ResNet (stride conv + GAP)
- Obyekt aniqlash va segmentatsiya mavzularida: Joyni saqlash uchun global pooling siz boshlar
8. Eng yaxshi amaliyotlar
Kichraytirishni
MaxPool2d(2)dan boshlang — sodda va arzon.Tarmoq oxirida
AdaptiveAvgPool2d(1),Flatten+ kattaLinearemas.Kichraytirganda kanallarni ko'paytiring.
Shakllar zanjirini bitta batch bilan chop eting.
Toq o'lchamlarga e'tibor bering (
ceil_modeyoki padding).Invariantlik uchun augmentatsiyaga tayaning, pooling ga emas.
Joy muhim vazifalarda global pooling ishlatmang.
Pooling va stride conv ni bir necha seed bilan taqqoslang.
9. Amaliy topshiriq
Vazifa 1: Bashorat qiling
1. # MaxPool2d(2) parametrlari soni?
2. # (4, 16, 32, 32) MaxPool2d(2) dan keyin?
3. # MaxPool2d(2) 7x7 dan?
4. # MaxPool2d(2, ceil_mode=True) 7x7 dan?
5. # MaxPool2d(3, 2, padding=1) 32x32 dan?
6. # [[1, 3], [5, 6]] max va avg?
7. # MaxPool gradienti oynada qayerga boradi?
8. # AdaptiveAvgPool2d(1) nimaga teng?
9. # 512x7x7 dan 1000 sinf: Flatten+Linear parametrlari?
10. # xuddi shu, GAP+Linear?
11. # qaysi pooling to'liq siljish invariant?
12. # MaxPool2d(2) va Conv2d(C, C, 3, stride=2, padding=1) chiqish o'lchami?Javoblar
- 0
(4, 16, 16, 16)- 3×3
- 4×4
- 16×16
- max 6, avg 3.75
- Faqat maksimum joyiga
x.mean(dim=(2, 3))(shakli(N, C, 1, 1))- 512 × 49 × 1000 + 1000 = 25 089 000
- 512 × 1000 + 1000 = 513 000
- Global (GAP/GMP) — ob'ekt xaritadan chiqmaguncha
- Bir xil — H/2 (juft H da)
Vazifa 2: Xatolarni tuzating
1. nn.Sequential(conv_qismi, nn.Flatten(), nn.Linear(32 * 8 * 8, 10)) # har xil o'lcham
2. gap = f.mean(dim=(1, 2))
3. # 8x8 kirish: [Conv, MaxPool2d(2)] x 4
4. nn.MaxPool2d(2)(torch.rand(1, 8, 7, 7)) # 7-qator ham kerak
5. bbox = nn.Linear(64, 4)(f.mean(dim=(2, 3))) # ob'ekt joyiJavoblar
1. nn.Sequential(conv_qismi, nn.AdaptiveAvgPool2d(1), nn.Flatten(), nn.Linear(32, 10))
2. gap = f.mean(dim=(2, 3))
3. # 8x8 kirish: 2 ta MaxPool2d(2), keyin AdaptiveAvgPool2d(1)
4. nn.MaxPool2d(2, ceil_mode=True)(torch.rand(1, 8, 7, 7))
5. # fazoviy xaritani saqlaydigan bosh (aniqlash mavzusida)Vazifa 3: Ichidan
Modellang:
- Qo'lda max va avg
- Parametrlar va kanallar
- O'lcham formulasi
- Gradient
Vazifa 4: Global pooling
Modellang:
meanbilan tenglik- Istalgan o'lcham
- Bosh parametrlari
- Joyni unutish
Vazifa 5: Invariantlik
Modellang:
- Nisbiy o'zgarish
- Pooling turlari
- Siljish kattaligi
- Juft siljish
Vazifa 6: Taqqoslash
Modellang:
- MaxPool zanjiri
- Stride zanjiri
- Bir necha seed
- Farq va SE
Vazifa 7: O'ylash
Hamkasbingiz aytdi: "Bizning kamera rasmlarida ob'ekt har xil joyda. Shuning uchun har konvolyutsiyadan keyin MaxPool qo'yamiz — tarmoq siljishga invariant bo'ladi, augmentatsiya kerak emas." 3-misol natijalariga tayanib javob bering.
Javob
Qisqa javob: mahalliy MaxPool siljishga invariantlik bermaydi — u faqat oyna ichidagi kichik siljishni qisman "yutadi". Haqiqiy invariantlik tarmoq oxiridagi global pooling va augmentatsiya dan keladi.
3-misol nimani ko'rsatdi:
1 piksel 2 piksel 3,3 piksel
MaxPool 2x2 kamaytirishi 13% 3% -3%
AvgPool 2x2 38% 27% 16%
global pooling 100% 100% 100%- MaxPool 2x2 1 piksel siljishda o'zgarishni atigi 13% ga kamaytirdi. 87% o'zgarish qoldi.
- Siljish kattalashgan sari foyda yo'qoldi: 2 pikselda 3%, (3, 3) da hatto -3% — pooling siz holatdan ham yomon.
- Juft siljishda chiqish aniq 1 ga siljidi — bu ekvivariantlik. Joyma-joy taqqoslasa o'zgarish 0.532 — invariantlik yo'q.
- Global pooling esa hamma siljishda o'zgarmas — ob'ekt xaritadan chiqmaguncha.
Nega shunday: MaxPool faqat maksimum o'z oynasi ichida qolsa o'zgarmaydi. Siljish oyna chegarasidan o'tkazsa, maksimum qo'shni oynaga "ko'chadi" va chiqish boshqa joyda yonadi. Ko'p qatlamli tarmoqda bu kichik chidamlilik biroz to'planadi, lekin to'liq invariantlikka aylanmaydi. Bundan tashqari, stride va pooling ning o'zi aliasing keltirib chiqaradi — 1 pikselli siljish ba'zan tarmoq javobini sezilarli o'zgartiradi.
Nima taklif qilish kerak:
# 1. Arxitektura: conv + pool bloklari, oxirida GAP
nn.Sequential(..., nn.AdaptiveAvgPool2d(1), nn.Flatten(), nn.Linear(64, n))
# 2. Augmentatsiya: tasodifiy siljitish / kesish (21-qism)
def siljit_aug(x, maks=3, g=None):
dy, dx = torch.randint(-maks, maks + 1, (2,), generator=g).tolist()
return torch.roll(x, shifts=(dy, dx), dims=(2, 3))
# 3. Tekshiruv: test to'plamini siljitib aniqlikni o'lchangHamkasbga javob:
"MaxPool siljishni faqat qisman yutadi: 1 piksel siljishda xaritadagi o'zgarishni 13% ga kamaytirdi, 3 pikselda umuman foyda bermadi. Siljishga chidamlilikni tarmoq oxiridagi global pooling va o'rgatishdagi tasodifiy siljitish beradi. Pooling ni o'lchamni kamaytirish uchun qoldiramiz, augmentatsiyani esa albatta qo'shamiz va siljitilgan test to'plamida tekshiramiz."
Nimani mustahkamlaydi: 2.3, 2.4-bo'limlar.
Xulosa
Bu darsda pooling ni ichidan ko'rdik va uning invariantligini o'lchadik.
Eng muhim uch fikr:
Pooling — parametrsiz, kanal bo'yicha alohida kichraytirish. 1-misolda qo'lda yozilgan max va avg pooling
torchbilan aynan teng chiqdi,MaxPool2d(2)ning parametrlari 0,(4, 16, 32, 32)esa(4, 16, 16, 16)ga aylandi. O'lcham formulasi konvolyutsiyaniki bilan bir xil: 7×7 danfloorbilan 3×3,ceil_mode=Truebilan 4×4. Max gradienti faqat maksimum joyiga bordi, avg esa teng 0.25 dan bo'ldi; bitta yorqin nuqtani max 1.0 da saqladi, avg 0.0625 gacha xiralashtirdi.Global average pooling — o'lchamdan ozod va arzon bosh. 2-misolda
AdaptiveAvgPool2d(1)mean(dim=(2, 3))ga teng chiqdi va 32×32, 48×48, 64×64, 33×33 kirishlarning hammasida ishladi,Flattenbosh esa 48×48 va 64×64 daRuntimeErrorberdi. 512×7×7 xaritadan 1000 sinf uchun GAP bosh 513 000 parametr,Flattenbosh 25 089 000 — 49 barobarga yaqin farq. Narxi — joy yo'qoladi: har xil joydagi ikki nuqta bir xil GAP qiymatini 0.0156-bob berdi.Mahalliy pooling siljishga faqat qisman chidamli. 3-misolda 500 ta raqamda MaxPool 2×2 1 piksel siljishdagi o'zgarishni 13% ga, 2 pikselda 3% ga kamaytirdi, (3, 3) siljishda esa -3% — foyda yo'qoldi; AvgPool 2×2 1 pikselda 38% bilan yaxshiroq bo'ldi. Faqat global pooling hamma siljishda 100% invariant chiqdi. 4-misolda
load_digitsda MaxPool 0.9713-bob vastride=2konvolyutsiya 0.9699-bob orasidagi farq -0.0014, SE 0.0035 — shovqin ichida, stride varianti esa 11 568 ta ko'proq parametr talab qildi.
Keyingi darsda birinchi CNN: konvolyutsiya, pooling va global pooling ni bitta modelga yig'ib, uni Trainer bilan to'liq o'rgatamiz va MLP bilan halol taqqoslaymiz.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!