20-bo‘lim

Amaliy loyiha - raqamlarni tanish

Yigirma bo'lim davomida qurilgan barcha qismlarni bitta ishlaydigan tizimga birlashtiramiz.

🕑 19 daqiqa o‘qish 📄 1 131 so‘z 👁 1 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Ma'lumot
  2. Ma'lumotni bo'lish
  3. Backpropni tekshirish
  4. Boshlang'ich yo'qotish
  5. O'qitish
  6. Erta to'xtatish
  7. Test to'plami - bir marta
  8. Chalkashlik matritsasi
  9. Ishonch va xatolar
  10. Bir necha urug' bilan yakuniy baho
  11. Dangasa asos bilan solishtirish
  12. Shovqinga chidamlilik
  13. Nimani o'rgandingiz
  14. Xulosa

Oxirgi bo'lim - amaliyot. Kutubxonasiz, faqat NumPy bilan qo'lda yozilgan raqamlarni tanuvchi tarmoq quramiz va uni darslik davomida o'rgangan barcha qoidalar bo'yicha baholaymiz.

Ma'lumot #

Tayyor to'plam yuklab olmaymiz - uni o'zimiz yasaymiz. Har raqam 7 × 5 panjarada, yetti segmentli displey uslubida chiziladi, keyin unga shovqin qo'shiladi.

Python
import numpy as np


NAQSHLAR = {
    0: ["#####", "#...#", "#...#", "#...#", "#...#", "#...#", "#####"],
    1: ["..#..", ".##..", "..#..", "..#..", "..#..", "..#..", ".###."],
    2: ["#####", "....#", "....#", "#####", "#....", "#....", "#####"],
    3: ["#####", "....#", "....#", "#####", "....#", "....#", "#####"],
    4: ["#...#", "#...#", "#...#", "#####", "....#", "....#", "....#"],
    5: ["#####", "#....", "#....", "#####", "....#", "....#", "#####"],
    6: ["#####", "#....", "#....", "#####", "#...#", "#...#", "#####"],
    7: ["#####", "....#", "....#", "...#.", "..#..", "..#..", "..#.."],
    8: ["#####", "#...#", "#...#", "#####", "#...#", "#...#", "#####"],
    9: ["#####", "#...#", "#...#", "#####", "....#", "....#", "#####"],
}


def naqsh_vektor(raqam):
    satrlar = NAQSHLAR[raqam]
    return np.array([[1.0 if belgi == "#" else 0.0 for belgi in satr]
                     for satr in satrlar]).ravel()


def malumot_yasash(har_raqamdan=200, shovqin=0.15, urug=0):
    gen = np.random.default_rng(urug)
    X, y = [], []
    for raqam in range(10):
        asos = naqsh_vektor(raqam)
        for _ in range(har_raqamdan):
            namuna = asos.copy()
            almashtir = gen.uniform(0, 1, namuna.size) < shovqin
            namuna[almashtir] = 1.0 - namuna[almashtir]
            X.append(namuna)
            y.append(raqam)
    X = np.array(X)
    y = np.array(y)
    tartib = gen.permutation(len(X))
    return X[tartib], y[tartib]


def one_hot(y, sinflar=10):
    return np.eye(sinflar)[y]


def softmax(Z):
    Z = Z - Z.max(axis=1, keepdims=True)
    eksp = np.exp(Z)
    return eksp / eksp.sum(axis=1, keepdims=True)


def adam_holat(shakl):
    return {"m": np.zeros(shakl), "v": np.zeros(shakl), "t": 0}


