IlmHamroh
Data Science va sun'iy intellekt/Kompyuter korish5/14-dars26 daqiqa
Mundarija (21)

22.5-dars: Birinchi CNN

22-QISM — KOMPYUTER KO'RISH · 5-dars


1. Kirish va motivatsiya

Oldingi to'rt darsda qurilish bloklarini alohida-alohida ko'rdik: 22.1-darsda rasm — bu (C, H, W) shakldagi sonlar massivi ekanini, 22.2-darsda konvolyutsiyani qo'lda hisoblashni, 22.3-darsda nn.Conv2d va retseptiv maydonni, 22.4-darsda pooling ni. Endi ularni bitta tarmoqqa yig'amiz va birinchi marta haqiqiy rasm ma'lumotida o'rgatamiz.

Ma'lumot sifatida sklearn.datasets.load_digits ni olamiz: 1797 ta qo'lda yozilgan raqam, har biri 8×8 piksel, 17 xil yorqinlik darajasi (0–16). Bu juda kichik rasmlar — lekin CNN ning asosiy g'oyalarini ko'rsatish uchun yetarli, va har bir tajriba bir necha soniyada tugaydi.

Bu darsning markaziy savoli: CNN oddiy MLP dan nimasi bilan yaxshi? 20-qismda ko'rgan to'liq bog'langan tarmoq ham rasmni 64 ta sonli vektor sifatida qabul qilib, raqamlarni yaxshi taniydi. Shuning uchun "CNN yaxshiroq" degan da'voni halol tekshiramiz: parametrlar sonini tenglashtiramiz, bir necha seed bilan o'rgatamiz, juftlashgan farq va uning standart xatosini hisoblaymiz (18-qism). Keyin CNN ning haqiqiy ustunligi qayerda ekanini ko'ramiz — siljishga barqarorlikda.

Real vaziyat. Bank chek skanerlaridagi raqamlarni tanish uchun jamoa MLP o'rgatdi: test to'plamida 98% aniqlik. Ishlab chiqarishda esa aniqlik keskin tushib ketdi. Sabab: yangi skanerlar raqamni kadrda bir-ikki piksel boshqa joyga qo'yardi. Test to'plami o'quv to'plami bilan bir xil kesilgan edi, shuning uchun bu zaiflik baholashda ko'rinmadi. Bu darsning 3-misoli aynan shu holatni o'lchaydi.

Bu darsda birinchi CNN ni quramiz va uni MLP bilan halol taqqoslaymiz.

Bu darsda:

  • Nima uchun rasm uchun konvolyutsiya
  • Birinchi CNN va shakllar zanjiri
  • Parametrlar hisobi
  • Halol taqqoslash: parametr, seed, juftlashgan farq
  • Siljishga barqarorlik: ekvivariantlik va invariantlik
  • Chalkashlik matritsasi va xatolar tahlili
  • Tuzoqlar

ℹ Misollar real torch/numpy bilan (Python 3.14, torch 2.14 CPU).


2. Nazariya — chuqur tushuntirish

2.1. Nima uchun rasm uchun konvolyutsiya

text
MLP RASMNI QANDAY KO'RADI:
  8x8 rasm -> 64 ta son (flatten)
  har yashirin neyron 64 pikselning HAMMASIGA o'z og'irligi bilan bog'langan
  piksel (2, 3) va (2, 4) qo'shni ekanini MLP BILMAYDI
  piksellarni istalgan qat'iy tartibda aralashtirsak - MLP uchun farqi yo'q

RASMNING TUZILISHI:
  1. lokallik     - ma'no qo'shni piksellardan chiqadi (chiziq, burchak)
  2. takrorlanish - bir xil naqsh (vertikal chiziq) rasmning istalgan joyida
  3. ierarxiya    - chiziqlar -> shakllar -> raqam

CNN BU TUZILISHNI ARXITEKTURAGA QO'YADI:
  lokal bog'lanish   - har chiqish faqat k x k qo'shnilikni ko'radi
  og'irlik ulashish  - bitta filtr butun rasm bo'ylab yuradi
  qatlamlar ketma-ketligi - retseptiv maydon kengayadi 22.3-bob

NATIJA:
  kamroq parametr, kuchliroq "oldindan taxmin" (inductive bias)
  siljishga ekvivariant konvolyutsiya (2.5)

CNN rasm haqidagi bilimni arxitekturaga joylaydi — MLP esa uni ma'lumotdan noldan o'rganishi kerak.

2.2. Birinchi CNN va shakllar zanjiri

text
KIRISH: (B, 1, 8, 8)   B - batch, 1 - kanal (kulrang), 8x8

nn.Conv2d(1, 16, 3, padding=1)  -> (B, 16, 8, 8)   padding=1: o'lcham saqlanadi
nn.ReLU()                       -> (B, 16, 8, 8)
nn.MaxPool2d(2)                 -> (B, 16, 4, 4)   har o'q 2 barobar kichik
nn.Conv2d(16, 32, 3, padding=1) -> (B, 32, 4, 4)
nn.ReLU()                       -> (B, 32, 4, 4)
nn.MaxPool2d(2)                 -> (B, 32, 2, 2)
nn.Flatten()                    -> (B, 128)        32 * 2 * 2
nn.Linear(128, 10)              -> (B, 10)         logitlar

ODATIY NAQSH:
  [Conv -> ReLU -> Pool] x N  ->  Flatten  ->  Linear
  fazoviy o'lcham kichrayadi, kanallar soni o'sadi
  "qayerda" ma'lumoti -> "nima" ma'lumotiga almashadi

SHAKLNI TEKSHIRISH:
  for qatlam in model: x = qatlam(x); print(qatlam, x.shape)
  Linear ning kirish o'lchami (128) aynan shunday topiladi

Shakllar zanjirini har doim chop eting — Linear ning kirish o'lchamidagi xato CNN dagi eng ko'p uchraydigan xato.

2.3. Parametrlar hisobi