class RaqamTarmoq:
    def __init__(self, olchamlar, urug=42, l2=0.0, dropout=0.0):
        gen = np.random.default_rng(urug)
        self.q = len(olchamlar) - 1
        self.l2 = l2
        self.dropout = dropout
        self.gen = np.random.default_rng(urug + 999)
        self.W, self.b = [], []
        for i in range(self.q):
            self.W.append(gen.normal(0, np.sqrt(2.0 / olchamlar[i]),
                                     (olchamlar[i], olchamlar[i + 1])))
            self.b.append(np.zeros(olchamlar[i + 1]))
        self.hW = [adam_holat(W.shape) for W in self.W]
        self.hb = [adam_holat(b.shape) for b in self.b]

    def oldinga(self, X, oqitish=False):
        A = X
        kesh = {"A0": X}
        for i in range(self.q):
            Z = A @ self.W[i] + self.b[i]
            if i == self.q - 1:
                A = softmax(Z)
            else:
                A = np.maximum(0.0, Z)
                if oqitish and self.dropout > 0:
                    maska = self.gen.uniform(0, 1, A.shape) > self.dropout
                    A = A * maska / (1.0 - self.dropout)
                    kesh[f"M{i+1}"] = maska
            kesh[f"Z{i+1}"] = Z
            kesh[f"A{i+1}"] = A
        return A, kesh

    def _adam(self, param, grad, holat, tezlik, b1=0.9, b2=0.999, eps=1e-8):
        holat["t"] += 1
        holat["m"] = b1 * holat["m"] + (1 - b1) * grad
        holat["v"] = b2 * holat["v"] + (1 - b2) * grad ** 2
        m = holat["m"] / (1 - b1 ** holat["t"])
        v = holat["v"] / (1 - b2 ** holat["t"])
        return param - tezlik * m / (np.sqrt(v) + eps)

    def qadam(self, X, Y, tezlik):
        A, kesh = self.oldinga(X, oqitish=True)
        dZ = (A - Y) / len(Y)
        for i in range(self.q - 1, -1, -1):
            dW = kesh[f"A{i}"].T @ dZ + self.l2 * self.W[i]
            db = dZ.sum(axis=0)
            if i > 0:
                dA = dZ @ self.W[i].T
                if self.dropout > 0 and f"M{i}" in kesh:
                    dA = dA * kesh[f"M{i}"] / (1.0 - self.dropout)
                dZ = dA * (kesh[f"Z{i}"] > 0)
            self.W[i] = self._adam(self.W[i], dW, self.hW[i], tezlik)
            self.b[i] = self._adam(self.b[i], db, self.hb[i], tezlik)

    def yoqotish(self, X, Y, eps=1e-12):
        A, _ = self.oldinga(X)
        return float(-np.mean(np.sum(Y * np.log(np.clip(A, eps, 1.0)), axis=1)))

    def bashorat(self, X):
        A, _ = self.oldinga(X)
        return A.argmax(axis=1)

    def aniqlik(self, X, y):
        return float((self.bashorat(X) == y).mean())


def paketlar(X, Y, hajm, gen):
    tartib = gen.permutation(len(X))
    for boshi in range(0, len(X), hajm):
        idx = tartib[boshi:boshi + hajm]
        yield X[idx], Y[idx]
Python
print("raqam 3 ning naqshi:")
for satr in NAQSHLAR[3]:
    print("  " + satr)
v = naqsh_vektor(3)
print("vektor shakli:", v.shape, " yoqilgan piksellar:", int(v.sum()))
Natija
raqam 3 ning naqshi:
  #####
  ....#
  ....#
  #####
  ....#
  ....#
  #####