text
Conv2d(C_kir, C_chiq, k):
  og'irlik: C_chiq * C_kir * k * k
  bias:     C_chiq
  RASM O'LCHAMIGA BOG'LIQ EMAS (og'irlik ulashish)

Linear(n_kir, n_chiq):
  n_kir * n_chiq + n_chiq

BIZNING CNN:
  Conv2d(1, 16, 3):   16*1*9  + 16 =  160
  Conv2d(16, 32, 3):  32*16*9 + 32 = 4640
  Linear(128, 10):    128*10  + 10 = 1290
  JAMI:                              6090

MLP 64 -> h -> 10:
  64*h + h + h*10 + 10 = 75h + 10
  h = 80 -> 6010  (CNN ga deyarli teng)

DIQQAT:
  8x8 rasmda farq kichik
  224x224x3 rasmda MLP ning birinchi qatlami: 150528 * h
  h = 1000 bo'lsa 150 million parametr - bitta qatlamda
  shu rasmda Conv2d(3, 64, 3) - atigi 1792 parametr

Konvolyutsiya parametrlari rasm o'lchamiga bog'liq emas — katta rasmda aynan shu hal qiluvchi.

2.4. Halol taqqoslash

text
NOHALOL TAQQOSLASH (ko'p uchraydi):
  CNN 100k parametr, MLP 5k parametr -> "CNN yaxshi"
  CNN 3 seed ichidan eng yaxshisi, MLP bitta seed
  CNN uchun lr sozlangan, MLP uchun standart

HALOL TAQQOSLASH:
  1. parametr soni taxminan TENG (yoki ikkala tomonga ham katta variant)
  2. bir xil bo'linish, bir xil davrlar, bir xil optimizator
  3. bir necha seed (3-5)
  4. juftlashgan farq: har seed da  d_s = aniq_CNN_s - aniq_MLP_s
     o'rtacha d, SE = std(d) / sqrt(n)
     |o'rtacha d| > 2 * SE  ->  farq sezilarli (taxminiy qoida)

NIMA UCHUN JUFTLASHGAN:
  bir seed da ikkala model bir xil tartibda ma'lumot ko'radi
  seed ta'siri qisman kamayadi -> farq aniqroq baholanadi

XULOSANI KOD YOZSIN:
  if abs(d) <= 2*se: "farq sezilarli emas"
  "CNN ustun" deb qattiq yozilgan matn - xato manbai

Taqqoslash natijasi bitta raqam emas, farq va uning SE si — 18-qismdagi qoida bu yerda ham amal qiladi.

2.5. Siljishga barqarorlik: ekvivariantlik va invariantlik

text
EKVIVARIANTLIK (konvolyutsiya):
  kirishni siljitsak -> chiqish ham XUDDI SHUNCHA siljiydi
  conv(siljit(x)) = siljit(conv(x))       (chegaradan tashqari)
  sabab: bitta filtr hamma joyda bir xil

INVARIANTLIK (pooling va oxirgi qatlamlar):
  kirishni siljitsak -> chiqish O'ZGARMAYDI
  MaxPool2d(2) kichik siljishlarga QISMAN invariant
  (siljish oyna ichida qolsa - maksimum o'zgarmaydi)

TO'LIQ INVARIANTLIK YO'Q:
  Flatten + Linear har joyga o'z og'irligini beradi
  -> katta siljish CNN ni ham adashtiradi
  global average pooling 22.6-bob invariantlikni kuchaytiradi

MLP:
  na ekvivariant, na invariant
  1 piksel siljish -> 64 ta kirishning deyarli hammasi o'zgaradi
  MLP uchun bu butunlay yangi vektor

8x8 RASMDA:
  1 piksel = rasm kengligining 12.5%
  2 piksel = 25% - bu KATTA siljish, ikkala model ham yomonlashadi

Konvolyutsiya siljishga ekvivariant, pooling qisman invariant — MLP da bu xossalar umuman yo'q.

2.6. Chalkashlik matritsasi va xatolar tahlili

text
UMUMIY ANIQLIK YASHIRADI:
  98% aniqlik - lekin qaysi 2% xato?
  bitta sinf 90%, qolganlari 99% bo'lishi mumkin

CHALKASHLIK MATRITSASI (14-qism):
  M[i, j] = haqiqiy i, bashorat j bo'lgan namunalar soni
  diagonal - to'g'ri, diagonaldan tashqari - xato
  sinf bo'yicha recall = M[i, i] / M[i, :].sum()

XATOLARNI KO'ZDAN KECHIRISH:
  xato qilingan rasmlarni CHIZIB ko'ring
  ko'pincha: yorliq xatosi, noaniq yozuv, haqiqatan o'xshash sinflar
  modelning ishonchi (softmax) ham ko'rsating:
    yuqori ishonch bilan xato -> tekshirish kerak (yorliq xatosi?)
    past ishonch bilan xato  -> noaniq namuna

KEYINGI QADAM:
  eng ko'p chalkashgan juftlik (masalan 8 va 1) -> ma'lumot yoki
  augmentatsiya 22.8-bob shu juftlikka qaratiladi

Xatolarni raqam bilan emas, rasm bilan tahlil qiling — ko'pincha sabab bir qarashda ko'rinadi.

2.7. Tuzoqlar

Asosiy tuzoqlar: kanal o'qini unutish ((B, 8, 8) o'rniga (B, 1, 8, 8) kerak); Linear kirish o'lchamini qo'lda noto'g'ri hisoblash; piksellarni masshtablamaslik (0–16 o'rniga 0–1); CNN va MLP ni turli parametr soni bilan taqqoslash; bitta seed bilan "CNN yaxshi" deyish; test to'plamida siljish yo'q deb barqarorlikni tekshirmaslik; faqat umumiy aniqlikka qarab, sinflar bo'yicha xatoni ko'rmaslik; model.eval() va torch.no_grad() siz baholash.


3. Tez ma'lumotnoma

python
import numpy as np
import torch
import torch.nn as nn
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split

d = load_digits()
X = (d.images / 16.0).astype(np.float32)          # (1797, 8, 8), 0..1
Xtr, Xte, ytr, yte = train_test_split(X, d.target, test_size=0.3,
                                      random_state=0, stratify=d.target)
Xtr = torch.tensor(Xtr).unsqueeze(1)              # (N, 1, 8, 8)

model = 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.Flatten(), nn.Linear(32 * 2 * 2, 10))

x = torch.zeros(1, 1, 8, 8)
for qatlam in model:
    x = qatlam(x)
    print(type(qatlam).__name__, tuple(x.shape))

param_soni = sum(p.numel() for p in model.parameters())

Birinchi CNN xulosasi

kirish (B, 1, H, W), piksellar 0..1
[Conv -> ReLU -> Pool] x N -> Flatten -> Linear
shakllar zanjirini chop eting
MLP bilan: teng parametr, bir necha seed, juftlashgan farq + SE
siljish va sinflar bo'yicha xatoni alohida tekshiring

4. Batafsil misollar

Misollar real torch/numpy bilan (Python 3.14, torch 2.14 CPU).

Misol 1 — Birinchi CNN: shakllar zanjiri va o'rgatish

python
"""load_digits da birinchi CNN: shakllar, parametrlar, o'rgatish."""

import numpy as np
import torch
import torch.nn as nn
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split


def cnn_yarat():
    return 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.Flatten(), nn.Linear(32 * 2 * 2, 10))


def aniqlik(model, X, y):
    model.eval()
    with torch.no_grad():
        return (model(X).argmax(1) == y).float().mean().item()


def main() -> None:
    d = load_digits()
    X = (d.images / 16.0).astype(np.float32)
    Xtr, Xte, ytr, yte = train_test_split(X, d.target, test_size=0.3,
                                          random_state=0, stratify=d.target)
    Xtr = torch.tensor(Xtr).unsqueeze(1)
    Xte = torch.tensor(Xte).unsqueeze(1)
    ytr, yte = torch.tensor(ytr), torch.tensor(yte)

    print("=== 1. Ma'lumot ===")
    print(f"  xom rasmlar: {d.images.shape}, qiymatlar "
          f"{d.images.min():.0f}..{d.images.max():.0f}")
    print(f"  o'quv tensori: {tuple(Xtr.shape)}  (N, kanal, H, W)")
    print(f"  test tensori:  {tuple(Xte.shape)}")
    print(f"  masshtab: {Xtr.min().item():.1f}..{Xtr.max().item():.1f}")

    print("\n=== 2. Shakllar zanjiri ===")
    torch.manual_seed(0)
    model = cnn_yarat()
    x = Xtr[:4]
    print(f"  {'kirish':<41} {str(tuple(x.shape)):>16}")
    for qatlam in model:
        x = qatlam(x)
        n = sum(p.numel() for p in qatlam.parameters())
        nom = repr(qatlam).split("(")[0]
        print(f"  {nom:<12} {n:>6} parametr {'':>12} "
              f"{str(tuple(x.shape)):>16}")
    jami = sum(p.numel() for p in model.parameters())
    print(f"  jami parametr: {jami}")

    print("\n=== 3. O'rgatish (Adam, lr=0.003, batch 64) ===")
    opt = torch.optim.Adam(model.parameters(), lr=0.003)
    g = torch.Generator().manual_seed(0)
    print(f"  {'davr':>5} {'o_quv loss':>11} {'o_quv aniq':>11} "
          f"{'test aniq':>10}")
    for davr in range(1, 31):
        model.train()
        tartib = torch.randperm(len(ytr), generator=g)
        jami_loss = 0.0
        for i in range(0, len(ytr), 64):
            idx = tartib[i:i + 64]
            opt.zero_grad()
            loss = nn.functional.cross_entropy(model(Xtr[idx]), ytr[idx])
            loss.backward()
            opt.step()
            jami_loss += loss.item() * len(idx)
        if davr in (1, 2, 5, 10, 20, 30):
            print(f"  {davr:>5} {jami_loss / len(ytr):>11.4f} "
                  f"{aniqlik(model, Xtr, ytr):>11.4f} "
                  f"{aniqlik(model, Xte, yte):>10.4f}")

    print("\n=== 4. Bitta bashorat ===")
    model.eval()
    with torch.no_grad():
        p = torch.softmax(model(Xte[:1]), 1)[0]
    top = p.topk(3)
    print(f"  haqiqiy: {int(yte[0])}")
    for ehtimol, sinf in zip(top.values, top.indices):
        print(f"  sinf {int(sinf)}: {ehtimol.item():.4f}")
    oquv = aniqlik(model, Xtr, ytr)
    test = aniqlik(model, Xte, yte)
    print(f"\n  yakuniy: o'quv {oquv:.4f}, test {test:.4f}, "
          f"farq {oquv - test:.4f}")
    if oquv - test > 0.05:
        print("  o'quv va test orasida katta farq - yodlash belgisi")
    else:
        print("  o'quv va test yaqin - kuchli yodlash yo'q")
    print("  ⭐ 6090 parametrli CNN 8x8 raqamlarni ishonchli taniydi")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Ma'lumot ===
  xom rasmlar: (1797, 8, 8), qiymatlar 0..16
  o'quv tensori: (1257, 1, 8, 8)  (N, kanal, H, W)
  test tensori:  (540, 1, 8, 8)
  masshtab: 0.0..1.0

=== 2. Shakllar zanjiri ===
  kirish                                        (4, 1, 8, 8)
  Conv2d          160 parametr                 (4, 16, 8, 8)
  ReLU              0 parametr                 (4, 16, 8, 8)
  MaxPool2d         0 parametr                 (4, 16, 4, 4)
  Conv2d         4640 parametr                 (4, 32, 4, 4)
  ReLU              0 parametr                 (4, 32, 4, 4)
  MaxPool2d         0 parametr                 (4, 32, 2, 2)
  Flatten           0 parametr                      (4, 128)
  Linear         1290 parametr                       (4, 10)
  jami parametr: 6090

=== 3. O'rgatish (Adam, lr=0.003, batch 64) ===
   davr  o_quv loss  o_quv aniq  test aniq
      1      2.1906      0.7629     0.7519
      2      1.5956      0.8250     0.8222
      5      0.2158      0.9507     0.9444
     10      0.0760      0.9833     0.9741
     20      0.0195      0.9968     0.9778
     30      0.0087      0.9992     0.9796

=== 4. Bitta bashorat ===
  haqiqiy: 1
  sinf 1: 0.9561
  sinf 8: 0.0418
  sinf 4: 0.0020

  yakuniy: o'quv 0.9992, test 0.9796, farq 0.0196
  o'quv va test yaqin - kuchli yodlash yo'q
  ⭐ 6090 parametrli CNN 8x8 raqamlarni ishonchli taniydi

Nima ko'rsatdi: 2.2, 2.3-bo'limlar.

Misol 2 — CNN va MLP: halol taqqoslash

python
"""Teng parametrli CNN va MLP: bir necha seed, juftlashgan farq."""

import numpy as np
import torch
import torch.nn as nn
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split


def cnn_yarat():
    return 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.Flatten(), nn.Linear(32 * 2 * 2, 10))