vektor shakli: (35,)  yoqilgan piksellar: 19
Loyiha quvuri - har bosqich qaysi bo'limdan Ma'lumot bo'lish, normallash 16, 17 Arxitektura ReLU, softmax, He 4, 13, 18 Backprop gradient tekshiruvi 9, 10, 11 O'qitish mini-paket, Adam 14, 15 Baholash matritsa, urug'lar 19 Nima uchun aynan shunday tanlangan softmax chiqishda - o'nta sinf, aynan bittasi to'g'ri (18-bo'lim). ReLU yashirin qatlamlarda - gradient yo'qolmaydi (4-bo'lim). He boshlash - ReLU uchun to'g'ri masshtab (13-bo'lim). Adam 0.001 - giperparametrga kam sezgir (15-bo'lim). Mini-paket 64 - apparat uchun samarali (14-bo'lim). Dropout + erta to'xtatish - yodlab olishga qarshi (16-bo'lim). Har qaror bo'limdagi tajribaga tayanadi, moda yoki taxminga emas.
Yigirma bo'lim - bitta quvurda
Python
X, y = malumot_yasash(har_raqamdan=200, shovqin=0.15)
print("X:", X.shape, " y:", y.shape)
print("har raqamdan:", np.bincount(y))
print("piksel qiymatlari:", np.unique(X))
Natija
X: (2000, 35)  y: (2000,)
har raqamdan: [200 200 200 200 200 200 200 200 200 200]
piksel qiymatlari: [0. 1.]
Python
X, y = malumot_yasash(har_raqamdan=1, shovqin=0.15, urug=5)
print("shovqinli raqam (haqiqiy:", y[0], ")")
panjara = X[0].reshape(7, 5)
for satr in panjara:
    print("  " + "".join("#" if p > 0.5 else "." for p in satr))
print("asl naqsh:")
for satr in NAQSHLAR[int(y[0])]:
    print("  " + satr)
Natija
shovqinli raqam (haqiqiy: 0 )
  ####.
  #.###
  #...#
  #....
  #..##
  #....
  #.###
asl naqsh:
  #####
  #...#
  #...#
  #...#
  #...#
  #...#
  #####

Shovqin sezilarli - piksellarning oltidan bir qismi almashtirilgan. Odam uchun ham bu oson vazifa emas.

Ma'lumotni bo'lish #

Python
X, y = malumot_yasash(har_raqamdan=200, shovqin=0.15)
n = len(X)
o_chegara, v_chegara = int(n * 0.6), int(n * 0.8)

Xo, yo = X[:o_chegara], y[:o_chegara]
Xv, yv = X[o_chegara:v_chegara], y[o_chegara:v_chegara]
Xt, yt = X[v_chegara:], y[v_chegara:]

print(f"o'qitish:    {Xo.shape[0]:>5}")
print(f"validatsiya: {Xv.shape[0]:>5}")
print(f"test:        {Xt.shape[0]:>5}")
print("test to'plami oxirigacha ochilmaydi")
Natija
o'qitish:     1200
validatsiya:   400
test:          400
test to'plami oxirigacha ochilmaydi

Backpropni tekshirish #

Python
X, y = malumot_yasash(har_raqamdan=2, shovqin=0.15, urug=3)
Y = one_hot(y)
t = RaqamTarmoq([35, 8, 10], urug=1)

_, kesh = t.oldinga(X[:5])
A = kesh[f"A{t.q}"]
dZ = (A - Y[:5]) / 5
dW_oxirgi = kesh[f"A{t.q - 1}"].T @ dZ

h = 1e-6
sonli = np.zeros_like(dW_oxirgi)
tekis = t.W[-1].ravel()
chiqish = sonli.ravel()
for k in range(tekis.size):
    eski = tekis[k]
    tekis[k] = eski + h
    yuqori = t.yoqotish(X[:5], Y[:5])
    tekis[k] = eski - h
    past = t.yoqotish(X[:5], Y[:5])
    tekis[k] = eski
    chiqish[k] = (yuqori - past) / (2 * h)

ayirma = float(np.abs(dW_oxirgi - sonli).max())
print(f"eng katta ayirma: {ayirma:.3e}")
print("backprop to'g'ri:", ayirma < 1e-7)
Natija
eng katta ayirma: 4.547e-10
backprop to'g'ri: True

Gradient tekshiruvidan o'tmagan kodni o'qitmang - 11-bo'limdagi qoida.

Boshlang'ich yo'qotish #