def mlp_yarat(h):
    return nn.Sequential(nn.Flatten(), nn.Linear(64, h), nn.ReLU(),
                         nn.Linear(h, 10))


def orgat(model, X, y, seed, davrlar=30):
    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()
            nn.functional.cross_entropy(model(X[idx]), y[idx]).backward()
            opt.step()
    model.eval()
    return model


def aniqlik(model, X, y):
    with torch.no_grad():
        return (model(X).argmax(1) == y).float().mean().item()


def main() -> None:
    d = load_digits()
    X = (d.images / 16.0).astype(np.float32)
    Xtr, Xte, ytr, yte = train_test_split(X, d.target, test_size=0.3,
                                          random_state=0, stratify=d.target)
    Xtr = torch.tensor(Xtr).unsqueeze(1)
    Xte = torch.tensor(Xte).unsqueeze(1)
    ytr, yte = torch.tensor(ytr), torch.tensor(yte)

    modellar = {"CNN": cnn_yarat,
                "MLP h=80": lambda: mlp_yarat(80),
                "MLP h=256": lambda: mlp_yarat(256)}
    seedlar = [0, 1, 2, 3]

    print("=== 1. Parametrlar soni ===")
    for nom, yasa in modellar.items():
        n = sum(p.numel() for p in yasa().parameters())
        print(f"  {nom:<10} {n:>7}")

    print("\n=== 2. Test aniqligi (har seed) ===")
    natija = {nom: [] for nom in modellar}
    for s in seedlar:
        for nom, yasa in modellar.items():
            torch.manual_seed(s)
            m = orgat(yasa(), Xtr, ytr, s)
            natija[nom].append(aniqlik(m, Xte, yte))
    print(f"  {'seed':>5} " + " ".join(f"{n:>10}" for n in modellar))
    for k, s in enumerate(seedlar):
        print(f"  {s:>5} " + " ".join(f"{natija[n][k]:>10.4f}"
                                      for n in modellar))
    print(f"  {'o_rt':>5} " + " ".join(f"{np.mean(natija[n]):>10.4f}"
                                      for n in modellar))

    print("\n=== 3. Juftlashgan farq (CNN - MLP) ===")
    cnn = np.array(natija["CNN"])
    print(f"  {'raqib':<10} {'o_rt farq':>10} {'SE':>8} {'xulosa':>28}")
    for nom in ["MLP h=80", "MLP h=256"]:
        farq = cnn - np.array(natija[nom])
        se = farq.std(ddof=1) / np.sqrt(len(farq))
        if abs(farq.mean()) <= 2 * se:
            xulosa = "sezilarli farq yo'q"
        elif farq.mean() > 0:
            xulosa = "CNN sezilarli yaxshi"
        else:
            xulosa = "MLP sezilarli yaxshi"
        print(f"  {nom:<10} {farq.mean():>+10.4f} {se:>8.4f} {xulosa:>28}")
    xato_cnn = 1 - cnn.mean()
    xato_mlp = 1 - np.mean(natija["MLP h=80"])
    print(f"\n  xato ulushi: CNN {xato_cnn:.4f}, MLP h=80 {xato_mlp:.4f}")
    if xato_cnn < xato_mlp:
        print(f"  CNN xatolari soni MLP xatolarining {xato_cnn / xato_mlp:.0%} "
              f"qismini tashkil etadi")
    else:
        print("  CNN xatolari MLP xatolaridan kam emas")
    print("  8x8 markazlangan raqamlarda ikkala model ham 97% dan yuqori")
    print("  ⭐ Farq kichik bo'lsa ham SE bilan tekshirilgan farq - fakt")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Parametrlar soni ===
  CNN           6090
  MLP h=80      6010
  MLP h=256    19210

=== 2. Test aniqligi (har seed) ===
   seed        CNN   MLP h=80  MLP h=256
      0     0.9796     0.9778     0.9778
      1     0.9833     0.9778     0.9796
      2     0.9870     0.9759     0.9815
      3     0.9852     0.9759     0.9796
   o_rt     0.9838     0.9769     0.9796

=== 3. Juftlashgan farq (CNN - MLP) ===
  raqib       o_rt farq       SE                       xulosa
  MLP h=80      +0.0069   0.0021         CNN sezilarli yaxshi
  MLP h=256     +0.0042   0.0009         CNN sezilarli yaxshi

  xato ulushi: CNN 0.0162, MLP h=80 0.0231
  CNN xatolari soni MLP xatolarining 70% qismini tashkil etadi
  8x8 markazlangan raqamlarda ikkala model ham 97% dan yuqori
  ⭐ Farq kichik bo'lsa ham SE bilan tekshirilgan farq - fakt

Nima ko'rsatdi: 2.3, 2.4-bo'limlar.

Misol 3 — Siljishga barqarorlik

python
"""Test rasmlarini 1-2 piksel siljitsak CNN va MLP qanday o'zgaradi."""

import numpy as np
import torch
import torch.nn as nn
from scipy import ndimage
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split


def cnn_yarat():
    return 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.Flatten(), nn.Linear(32 * 2 * 2, 10))


def mlp_yarat():
    return nn.Sequential(nn.Flatten(), nn.Linear(64, 80), nn.ReLU(),
                         nn.Linear(80, 10))


def orgat(model, X, y, seed, davrlar=30):
    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()
            nn.functional.cross_entropy(model(X[idx]), y[idx]).backward()
            opt.step()
    model.eval()
    return model


def aniqlik(model, X, y):
    with torch.no_grad():
        return (model(X).argmax(1) == y).float().mean().item()


def siljit(X, dy, dx):
    """Butun piksel siljish, bo'shagan joy 0 bilan to'ldiriladi."""
    return np.stack([ndimage.shift(x, (dy, dx), order=0, mode="constant")
                     for x in X])