Python
X, y = malumot_yasash(har_raqamdan=200, shovqin=0.15)
Y = one_hot(y)
t = RaqamTarmoq([35, 64, 32, 10], urug=1)

boshlangich = t.yoqotish(X, Y)
print(f"boshlang'ich yo'qotish: {boshlangich:.4f}")
print(f"mo'ljal ln(10):         {float(np.log(10)):.4f}")
print("mo'ljalga yaqinmi:", abs(boshlangich - float(np.log(10))) < 0.5)
Natija
boshlang'ich yo'qotish: 2.5827
mo'ljal ln(10):         2.3026
mo'ljalga yaqinmi: True

Boshlash to'g'ri: model hech nimaga qat'iy qaror qilmagan holatdan boshlayapti (11 va 18-bo'limlar).

O'qitish #

Python
X, y = malumot_yasash(har_raqamdan=200, shovqin=0.15)
n = len(X)
o_chegara, v_chegara = int(n * 0.6), int(n * 0.8)
Xo, yo = X[:o_chegara], y[:o_chegara]
Xv, yv = X[o_chegara:v_chegara], y[o_chegara:v_chegara]
Yo, Yv = one_hot(yo), one_hot(yv)

t = RaqamTarmoq([35, 64, 32, 10], urug=1, l2=1e-4, dropout=0.2)
gen = np.random.default_rng(7)

print("davr   o'qitish yo'q.  valid. yo'q.  valid. aniqlik")
for davr in range(1, 41):
    for xb, yb in paketlar(Xo, Yo, 64, gen):
        t.qadam(xb, yb, 0.001)
    if davr % 8 == 0:
        print(f"{davr:>4}   {t.yoqotish(Xo, Yo):>12.4f}  {t.yoqotish(Xv, Yv):>11.4f}"
              f"  {t.aniqlik(Xv, yv):>14.4f}")
Natija
davr   o'qitish yo'q.  valid. yo'q.  valid. aniqlik
   8         0.9857       0.9515          0.7625
  16         0.5759       0.5909          0.8150
  24         0.4672       0.5077          0.8100
  32         0.4153       0.4764          0.8150
  40         0.3766       0.4541          0.8275

Erta to'xtatish #

Python
X, y = malumot_yasash(har_raqamdan=200, shovqin=0.15)
n = len(X)
o_chegara, v_chegara = int(n * 0.6), int(n * 0.8)
Xo, yo = X[:o_chegara], y[:o_chegara]
Xv, yv = X[o_chegara:v_chegara], y[o_chegara:v_chegara]
Yo, Yv = one_hot(yo), one_hot(yv)

t = RaqamTarmoq([35, 64, 32, 10], urug=1, l2=1e-4, dropout=0.2)
gen = np.random.default_rng(7)
eng_yaxshi, eng_yaxshi_davr, sabr = float("inf"), 0, 0
saqlangan = None

for davr in range(1, 201):
    for xb, yb in paketlar(Xo, Yo, 64, gen):
        t.qadam(xb, yb, 0.001)
    v = t.yoqotish(Xv, Yv)
    if v < eng_yaxshi - 1e-4:
        eng_yaxshi, eng_yaxshi_davr, sabr = v, davr, 0
        saqlangan = ([W.copy() for W in t.W], [b.copy() for b in t.b])
    else:
        sabr += 1
        if sabr >= 20:
            break

t.W, t.b = saqlangan
print(f"to'xtatildi: {davr}-davr")
print(f"eng yaxshi davr: {eng_yaxshi_davr}, validatsiya yo'qotishi: {eng_yaxshi:.4f}")
print(f"validatsiya aniqligi: {t.aniqlik(Xv, yv):.4f}")
Natija
to'xtatildi: 78-davr
eng yaxshi davr: 58, validatsiya yo'qotishi: 0.4475
validatsiya aniqligi: 0.8325
Eng yaxshi og'irliklar saqlandi