def main() -> None:
    d = load_digits()
    X = (d.images / 16.0).astype(np.float32)
    Xtr, Xte, ytr, yte = train_test_split(X, d.target, test_size=0.3,
                                          random_state=0, stratify=d.target)
    T = lambda a: torch.tensor(a).unsqueeze(1)
    Xtr_t, Xte_t = T(Xtr), T(Xte)
    ytr_t, yte_t = torch.tensor(ytr), torch.tensor(yte)

    print("=== 1. Konvolyutsiya ekvivariantligi ===")
    torch.manual_seed(0)
    conv = nn.Conv2d(1, 4, 3, padding=1)
    x = Xte_t[:1]
    xs = T(siljit(Xte[:1], 0, 1))
    with torch.no_grad():
        a = conv(xs)
        b = torch.roll(conv(x), 1, dims=3)
    ichki = (a - b)[..., 2:-2].abs().max().item()
    print(f"  conv(siljit(x)) va siljit(conv(x)) ichki farqi: {ichki:.2e}")
    print("  (chegara ustunlari hisobga olinmadi)")
    with torch.no_grad():
        p1 = nn.MaxPool2d(2)(torch.relu(conv(x)))
        p2 = nn.MaxPool2d(2)(torch.relu(conv(xs)))
    ozgardi = (p1 - p2).abs().gt(1e-6).float().mean().item()
    print(f"  pooling dan keyin 1 piksel siljishda o'zgargan qiymatlar: "
          f"{ozgardi:.1%}")
    print("  pooling faqat QISMAN invariant")

    print("\n=== 2. Siljitilgan test to'plamlari ===")
    yonalishlar = {1: [(0, 1), (0, -1), (1, 0), (-1, 0)],
                   2: [(0, 2), (0, -2), (2, 0), (-2, 0)]}
    toplamlar = {0: [Xte_t]}
    for k, yon in yonalishlar.items():
        toplamlar[k] = [T(siljit(Xte, dy, dx)) for dy, dx in yon]
    for k in (1, 2):
        chiqqan = np.mean([(np.abs(siljit(Xte, dy, dx)).sum((1, 2))
                            < np.abs(Xte).sum((1, 2)) - 1e-6).mean()
                           for dy, dx in yonalishlar[k]])
        print(f"  {k} piksel: siyohning bir qismi kadrdan chiqqan rasmlar "
              f"{chiqqan:.1%}")

    print("\n=== 3. Aniqlik (3 seed, 4 yo'nalish o'rtachasi) ===")
    natija = {"CNN": {k: [] for k in toplamlar},
              "MLP": {k: [] for k in toplamlar}}
    for s in range(3):
        for nom, yasa in [("CNN", cnn_yarat), ("MLP", mlp_yarat)]:
            torch.manual_seed(s)
            m = orgat(yasa(), Xtr_t, ytr_t, s)
            for k, lst in toplamlar.items():
                natija[nom][k].append(np.mean([aniqlik(m, Z, yte_t)
                                               for Z in lst]))
    print(f"  {'siljish':>8} {'CNN':>8} {'MLP':>8} {'farq':>8} {'SE':>7} "
          f"{'sezilarli':>10}")
    for k in toplamlar:
        c = np.array(natija["CNN"][k])
        m = np.array(natija["MLP"][k])
        farq = c - m
        se = farq.std(ddof=1) / np.sqrt(len(farq))
        print(f"  {k:>6}px {c.mean():>8.4f} {m.mean():>8.4f} "
              f"{farq.mean():>+8.4f} {se:>7.4f} "
              f"{str(abs(farq.mean()) > 2 * se):>10}")

    print("\n=== 4. Nisbiy yo'qotish ===")
    for nom in ["CNN", "MLP"]:
        t0 = np.mean(natija[nom][0])
        t1 = np.mean(natija[nom][1])
        t2 = np.mean(natija[nom][2])
        print(f"  {nom}: 1px da aniqlikning {1 - t1 / t0:.0%} qismi, "
              f"2px da {1 - t2 / t0:.0%} qismi yo'qoldi")
    c1 = np.mean(natija["CNN"][1])
    m1 = np.mean(natija["MLP"][1])
    if c1 > m1:
        print(f"  1px siljishda CNN MLP dan {c1 - m1:.2f} ga yuqori")
    else:
        print("  1px siljishda CNN ustunlik ko'rsatmadi")
    if c1 < 0.9:
        print("  lekin CNN ham kuchli yomonlashdi: to'liq invariantlik YO'Q")
    print("  ⭐ Barqarorlikni alohida o'lchang - toza test uni ko'rsatmaydi")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Konvolyutsiya ekvivariantligi ===
  conv(siljit(x)) va siljit(conv(x)) ichki farqi: 0.00e+00
  (chegara ustunlari hisobga olinmadi)
  pooling dan keyin 1 piksel siljishda o'zgargan qiymatlar: 46.9%
  pooling faqat QISMAN invariant

=== 2. Siljitilgan test to'plamlari ===
  1 piksel: siyohning bir qismi kadrdan chiqqan rasmlar 53.8%
  2 piksel: siyohning bir qismi kadrdan chiqqan rasmlar 94.2%

=== 3. Aniqlik (3 seed, 4 yo'nalish o'rtachasi) ===
   siljish      CNN      MLP     farq      SE  sezilarli
       0px   0.9833   0.9772  +0.0062  0.0027       True
       1px   0.6446   0.4606  +0.1840  0.0161       True
       2px   0.2282   0.1136  +0.1147  0.0129       True

=== 4. Nisbiy yo'qotish ===
  CNN: 1px da aniqlikning 34% qismi, 2px da 77% qismi yo'qoldi
  MLP: 1px da aniqlikning 53% qismi, 2px da 88% qismi yo'qoldi
  1px siljishda CNN MLP dan 0.18 ga yuqori
  lekin CNN ham kuchli yomonlashdi: to'liq invariantlik YO'Q
  ⭐ Barqarorlikni alohida o'lchang - toza test uni ko'rsatmaydi

Nima ko'rsatdi: 2.5-bo'lim.

Misol 4 — Chalkashlik matritsasi va xato qilingan misollar

python
"""CNN qaysi raqamlarni adashtiradi - matritsa va rasmlar."""

import numpy as np
import torch
import torch.nn as nn
from sklearn.datasets import load_digits
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import train_test_split


def cnn_yarat():
    return 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.Flatten(), nn.Linear(32 * 2 * 2, 10))


def orgat(model, X, y, seed, davrlar=30):
    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()
            nn.functional.cross_entropy(model(X[idx]), y[idx]).backward()
            opt.step()
    model.eval()
    return model


def chiz(rasm):
    belgilar = " .:+#"
    qatorlar = []
    for satr in rasm:
        qatorlar.append("".join(belgilar[min(4, int(v * 5))] * 2
                                for v in satr))
    return qatorlar


def main() -> None:
    d = load_digits()
    X = (d.images / 16.0).astype(np.float32)
    Xtr, Xte, ytr, yte = train_test_split(X, d.target, test_size=0.3,
                                          random_state=0, stratify=d.target)
    Xtr_t = torch.tensor(Xtr).unsqueeze(1)
    Xte_t = torch.tensor(Xte).unsqueeze(1)
    torch.manual_seed(0)
    model = orgat(cnn_yarat(), Xtr_t, torch.tensor(ytr), seed=0)
    with torch.no_grad():
        p = torch.softmax(model(Xte_t), 1).numpy()
    bashorat = p.argmax(1)

    print("=== 1. Chalkashlik matritsasi (qator - haqiqiy) ===")
    M = confusion_matrix(yte, bashorat)
    print("       " + "".join(f"{j:>4}" for j in range(10)))
    for i in range(10):
        print(f"  {i:>3}: " + "".join(f"{M[i, j]:>4}" for j in range(10)))
    print(f"  jami aniqlik: {np.trace(M) / M.sum():.4f}, "
          f"xatolar: {M.sum() - np.trace(M)} / {M.sum()}")

    print("\n=== 2. Sinflar bo'yicha recall ===")
    recall = M.diagonal() / M.sum(1)
    tartib = np.argsort(recall)
    for i in tartib[:4]:
        print(f"  raqam {i}: {recall[i]:.4f}")
    print(f"  eng yaxshi: raqam {tartib[-1]} ({recall[tartib[-1]]:.4f})")
    print(f"  sinflar orasidagi oraliq: {recall.max() - recall.min():.4f}")

    print("\n=== 3. Eng ko'p chalkashgan juftliklar ===")
    Mx = M.copy()
    np.fill_diagonal(Mx, 0)
    juftlar = sorted(((Mx[i, j], i, j) for i in range(10)
                      for j in range(10) if Mx[i, j] > 0), reverse=True)
    for soni, i, j in juftlar[:4]:
        print(f"  haqiqiy {i} -> bashorat {j}: {soni} marta")

    print("\n=== 4. Xato qilingan rasmlar ===")
    xato = np.where(bashorat != yte)[0]
    ishonch = p[xato, bashorat[xato]]
    tanlov = xato[np.argsort(-ishonch)[:3]]
    rasmlar = [chiz(Xte[i]) for i in tanlov]
    sarlavha = [f"h={yte[i]} b={bashorat[i]} p={p[i, bashorat[i]]:.2f}"
                for i in tanlov]
    print("  " + "   ".join(f"{s:<16}" for s in sarlavha))
    for q in range(8):
        print("  " + "   ".join(f"{r[q]:<16}" for r in rasmlar))
    yuqori = int((ishonch > 0.9).sum())
    print(f"\n  xatolardan {yuqori} tasi 0.9 dan yuqori ishonch bilan")
    print(f"  xatolardagi o'rtacha ishonch: {ishonch.mean():.3f}")
    togri = np.where(bashorat == yte)[0]
    print(f"  to'g'ri javoblardagi o'rtacha ishonch: "
          f"{p[togri, bashorat[togri]].mean():.3f}")
    print("  ⭐ Xatolarni ko'zdan kechiring - sabab ko'pincha rasmning o'zida")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Chalkashlik matritsasi (qator - haqiqiy) ===
          0   1   2   3   4   5   6   7   8   9
    0:   54   0   0   0   0   0   0   0   0   0
    1:    0  53   0   0   0   0   0   0   2   0
    2:    0   1  52   0   0   0   0   0   0   0
    3:    0   0   0  52   0   0   0   0   1   2
    4:    0   0   0   0  54   0   0   0   0   0
    5:    0   0   0   1   0  54   0   0   0   0
    6:    0   1   0   0   0   0  53   0   0   0
    7:    0   0   0   0   0   0   0  54   0   0
    8:    0   1   0   0   0   0   0   1  50   0
    9:    0   0   0   0   0   0   0   0   1  53
  jami aniqlik: 0.9796, xatolar: 11 / 540

=== 2. Sinflar bo'yicha recall ===
  raqam 3: 0.9455
  raqam 8: 0.9615
  raqam 1: 0.9636
  raqam 2: 0.9811
  eng yaxshi: raqam 4 1.0000-bob
  sinflar orasidagi oraliq: 0.0545

=== 3. Eng ko'p chalkashgan juftliklar ===
  haqiqiy 3 -> bashorat 9: 2 marta
  haqiqiy 1 -> bashorat 8: 2 marta
  haqiqiy 9 -> bashorat 8: 1 marta
  haqiqiy 8 -> bashorat 7: 1 marta

=== 4. Xato qilingan rasmlar ===
  h=8 b=1 p=0.79     h=3 b=9 p=0.72     h=9 b=8 p=0.64
        ::::             ..##::               ++##++
      ..####             ######             ##::::##
    ..##++##..           ##++##           ::::  ::++
    ..##++##             ..####::         ::::  ####
      ######               ....##..         ####::##
        ##++::                 ##::               ::..
      ..##  ++##         ++::::##..         ..##..::::
        ++++::           ::####++             ++####..

  xatolardan 0 tasi 0.9 dan yuqori ishonch bilan
  xatolardagi o'rtacha ishonch: 0.603
  to'g'ri javoblardagi o'rtacha ishonch: 0.990
  ⭐ Xatolarni ko'zdan kechiring - sabab ko'pincha rasmning o'zida

Nima ko'rsatdi: 2.6-bo'lim.


5. To'g'ri va noto'g'ri tushunishlar