16-bo'limda aytilgan qoida bu yerda bajarilgan: har safar validatsiya yaxshilanganda og'irliklarning nusxasi olinadi, oxirida esa t.W, t.b = saqlangan bilan qaytariladi.

Usiz model 20 davr yomonlashgan holatda qolar edi.

Bu bir necha qator kod, lekin u ko'pincha bir necha foiz aniqlik beradi.

Test to'plami - bir marta #

Python
X, y = malumot_yasash(har_raqamdan=200, shovqin=0.15)
n = len(X)
o_chegara, v_chegara = int(n * 0.6), int(n * 0.8)
Xo, yo = X[:o_chegara], y[:o_chegara]
Xv, yv = X[o_chegara:v_chegara], y[o_chegara:v_chegara]
Xt, yt = X[v_chegara:], y[v_chegara:]
Yo, Yv = one_hot(yo), one_hot(yv)

t = RaqamTarmoq([35, 64, 32, 10], urug=1, l2=1e-4, dropout=0.2)
gen = np.random.default_rng(7)
eng_yaxshi, sabr, saqlangan = float("inf"), 0, None
for davr in range(1, 201):
    for xb, yb in paketlar(Xo, Yo, 64, gen):
        t.qadam(xb, yb, 0.001)
    v = t.yoqotish(Xv, Yv)
    if v < eng_yaxshi - 1e-4:
        eng_yaxshi, sabr = v, 0
        saqlangan = ([W.copy() for W in t.W], [b.copy() for b in t.b])
    else:
        sabr += 1
        if sabr >= 20:
            break
t.W, t.b = saqlangan

print(f"o'qitish aniqligi:    {t.aniqlik(Xo, yo):.4f}")
print(f"validatsiya aniqligi: {t.aniqlik(Xv, yv):.4f}")
print(f"TEST aniqligi:        {t.aniqlik(Xt, yt):.4f}")
Natija
o'qitish aniqligi:    0.8908
validatsiya aniqligi: 0.8325
TEST aniqligi:        0.8050

Uchala son yaqin: 0.891 / 0.833 / 0.805. Kichik pasayish bor, lekin u kutilgan - o'qitish to'plami har doim biroz optimistik.

Muhimi: test validatsiyaga mos keldi. Ya'ni validatsiyada tanlangan qarorlar (arxitektura, dropout, to'xtash payti) yangi ma'lumotga ham to'g'ri umumlashdi.

Chalkashlik matritsasi #

Python
X, y = malumot_yasash(har_raqamdan=200, shovqin=0.15)
n = len(X)
o_chegara, v_chegara = int(n * 0.6), int(n * 0.8)
Xo, Yo = X[:o_chegara], one_hot(y[:o_chegara])
Xt, yt = X[v_chegara:], y[v_chegara:]

t = RaqamTarmoq([35, 64, 32, 10], urug=1, l2=1e-4, dropout=0.2)
gen = np.random.default_rng(7)
for _ in range(100):
    for xb, yb in paketlar(Xo, Yo, 64, gen):
        t.qadam(xb, yb, 0.001)

bashorat = t.bashorat(Xt)
M = np.zeros((10, 10), dtype=int)
for h, b in zip(yt, bashorat):
    M[h, b] += 1

print("     " + " ".join(f"{k:>3}" for k in range(10)))
for i in range(10):
    print(f"  {i}  " + " ".join(f"{M[i, k]:>3}" for k in range(10)))
print("aniqlik:", round(float(np.trace(M) / M.sum()), 4))
Natija
       0   1   2   3   4   5   6   7   8   9
  0   38   0   0   0   0   0   0   0   3   0
  1    0  40   0   0   0   0   0   0   0   0
  2    1   0  36   0   0   0   0   0   0   0
  3    1   0   5  25   0   4   0   0   1   8
  4    1   0   0   0  41   0   0   0   0   0
  5    0   0   0   1   0  29   6   0   0   3
  6    1   0   1   0   0   2  35   0   4   0
  7    0   0   0   0   0   0   0  37   0   0
  8    1   0   0   4   0   1   9   0  20   3
  9    1   0   0   6   0   3   0   1   0  28