Noto'g'ri fikr To'g'risi
"CNN har doim MLP dan ancha yaxshi" Kichik markazlangan rasmda farq kichik — o'lchash kerak
"Ko'proq parametr — shuning uchun CNN yutdi" Halol taqqoslashda parametr teng qilinadi
"CNN siljishga to'liq invariant" Konvolyutsiya ekvivariant, pooling qisman invariant
"Bitta seed yetarli" Seed farqi model farqidan katta bo'lishi mumkin
"Test aniqligi 98% — ishlab chiqarishga tayyor" Siljish kabi o'zgarishlarni alohida tekshiring
"Conv2d parametrlari rasm o'lchami bilan o'sadi" Faqat kanal va yadro o'lchamiga bog'liq
"Kanal o'qi ixtiyoriy" Conv2d (B, C, H, W) kutadi
"Umumiy aniqlik hammasini aytadi" Sinflar bo'yicha recall va xato rasmlari kerak

6. Keng tarqalgan xatolar va yechimlari

1. Kanal o'qi yo'q

python
model(torch.tensor(Xtr))                     # (N, 8, 8)       # ⚠️
model(torch.tensor(Xtr).unsqueeze(1))        # (N, 1, 8, 8)    # ✅

2. Linear kirishi qo'lda noto'g'ri

python
nn.Linear(32 * 8 * 8, 10)    # ikki pooling unutilgan          # ⚠️
nn.Linear(32 * 2 * 2, 10)    # shakllar zanjiridan olingan     # ✅

3. Masshtablanmagan piksellar

python
X = d.images.astype(np.float32)              # 0..16           # ⚠️
X = (d.images / 16.0).astype(np.float32)     # 0..1            # ✅

4. Teng bo'lmagan taqqoslash

python
# CNN 100k parametr va MLP 5k parametr                         # ⚠️
# parametr soni taxminan teng + katta variant ham               # ✅

5. Bitta seed

python
aniq_cnn > aniq_mlp  # bitta ishga tushirish                   # ⚠️
farq = cnn_s - mlp_s; abs(farq.mean()) > 2 * se                # ✅

6. np.roll bilan siljitish

python
np.roll(x, 1, axis=1)        # o'ng chet chapga o'tadi          # ⚠️
ndimage.shift(x, (0, 1), order=0, mode="constant")             # ✅

7. eval siz baholash

python
aniq = (model(Xte).argmax(1) == yte).float().mean()            # ⚠️
model.eval()
with torch.no_grad(): aniq = ...                               # ✅