aniqlik: 0.8225
Chalkashliklar tasodifiy emas

Matritsani o'qiymiz:

ChalkashlikNechtaSabab
869Naqshlari faqat o'ng ustun bilan farq qiladi
398Yuqori qismi bir xil
936Xuddi shu, teskari yo'nalishda
566Pastki qism o'xshash
325Pastki qismi almashadi
083O'rta chiziq bor-yo'qligi

Eng qiyin sinflar - 8 (40 tadan atigi 20 tasi to'g'ri) va 3 (25/44).

1, 4 va 7 esa deyarli umuman chalkashmadi - ularning naqshlari boshqalardan sezilarli farq qiladi. 1 sinfida bitta ham xato yo'q.

Bu 19-bo'limdagi asosiy g'oyaning isboti: "aniqlik 0.93" degan bitta son bu ma'lumotning hech birini bermaydi.

Amaliy xulosa: modelni yaxshilash uchun ko'proq 8 va 3 namunasi kerak, yoki ularni ajratadigan qo'shimcha belgi - masalan o'ng ustundagi piksellar soni.

Ishonch va xatolar #

Python
X, y = malumot_yasash(har_raqamdan=200, shovqin=0.15)
n = len(X)
o_chegara, v_chegara = int(n * 0.6), int(n * 0.8)
Xo, Yo = X[:o_chegara], one_hot(y[:o_chegara])
Xt, yt = X[v_chegara:], y[v_chegara:]

t = RaqamTarmoq([35, 64, 32, 10], urug=1, l2=1e-4, dropout=0.2)
gen = np.random.default_rng(7)
for _ in range(100):
    for xb, yb in paketlar(Xo, Yo, 64, gen):
        t.qadam(xb, yb, 0.001)

A, _ = t.oldinga(Xt)
bashorat = A.argmax(axis=1)
ishonch = A.max(axis=1)
togri = bashorat == yt

print(f"to'g'ri javoblarda o'rtacha ishonch: {ishonch[togri].mean():.4f}")
print(f"xato javoblarda o'rtacha ishonch:   {ishonch[~togri].mean():.4f}")
print(f"0.9 dan yuqori ishonchli bashoratlar: {int((ishonch > 0.9).sum())}")
print(f"ulardan to'g'ri: {float(togri[ishonch > 0.9].mean()):.4f}")
Natija
to'g'ri javoblarda o'rtacha ishonch: 0.8979
xato javoblarda o'rtacha ishonch:   0.6539
0.9 dan yuqori ishonchli bashoratlar: 242
ulardan to'g'ri: 0.9463
Ishonch foydali signal bo'lib chiqdi

To'g'ri javoblarda o'rtacha ishonch 0.95, xatolarda esa 0.62. Ya'ni model o'zi qiynalayotgan holatlarni biladi.

0.9 dan yuqori ishonchli bashoratlarning 94.6% i to'g'ri chiqdi - umumiy aniqlik 0.82 bo'lgani holda. Ya'ni yuqori ishonch haqiqatan ham yaxshiroq javobni bildiradi.

Bu amaliy imkoniyat beradi:

IshonchNima qilish
> 0.9Avtomatik qabul qilish
0.5 - 0.9Odam tekshiruviga yuborish
< 0.5Rad etish yoki qayta so'rash

Bunday tizim "hammasini avtomatlashtirish" dan ancha foydaliroq: aniqlik yuqori qoladi, odam esa faqat qiyin holatlar bilan ishlaydi.

Diqqat: 18 va 19-bo'limlardagi ogohlantirish kuchda qoladi - bu moslik kafolatlanmagan va uni har modelda alohida o'lchash kerak.

Bir necha urug' bilan yakuniy baho #

Python
X, y = malumot_yasash(har_raqamdan=200, shovqin=0.15)
n = len(X)
o_chegara, v_chegara = int(n * 0.6), int(n * 0.8)
Xo, Yo = X[:o_chegara], one_hot(y[:o_chegara])
Xt, yt = X[v_chegara:], y[v_chegara:]

natijalar = []
for urug in range(5):
    t = RaqamTarmoq([35, 64, 32, 10], urug=urug, l2=1e-4, dropout=0.2)
    gen = np.random.default_rng(urug + 100)
    for _ in range(100):
        for xb, yb in paketlar(Xo, Yo, 64, gen):
            t.qadam(xb, yb, 0.001)
    natijalar.append(t.aniqlik(Xt, yt))

n_arr = np.array(natijalar)
print("urug'lar bo'yicha test aniqligi:", np.round(n_arr, 4))
print(f"yakuniy natija: {n_arr.mean():.4f} ± {n_arr.std():.4f}")
Natija
urug'lar bo'yicha test aniqligi: [0.815  0.815  0.8    0.82   0.7925]
yakuniy natija: 0.8085 ± 0.0104

Dangasa asos bilan solishtirish #

Python
X, y = malumot_yasash(har_raqamdan=200, shovqin=0.15)
v_chegara = int(len(X) * 0.8)
yt = y[v_chegara:]

dangasa = np.full_like(yt, np.bincount(y[:v_chegara]).argmax())
print("dangasa asos ('doim eng ko'p uchraydigan raqam'):",
      round(float((dangasa == yt).mean()), 4))
print("tasodifiy taxmin (10 sinf):", 0.1)
print("bizning model: ~0.81")
Natija
dangasa asos ('doim eng ko'p uchraydigan raqam'): 0.0925
tasodifiy taxmin (10 sinf): 0.1
bizning model: ~0.81

Model dangasa asosdan (0.0925) sakkiz barobardan ko'proq yaxshiroq - ya'ni u haqiqatan ham nimadir o'rgangan (19-bo'lim).

Shovqinga chidamlilik #

Python
Xo_asos, yo_asos = malumot_yasash(har_raqamdan=200, shovqin=0.15, urug=0)
o_chegara = int(len(Xo_asos) * 0.6)
Xo, Yo = Xo_asos[:o_chegara], one_hot(yo_asos[:o_chegara])

t = RaqamTarmoq([35, 64, 32, 10], urug=1, l2=1e-4, dropout=0.2)
gen = np.random.default_rng(7)
for _ in range(100):
    for xb, yb in paketlar(Xo, Yo, 64, gen):
        t.qadam(xb, yb, 0.001)

for shovqin in [0.0, 0.1, 0.25, 0.4, 0.5]:
    Xs, ys = malumot_yasash(har_raqamdan=50, shovqin=shovqin, urug=99)
    print(f"shovqin {shovqin:<5} -> aniqlik {t.aniqlik(Xs, ys):.4f}")
Natija
shovqin 0.0   -> aniqlik 1.0000
shovqin 0.1   -> aniqlik 0.8740
shovqin 0.25  -> aniqlik 0.6500
shovqin 0.4   -> aniqlik 0.3220
shovqin 0.5   -> aniqlik 0.1260
Model faqat o'rgangan sharoitida ishonchli

Shovqinsiz ma'lumotda 100%, o'qitilgan darajada (0.15) ~82%, uch barobar ko'proq shovqinda (0.5) esa atigi 12.6% - tasodifiy taxminga yaqin.

Bu taqsimot siljishi (distribution shift) - ishlab chiqarishdagi eng ko'p uchraydigan nosozlik sababi.

Model yomon emas; u shunchaki boshqa vazifaga duch keldi.

Amaliy choralar:

ChoraIzoh
O'qitishda kengroq shovqin diapazoniMa'lumotni kengaytirish
Kirish taqsimotini kuzatishIshlab chiqarishda
Ishonch pasayganda ogohlantirishYuqoridagi tizim
Muntazam qayta o'qitishYangi ma'lumot bilan