7. Integratsiya — bu bilim qayerda kerak bo'ladi

  • 20-qism (o'tilgan): MLP, orqaga tarqalish, yo'qotish funksiyalari
  • 21.5-dars (o'tilgan): Trainer — bu darsdagi o'rgatish sikli uning soddalashgan shakli
  • 18-qism (o'tilgan): Juftlashgan taqqoslash va standart xato
  • 22.3, 22.4-darslar (o'tilgan): nn.Conv2d, retseptiv maydon, pooling
  • Keyingi darslar: CNN arxitekturalari, chuqur CNN ni o'rgatish, rasm augmentatsiyasi, transfer learning

8. Eng yaxshi amaliyotlar

  1. Kirishni (B, C, H, W) shaklga keltiring va 0–1 ga masshtablang.

  2. Shakllar zanjirini chop eting.

  3. Parametrlar sonini hisoblang va hisobotda ko'rsating.

  4. Bazaviy model (MLP yoki logistik regressiya) bilan taqqoslang.

  5. Teng parametr, bir necha seed, juftlashgan farq + SE.

  6. Siljish kabi real o'zgarishlarga barqarorlikni alohida o'lchang.

  7. Sinflar bo'yicha recall va chalkashlik matritsasini ko'ring.

  8. Xato qilingan rasmlarni ko'zdan kechiring.


9. Amaliy topshiriq

Vazifa 1: Bashorat qiling

python
1.  # load_digits rasmlari o'lchami va qiymatlar oralig'i?
2.  # Conv2d kutadigan kirish shakli?
3.  # Conv2d(16, 32, 3) parametrlari soni?
4.  # 8x8 kirish ikki MaxPool2d(2) dan keyin?
5.  # Flatten dan keyingi o'lcham (32 kanal)?
6.  # MLP 64 -> 80 -> 10 parametrlari?
7.  # halol taqqoslashning 3 sharti?
8.  # juftlashgan farqda SE formulasi?
9.  # ekvivariantlik nima?
10. # nima uchun MLP siljishga zaif?
11. # np.roll bilan siljitishning muammosi?
12. # chalkashlik matritsasida M[i, j]?
Javoblar
  1. (8, 8), 0–16
  2. (B, C, H, W)
  3. 32 * 16 * 9 + 32 = 4640
  4. 2 × 2
  5. 32 * 2 * 2 = 128
  6. 64 * 80 + 80 + 80 * 10 + 10 = 6010
  7. Teng parametr, bir xil bo'linish/davrlar, bir necha seed
  8. std(d, ddof=1) / sqrt(n)
  9. Kirish siljisa, chiqish ham shuncha siljiydi
  10. Har piksel o'z og'irligiga ega — siljish butunlay yangi vektor beradi
  11. Chetdan chiqqan piksellar qarama-qarshi chetga o'tadi
  12. Haqiqiy i, bashorat j bo'lgan namunalar soni

Vazifa 2: Xatolarni tuzating

python
1.  model(torch.tensor(d.images, dtype=torch.float32))

2.  nn.Linear(32 * 8 * 8, 10)   # ikki MaxPool2d(2) dan keyin

3.  print("CNN yaxshiroq" if aniq_cnn > aniq_mlp else "MLP yaxshiroq")

4.  x_sil = np.roll(x, 2, axis=1)

5.  aniq = (model(Xte).argmax(1) == yte).float().mean()   # train rejimida
Javoblar
python
1.  model(torch.tensor(d.images / 16.0, dtype=torch.float32).unsqueeze(1))

2.  nn.Linear(32 * 2 * 2, 10)

3.  farq = cnn_s - mlp_s
    se = farq.std(ddof=1) / np.sqrt(len(farq))
    print("sezilarli" if abs(farq.mean()) > 2 * se else "sezilarli emas")

4.  x_sil = ndimage.shift(x, (0, 2), order=0, mode="constant")

5.  model.eval()
    with torch.no_grad():
        aniq = (model(Xte).argmax(1) == yte).float().mean()

Vazifa 3: Birinchi CNN

Modellang:

  1. Shakllar zanjiri
  2. Parametrlar
  3. O'rgatish egri chizig'i
  4. Bitta bashorat

Vazifa 4: Halol taqqoslash

Modellang:

  1. Teng parametr
  2. Seedlar
  3. Juftlashgan farq
  4. Katta MLP

Vazifa 5: Siljish

Modellang:

  1. Ekvivariantlik
  2. 1 va 2 piksel
  3. Juftlashgan farq
  4. Nisbiy yo'qotish

Vazifa 6: Xatolar

Modellang:

  1. Matritsa
  2. Recall
  3. Juftliklar
  4. Rasmlar

Vazifa 7: O'ylash

Hamkasbingiz aytdi: "Bizda CNN va MLP deyarli bir xil test aniqligi berdi (98.3% va 97.7%). Demak CNN ga vaqt sarflashning keragi yo'q, oddiy MLP ni ishlatamiz." Siz nima deysiz?

Javob

Qisqa javob: toza test to'plamidagi aniqlik — savolning faqat bir qismi. Qaror ma'lumot va ishlab chiqarish sharoitiga bog'liq.

1. Avval farqning o'zini tekshiring. 0.6 foiz punkt farq bitta seed da tasodif bo'lishi mumkin. Bir necha seed bilan juftlashgan farq va SE hisoblang. 2-misolda bu farq kichik bo'lsa ham SE bilan solishtirildi — shundan keyingina "sezilarli" yoki "sezilarli emas" deyish mumkin.

2. Aniqlikni xato ulushi sifatida ham ko'ring. 98.3% va 97.7% — bu 1.7% va 2.3% xato. Ya'ni bir model ikkinchisidan taxminan 30% kam xato qiladi. Chek skanerida kuniga 100 000 raqam bo'lsa, bu yuzlab xato demakdir.

3. Toza test sharoitni aks ettiradimi? load_digits raqamlari markazlangan va bir xil masshtabda. Ishlab chiqarishda esa:

  • raqam kadrda boshqa joyda bo'lishi mumkin (siljish)
  • rasm kattaroq bo'lishi mumkin (28×28, 64×64)
  • yorug'lik va qalinlik boshqacha

3-misolda 1 piksel siljishda MLP ning aniqligi CNN aniqligidan ancha ko'proq tushdi. Toza testda bu umuman ko'rinmaydi.

4. Masshtab haqida. 8×8 da MLP ning birinchi qatlami 64 × h. Real skanerda 64×64 rasm bo'lsa — 4096 × h, va har piksel o'z og'irligini alohida o'rganishi kerak. CNN parametrlari esa rasm o'lchamiga bog'liq emas.

Tavsiya:

python
# 1. Ikkala model uchun 3-5 seed, juftlashgan farq + SE
# 2. Ishlab chiqarishga o'xshash test: siljitilgan, shovqinli rasmlar
# 3. Agar MLP hamma sharoitda teng bo'lsa - soddasini tanlang
# 4. Aks holda - CNN (yoki siljish augmentatsiyasi bilan MLP ni sinang)

Hamkasbga javob: "Soddaroq modelni tanlash to'g'ri tamoyil — lekin bir xil sharoitda teng bo'lsa. Keling, ikkalasini ishlab chiqarishga o'xshash test to'plamida (siljish, shovqin bilan) bir necha seed bilan solishtiraylik. Agar MLP u yerda ham teng bo'lsa — MLP ni olamiz."

Nimani mustahkamlaydi: 2.4, 2.5-bo'limlar.


Xulosa

Bu darsda birinchi CNN ni qurdik va uni MLP bilan halol taqqosladik.

Eng muhim uch fikr:

  1. CNN — [Conv → ReLU → Pool] × N → Flatten → Linear. 1-misolda shakllar zanjiri (B, 1, 8, 8) dan (B, 32, 2, 2) gacha kichrayib, Flatten dan keyin 128 o'lchamli vektorga aylandi — Linear(128, 10) ning kirishi aynan shu zanjirdan olinadi. 6090 parametrli tarmoq 30 davrda test to'plamida 0.9796 aniqlikka yetdi, o'quv va test orasidagi farq atigi 0.02. Konvolyutsiya parametrlari faqat kanal va yadro o'lchamiga bog'liq — rasm kattalashsa ham ular o'zgarmaydi.

  2. Halol taqqoslash — teng parametr, bir necha seed, juftlashgan farq. 2-misolda 6090 parametrli CNN va 6010 parametrli MLP to'rt seed da bir xil sharoitda o'rgatildi: o'rtacha 0.9838 va 0.9769. Farq kichik (+0.0069), lekin uning SE si 0.0021 — ya'ni farq 2 × SE dan katta va sezilarli. Uch barobar katta MLP (19 210 parametr) ham farqni yopmadi (+0.0042, SE 0.0009). Xato ulushi bo'yicha CNN MLP xatolarining taxminan 70% ini qildi. Bu xulosani kod natijadan hisobladi — oldindan yozilgan "CNN ustun" matni emas.

  3. CNN ning haqiqiy ustunligi — siljishga barqarorlik, lekin u to'liq emas. 3-misolda konvolyutsiya ekvivariantligi aniq tasdiqlandi (ichki farq 0), pooling esa faqat qisman invariant chiqdi. Test rasmlarini 1 piksel siljitganda CNN aniqligi 0.64 ga, MLP niki 0.46 ga tushdi — farq +0.18, toza testdagi +0.006 dan o'ttiz barobar katta. Lekin CNN ham aniqligining uchdan bir qismini yo'qotdi: 8×8 rasmda 1 piksel — kenglikning 12.5% i, va Flatten + Linear har joyga o'z og'irligini beradi. 4-misoldagi chalkashlik matritsasi esa 540 ta testdan 11 ta xatoni ko'rsatdi: eng qiyin sinf 3 (recall 0.9455), xatolardagi o'rtacha ishonch 0.60 — to'g'ri javoblardagi 0.99 dan ancha past.

Keyingi darsda CNN arxitekturalari: LeNet, VGG va ResNet uslubidagi bloklar, 3×3 yadrolar to'plami, residual ulanish va global average pooling.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
22.5-dars: Birinchi CNN — IlmHamroh