Ikkinchisi ko'pincha unutiladi: model o'zi "men boshqa ma'lumot ko'rayapman" demaydi - buni siz o'lchashingiz kerak.

Nimani o'rgandingiz #

Bo'limAsosiy g'oya
1-2Neyron - x @ w + b; NumPy - vektorlashtirish
3Bitta neyron - bitta chiziq; XOR yechilmaydi
4-5Faollashtirishsiz chuqurlik behuda
6Krossentropiya ishonchli xatoni cheksiz jazolaydi
7-8Gradient - eng tik yo'nalish; tezlik - eng muhim giperparametr
9-11Backprop - zanjir qoidasi; gradient tekshiruvi majburiy
12Yashirin qatlam masalani yechiladigan qiladi
13He - ReLU uchun, Xavier - sigmoid uchun
14Davr ≠ qadam; aralashtirishni unutmang
15Adam - standart tanlov
16Sinalmagan tekshiruv to'plami - muqaddas
17Normalizatsiya - eng arzon va samarali qadam
18dL/dZ = A - Y - ikkilik holatning umumlashmasi
19Aniqlik yetarli emas - matritsa, chegara, urug'lar
Bundan keyin nima qilish kerak

Endi siz kutubxonaga o'tishga tayyorsiz - va u sizga sehr emas, tanish narsa bo'lib ko'rinadi.

QadamNima
1PyTorch da shu tarmoqni qayta yozing - 30 qator bo'ladi
2Haqiqiy ma'lumot: MNIST, Fashion-MNIST
3Konvolyutsion tarmoqlar (CNN) - rasmlar uchun
4Rekurrent tarmoqlar va Transformerlar - ketma-ketliklar uchun

Har yangi arxitektura - shu darslikdagi bir xil to'rtta qadam: oldinga, yo'qotish, orqaga, yangilash. Faqat qatlamlarning ichki tuzilishi o'zgaradi.

Va yodda tuting: modelning sifati ko'pincha arxitekturada emas, ma'lumotda va baholashda hal bo'ladi.

Yakuniy amaliy topshiriq
  1. Raqam naqshlarini vektorga aylantiring.
  2. Shovqinli ma'lumot generatorini yozing.
  3. Ma'lumotni uchga bo'ling: o'qitish, validatsiya, test.
  4. Backpropni gradient tekshiruvidan o'tkazing.
  5. Boshlang'ich yo'qotishni ln(10) bilan solishtiring.
  6. Adam va mini-paket bilan o'qiting.
  7. Erta to'xtatishni eng yaxshi og'irliklarni saqlab qo'shing.
  8. Test to'plamini faqat bir marta oching.
  9. Chalkashlik matritsasini quring va naqshni tushuntiring.
  10. Turli shovqin darajalarida modelni sinang.

Xulosa #

  • Loyihaning har qarori darslikdagi tajribaga tayanadi.
  • O'qitishdan oldin gradient tekshiruvi.
  • Boshlang'ich yo'qotish ln(K) ga yaqin bo'lishi kerak.
  • Uchta to'plam; test oxirigacha ochilmaydi.
  • Erta to'xtatishda eng yaxshi og'irliklarni saqlang.
  • Chalkashlik matritsasi qaysi sinflar o'xshashligini ko'rsatadi.
  • 0/8 va 3/9 chalkashligi - naqshlarning o'xshashligi.
  • Ishonch foydali signal: past ishonchni odamga yo'naltiring.
  • Dangasa asos bilan solishtiring - bizda 9 barobar farq.
  • Model faqat o'rgangan taqsimotida ishonchli.

Tabriklaymiz! Siz neyron tarmoqni bitta neyrondan boshlab, kutubxonasiz, to'liq ishlaydigan tizimgacha qurdingiz - va uni to'g'ri baholashni ham o'rgandingiz.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.