IlmHamroh
Data Science va sun'iy intellekt/Neyron tarmoqlar1/12-dars22 daqiqa
Mundarija (21)

20.1-dars: Neyron va perseptron

20-QISM — NEYRON TARMOQLAR · 1-dars


1. Kirish va motivatsiya

Shu paytgacha modellarni tayyor oldik: LogisticRegression, RandomForest, HistGradientBoosting. Ular ichida nima bo'layotganini bilardik, lekin o'zimiz qurmadik.

Neyron tarmoqlar boshqacha: ular juda oddiy bloklardan yig'iladi. Bitta blok — neyron — atigi ikki amal bajaradi: kirishlarni og'irliklar bilan ko'paytirib qo'shadi, so'ng natijani aktivatsiya funksiyasidan o'tkazadi. Hammasi shu.

Sehr bloklarda emas, ularning soni va joylashuvida. Bitta neyron faqat to'g'ri chiziq chiza oladi. Ikki qatlam neyron esa — 1989-yilda isbotlangan universal approksimatsiya teoremasi bo'yicha — istalgan uzluksiz funksiyani xohlagancha aniq taqlid qila oladi.

Bu darsda eng boshidan boshlaymiz: bitta neyron, uni qo'lda hisoblash, perseptron o'rgatish qoidasi va perseptronning mashhur cheklovi — XOR muammosi.

Real vaziyat. 1958-yilda Frank Rosenblatt perseptronni e'lon qilganda, gazetalar "o'zini anglaydigan mashina" deb yozdi. 1969-yilda Minsky va Papert bitta perseptron XOR ni yecha olmasligini isbotladi va soha 15 yilga to'xtadi. Cheklov haqiqiy edi — lekin u faqat bitta qatlam uchun.

Bu darsda neyronning ichini ochamiz.

Bu darsda:

  • Neyron: og'irlik, bias, aktivatsiya
  • Perseptron o'rgatish qoidasi
  • Chiziqli ajralish
  • XOR muammosi
  • Qatlam tushunchasi
  • Tuzoqlar
  • Amaliy: qo'lda neyron

ℹ Misollar real numpy/sklearn bilan (Python 3.14).


2. Nazariya — chuqur tushuntirish

2.1. Neyron nima

text
KIRISH          OG'IRLIK        YIG'INDI       AKTIVATSIYA   CHIQISH
x1 ---- w1 ----\
x2 ---- w2 -----> z = w·x + b --> f(z) -------> a
x3 ---- w3 ----/

IKKI QADAM:
  1. CHIZIQLI:    z = w1*x1 + w2*x2 + ... + wn*xn + b
  2. NOCHIZIQLI:  a = f(z)

w — og'irliklar (weights): har kirishning MUHIMLIGI
b — siljish (bias): chegarani surish
f — aktivatsiya: nochiziqlilik manbai

MUHIM: f BO'LMASA, neyron chiziqli regressiyadan farq qilmaydi

Neyron = chiziqli kombinatsiya + nochiziqli funksiya. Ikkinchisisiz qancha qatlam qo'ysangiz ham natija baribir chiziqli bo'ladi.

2.2. Bias nima uchun kerak

text
b SIZ:   z = w1*x1 + w2*x2
         chegara (z = 0) HAR DOIM koordinata boshidan o'tadi

b BILAN: z = w1*x1 + w2*x2 + b
         chegarani istalgan joyga surish mumkin

MISOL: "harorat 37 dan yuqorimi" degan neyron
  b siz:   w*harorat > 0  ->  faqat harorat > 0 ni aniqlaydi
  b bilan: w*harorat - 37w > 0  ->  to'g'ri chegara

Bias — chegarani surish imkoni; usiz model koordinata boshiga bog'lanib qoladi.

2.3. Perseptron o'rgatish qoidasi

text
AKTIVATSIYA: step(z) = 1 agar z > 0, aks holda 0

HAR NAMUNA UCHUN:
  bashorat = step(w·x + b)
  xato = haqiqiy - bashorat          # -1, 0 yoki +1
  w <- w + eta * xato * x
  b <- b + eta * xato

MANTIQ:
  xato = 0   -> hech narsa o'zgarmaydi
  xato = +1  -> bashorat past edi, w ni x YO'NALISHIDA suramiz
  xato = -1  -> bashorat baland edi, w ni x ga QARSHI suramiz

KAFOLAT (Novikoff, 1962):
  ma'lumot chiziqli ajraladigan bo'lsa - CHEKLI qadamda to'xtaydi
  ajralmasa - ABADIY aylanadi

Perseptron faqat chiziqli ajraladigan ma'lumotda yaqinlashadi — bu teorema, taxmin emas.

2.4. Chiziqli ajralish va XOR

text
AND            OR             XOR
x1 x2 | y      x1 x2 | y      x1 x2 | y
 0  0 | 0       0  0 | 0       0  0 | 0
 0  1 | 0       0  1 | 1       0  1 | 1
 1  0 | 0       1  0 | 1       1  0 | 1
 1  1 | 1       1  1 | 1       1  1 | 0

AND, OR:  bitta to'g'ri chiziq 0 larni 1 lardan ajratadi  -> YECHILADI
XOR:      1 lar DIAGONAL joylashgan                       -> YECHILMAYDI

  1 |  1     0            bitta chiziq bilan
    |                     diagonalni ajratib bo'lmaydi
  0 |  0     1
    +-----------
       0     1

XOR — bitta neyronning chegarasi, chunki bitta neyron faqat bitta gipertekislik chiza oladi.

2.5. Qatlam — XOR yechimi

text
IKKI QATLAM XOR ni yechadi:

  h1 = step(x1 + x2 - 0.5)      # OR
  h2 = step(x1 + x2 - 1.5)      # AND
  y  = step(h1 - h2 - 0.5)      # OR VA AND EMAS

x1 x2 | h1  h2 | y
 0  0 |  0   0 | 0
 0  1 |  1   0 | 1
 1  0 |  1   0 | 1
 1  1 |  1   1 | 0

YASHIRIN QATLAM ma'lumotni YANGI FAZOGA ko'chiradi,
u yerda sinflar chiziqli ajraladigan bo'lib qoladi

Yashirin qatlamning vazifasi — koordinatani almashtirish, shundan keyin oxirgi qatlam oddiy chiziq chizadi.

2.6. Perseptron va logistik regressiya

text
                perseptron          logistik regressiya
aktivatsiya     step (0/1)          sigmoid (0..1)
chiqish         sinf                EHTIMOLLIK
loss            yo'q (qoida)        log-loss
gradient        yo'q (step uzilgan) bor
ajralmasa       aylanaveradi        yaqinlashadi
marja           e'tibor bermaydi    maksimallashtiradi

XULOSA: perseptron - tarixiy asos, amalda sigmoid/softmax ishlatiladi

Step funksiyaning hosilasi hamma joyda nol — shuning uchun perseptronni gradient bilan o'rgatib bo'lmaydi va shuning uchun zamonaviy tarmoqlarda u ishlatilmaydi.

2.7. Tuzoqlar

Asosiy tuzoqlar: aktivatsiyasiz qatlamlarni ko'paytirish (natija baribir chiziqli); bias ni unutish; perseptronni ajralmaydigan ma'lumotda cheksiz aylantirish; step bilan gradient izlash; XOR ni bitta neyron bilan yechishga urinish; og'irliklarni nol bilan boshlash (ko'p neyronli qatlamda hammasi bir xil qoladi).


3. Tez ma'lumotnoma

python
import numpy as np

# bitta neyron
def neyron(x, w, b, f=lambda z: (z > 0).astype(float)):
    return f(x @ w + b)

# perseptron o'rgatish
for _ in range(davrlar):
    for xi, yi in zip(X, y):
        xato = yi - neyron(xi, w, b)
        w += eta * xato * xi
        b += eta * xato

# XOR ni ikki qatlam bilan
W1 = np.array([[1.0, 1.0], [1.0, 1.0]])   # (kirish, yashirin)
b1 = np.array([-0.5, -1.5])
W2 = np.array([[1.0], [-1.0]])
b2 = np.array([-0.5])

Neyron xulosasi

z = w·x + b            chiziqli qism
a = f(z)               nochiziqli qism
perseptron: step + xato*x qoidasi
chiziqli ajralish  -> yaqinlashadi
XOR                -> ikki qatlam kerak

4. Batafsil misollar

Misollar real numpy/sklearn bilan (Python 3.14).

Misol 1 — Bitta neyronni qo'lda hisoblash

python
"""Neyronning ichi: og'irlik, bias, aktivatsiya (real numpy)."""

import numpy as np


def step(z):
    return (np.asarray(z) > 0).astype(float)


def neyron(X, w, b, f=step):
    return f(X @ w + b)


def main() -> None:
    X = np.array([[0.0, 0.0], [0.0, 1.0], [1.0, 0.0], [1.0, 1.0]])

    print("=== 1. Qo'lda qo'yilgan og'irliklar: AND ===")
    w_and, b_and = np.array([1.0, 1.0]), -1.5
    print(f"  w = {w_and}, b = {b_and}")
    print(f"  {'x1':>4} {'x2':>4} {'z = w·x + b':>13} {'step(z)':>9}")
    for x in X:
        z = float(x @ w_and + b_and)
        print(f"  {x[0]:>4.0f} {x[1]:>4.0f} {z:>13.1f} {step(z):>9.0f}")

    print("\n=== 2. Bir xil tuzilma, boshqa bias: OR ===")
    w_or, b_or = np.array([1.0, 1.0]), -0.5
    print(f"  w = {w_or}, b = {b_or}  (faqat b o'zgardi)")
    print(f"  {'x1':>4} {'x2':>4} {'z':>7} {'step(z)':>9}")
    for x in X:
        z = float(x @ w_or + b_or)
        print(f"  {x[0]:>4.0f} {x[1]:>4.0f} {z:>7.1f} {step(z):>9.0f}")
    print("  BIAS chegarani suradi - og'irliklar o'zgarmadi")

    print("\n=== 3. Bias nima uchun kerak ===")
    print(f"  {'holat':<22} {'z(0,0)':>8} {'natija':>8}")
    for nom, b in [("b = 0 (bias yo'q)", 0.0), ("b = -0.5", -0.5),
                   ("b = +0.5", 0.5)]:
        z = float(np.zeros(2) @ w_or + b)
        print(f"  {nom:<22} {z:>8.1f} {step(z):>8.0f}")
    print("  b = 0 bo'lsa chegara HAR DOIM (0,0) dan o'tadi")

    print("\n=== 4. Chegara chizig'i ===")
    print("  w·x + b = 0  =>  x2 = -(w1/w2)*x1 - b/w2")
    for nom, w, b in [("AND", w_and, b_and), ("OR", w_or, b_or)]:
        qiya = -w[0] / w[1]
        kesim = -b / w[1]
        print(f"  {nom:<4} x2 = {qiya:+.1f}*x1 {kesim:+.1f}")

    print("\n=== 5. Aktivatsiyasiz nima bo'ladi ===")
    W1 = np.array([[0.5, -1.0], [2.0, 0.3]])
    W2 = np.array([[1.5], [-0.7]])
    ikki_qatlam = (X @ W1) @ W2          # aktivatsiya YO'Q
    birlashgan = X @ (W1 @ W2)           # bitta matritsa
    print(f"  ikki qatlam (f yo'q): {ikki_qatlam.ravel().round(4)}")
    print(f"  bitta matritsa:       {birlashgan.ravel().round(4)}")
    print(f"  bir xilmi: {np.allclose(ikki_qatlam, birlashgan)}")
    print("  ⭐ Aktivatsiyasiz N qatlam = 1 qatlam")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Qo'lda qo'yilgan og'irliklar: AND ===
  w = [1. 1.], b = -1.5
    x1   x2   z = w·x + b   step(z)
     0    0          -1.5         0
     0    1          -0.5         0
     1    0          -0.5         0
     1    1           0.5         1

=== 2. Bir xil tuzilma, boshqa bias: OR ===
  w = [1. 1.], b = -0.5  (faqat b o'zgardi)
    x1   x2       z   step(z)
     0    0    -0.5         0
     0    1     0.5         1
     1    0     0.5         1
     1    1     1.5         1
  BIAS chegarani suradi - og'irliklar o'zgarmadi

=== 3. Bias nima uchun kerak ===
  holat                    z(0,0)   natija
  b = 0 (bias yo'q)           0.0        0
  b = -0.5                   -0.5        0
  b = +0.5                    0.5        1
  b = 0 bo'lsa chegara HAR DOIM (0,0) dan o'tadi

=== 4. Chegara chizig'i ===
  w·x + b = 0  =>  x2 = -(w1/w2)*x1 - b/w2
  AND  x2 = -1.0*x1 +1.5
  OR   x2 = -1.0*x1 +0.5

=== 5. Aktivatsiyasiz nima bo'ladi ===
  ikki qatlam (f yo'q): [0.   2.79 1.45 4.24]
  bitta matritsa:       [0.   2.79 1.45 4.24]
  bir xilmi: True
  ⭐ Aktivatsiyasiz N qatlam = 1 qatlam

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

Misol 2 — Perseptron o'rgatish qoidasi

python
"""Rosenblatt qoidasi: yaqinlashish va aylanish (real numpy)."""

import numpy as np


def perseptron_orgat(X, y, eta=0.1, davrlar=50):
    """Og'irliklarni qaytaradi + har davrdagi xatolar soni."""
    w = np.zeros(X.shape[1])
    b = 0.0
    tarix = []
    for _ in range(davrlar):
        xatolar = 0
        for xi, yi in zip(X, y):
            bashorat = 1.0 if xi @ w + b > 0 else 0.0
            xato = yi - bashorat
            if xato != 0:
                w = w + eta * xato * xi
                b = b + eta * xato
                xatolar += 1
        tarix.append(xatolar)
        if xatolar == 0:
            break
    return w, b, tarix


def main() -> None:
    X = np.array([[0.0, 0.0], [0.0, 1.0], [1.0, 0.0], [1.0, 1.0]])
    vazifalar = {
        "AND": np.array([0.0, 0.0, 0.0, 1.0]),
        "OR": np.array([0.0, 1.0, 1.0, 1.0]),
        "XOR": np.array([0.0, 1.0, 1.0, 0.0]),
    }

    print("=== 1. Uch mantiqiy vazifa ===")
    print(f"  {'vazifa':<6} {'davrlar':>8} {'yaqinlashdi':>12} "
          f"{'w':>18} {'b':>7}")
    natijalar = {}
    for nom, y in vazifalar.items():
        w, b, tarix = perseptron_orgat(X, y)
        natijalar[nom] = (w, b, tarix)
        print(f"  {nom:<6} {len(tarix):>8} "
              f"{str(tarix[-1] == 0):>12} "
              f"{str(w.round(2)):>18} {b:>7.2f}")

    print("\n=== 2. Xatolar tarixi ===")
    for nom in vazifalar:
        tarix = natijalar[nom][2]
        print(f"  {nom:<6} {tarix[:12]}")
    print("  XOR hech qachon nolga tushmaydi - abadiy aylanadi")

    print("\n=== 3. Qadamma-qadam (OR, birinchi davr) ===")
    w, b = np.zeros(2), 0.0
    y = vazifalar["OR"]
    print(f"  {'x':<10} {'y':>3} {'bashorat':>9} {'xato':>6} "
          f"{'yangi w':<14} {'yangi b':>8}")
    for xi, yi in zip(X, y):
        bashorat = 1.0 if xi @ w + b > 0 else 0.0
        xato = yi - bashorat
        w = w + 0.1 * xato * xi
        b = b + 0.1 * xato
        print(f"  {str(xi):<10} {yi:>3.0f} {bashorat:>9.0f} {xato:>6.0f} "
              f"{str(w.round(2)):<14} {b:>8.2f}")

    print("\n=== 4. Boshlang'ich nuqta natijaga ta'sir qiladimi ===")
    rng = np.random.default_rng(0)
    y_and = vazifalar["AND"]
    print(f"  {'urinish':>8} {'davrlar':>8} {'w':>18} {'b':>7}")
    for i in range(4):
        w = rng.normal(0, 1, 2)
        b = float(rng.normal())
        davr = 0
        for davr in range(1, 51):
            xatolar = 0
            for xi, yi in zip(X, y_and):
                bashorat = 1.0 if xi @ w + b > 0 else 0.0
                xato = yi - bashorat
                if xato != 0:
                    w = w + 0.1 * xato * xi
                    b = b + 0.1 * xato
                    xatolar += 1
            if xatolar == 0:
                break
        print(f"  {i + 1:>8} {davr:>8} {str(w.round(2)):>18} {b:>7.2f}")
    print("  yechim BITTA emas - cheksiz ko'p to'g'ri chiziq bor")

    print("\n=== 5. Chiziqli ajraladigan real ma'lumot ===")
    rng = np.random.default_rng(42)
    A = rng.normal([-2, -2], 0.7, size=(60, 2))
    B = rng.normal([2, 2], 0.7, size=(60, 2))
    Xr = np.vstack([A, B])
    yr = np.r_[np.zeros(60), np.ones(60)]
    w, b, tarix = perseptron_orgat(Xr, yr, eta=0.01, davrlar=100)
    aniqlik = ((Xr @ w + b > 0).astype(float) == yr).mean()
    print(f"  davrlar: {len(tarix)}, oxirgi xatolar: {tarix[-1]}")
    print(f"  aniqlik: {aniqlik:.4f}")
    print(f"  w = {w.round(3)}, b = {b:.3f}")
    print("  ⭐ Ajraladigan bo'lsa - kafolatlangan yaqinlashish")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Uch mantiqiy vazifa ===
  vazifa  davrlar  yaqinlashdi                  w       b
  AND           6         True          [0.2 0.1]   -0.20
  OR            4         True          [0.1 0.1]    0.00
  XOR          50        False        [-0.1  0. ]    0.10

=== 2. Xatolar tarixi ===
  AND    [1, 3, 3, 2, 1, 0]
  OR     [1, 2, 1, 0]
  XOR    [2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
  XOR hech qachon nolga tushmaydi - abadiy aylanadi

=== 3. Qadamma-qadam (OR, birinchi davr) ===
  x            y  bashorat   xato yangi w         yangi b
  [0. 0.]      0         0      0 [0. 0.]            0.00
  [0. 1.]      1         0      1 [0.  0.1]          0.10
  [1. 0.]      1         1      0 [0.  0.1]          0.10
  [1. 1.]      1         1      0 [0.  0.1]          0.10

=== 4. Boshlang'ich nuqta natijaga ta'sir qiladimi ===
   urinish  davrlar                  w       b
         1       10        [0.23 0.07]   -0.26
         2       11        [0.2  0.06]   -0.24
         3        4        [1.   0.85]   -1.10
         4       19        [0.23 0.08]   -0.26
  yechim BITTA emas - cheksiz ko'p to'g'ri chiziq bor

=== 5. Chiziqli ajraladigan real ma'lumot ===
  davrlar: 2, oxirgi xatolar: 0
  aniqlik: 1.0000
  w = [0.013 0.021], b = 0.010
  ⭐ Ajraladigan bo'lsa - kafolatlangan yaqinlashish

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

Misol 3 — XOR ni ikki qatlam bilan yechish

python
"""Yashirin qatlam ma'lumotni yangi fazoga ko'chiradi (real numpy)."""

import numpy as np


def step(z):
    return (z > 0).astype(float)


def main() -> None:
    X = np.array([[0.0, 0.0], [0.0, 1.0], [1.0, 0.0], [1.0, 1.0]])
    y = np.array([0.0, 1.0, 1.0, 0.0])

    print("=== 1. Qo'lda qurilgan tarmoq ===")
    W1 = np.array([[1.0, 1.0],
                   [1.0, 1.0]])           # (kirish=2, yashirin=2)
    b1 = np.array([-0.5, -1.5])           # h1 = OR, h2 = AND
    W2 = np.array([[1.0], [-1.0]])        # (yashirin=2, chiqish=1)
    b2 = np.array([-0.5])
    print(f"  W1 =\n{W1}")
    print(f"  b1 = {b1}   -> h1 = OR, h2 = AND")
    print(f"  W2 = {W2.ravel()}, b2 = {b2}  -> y = h1 VA h2 EMAS")

    print("\n=== 2. Qadamma-qadam hisob ===")
    H = step(X @ W1 + b1)
    Y = step(H @ W2 + b2)
    print(f"  {'x1':>3} {'x2':>3} | {'h1(OR)':>7} {'h2(AND)':>8} | "
          f"{'y':>3} {'kerak':>6}")
    for i in range(4):
        print(f"  {X[i, 0]:>3.0f} {X[i, 1]:>3.0f} | {H[i, 0]:>7.0f} "
              f"{H[i, 1]:>8.0f} | {Y[i, 0]:>3.0f} {y[i]:>6.0f}")
    print(f"  hammasi to'g'rimi: {np.array_equal(Y.ravel(), y)}")

    print("\n=== 3. Yashirin qatlam nima qildi ===")
    print(f"  {'asl (x1,x2)':<14} {'sinf':>5} {'yangi (h1,h2)':<16}")
    for i in range(4):
        print(f"  {str(X[i]):<14} {y[i]:>5.0f} {str(H[i]):<16}")
    print("  (0,1) va (1,0) YANGI fazoda AYNI nuqtaga tushdi")
    print("  endi bitta chiziq yetarli")

    print("\n=== 4. Yangi fazoda chiziqli ajralish ===")
    nol = H[y == 0]
    bir = H[y == 1]
    print(f"  sinf 0 nuqtalari: {[tuple(t) for t in nol]}")
    print(f"  sinf 1 nuqtalari: {[tuple(t) for t in bir]}")
    print(f"  ajratuvchi: h1 - h2 - 0.5 = 0")
    for i in range(4):
        qiymat = float(H[i] @ W2.ravel() + b2[0])
        print(f"    {str(H[i]):<12} -> {qiymat:>5.1f} "
              f"({'1' if qiymat > 0 else '0'})")

    print("\n=== 5. Bitta neyron urinib ko'radi ===")
    eng_yaxshi = (-1.0, None)
    rng = np.random.default_rng(0)
    for _ in range(20000):
        w = rng.uniform(-3, 3, 2)
        b = rng.uniform(-3, 3)
        ball = (step(X @ w + b) == y).mean()
        if ball > eng_yaxshi[0]:
            eng_yaxshi = (ball, (w.round(2), round(b, 2)))
    print(f"  20000 ta tasodifiy chiziqdan eng yaxshisi: "
          f"{eng_yaxshi[0]:.2f}")
    print(f"  og'irliklar: {eng_yaxshi[1]}")
    print("  4 tadan 3 tasi - bu chegara, izlash muammosi EMAS")
    print("  ⭐ XOR uchun yashirin qatlam SHART")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Qo'lda qurilgan tarmoq ===
  W1 =
[[1. 1.]
 [1. 1.]]
  b1 = [-0.5 -1.5]   -> h1 = OR, h2 = AND
  W2 = [ 1. -1.], b2 = [-0.5]  -> y = h1 VA h2 EMAS

=== 2. Qadamma-qadam hisob ===
   x1  x2 |  h1(OR)  h2(AND) |   y  kerak
    0   0 |       0        0 |   0      0
    0   1 |       1        0 |   1      1
    1   0 |       1        0 |   1      1
    1   1 |       1        1 |   0      0
  hammasi to'g'rimi: True

=== 3. Yashirin qatlam nima qildi ===
  asl (x1,x2)     sinf yangi (h1,h2)
  [0. 0.]            0 [0. 0.]
  [0. 1.]            1 [1. 0.]
  [1. 0.]            1 [1. 0.]
  [1. 1.]            0 [1. 1.]
  (0,1) va (1,0) YANGI fazoda AYNI nuqtaga tushdi
  endi bitta chiziq yetarli

=== 4. Yangi fazoda chiziqli ajralish ===
  sinf 0 nuqtalari: [(np.float64(0.0), np.float64(0.0)), (np.float64(1.0), np.float64(1.0))]
  sinf 1 nuqtalari: [(np.float64(1.0), np.float64(0.0)), (np.float64(1.0), np.float64(0.0))]
  ajratuvchi: h1 - h2 - 0.5 = 0
    [0. 0.]      ->  -0.5 (0)
    [1. 0.]      ->   0.5 (1)
    [1. 0.]      ->   0.5 (1)
    [1. 1.]      ->  -0.5 (0)

=== 5. Bitta neyron urinib ko'radi ===
  20000 ta tasodifiy chiziqdan eng yaxshisi: 0.75
  og'irliklar: (array([1.81, 2.54]), -1.4)
  4 tadan 3 tasi - bu chegara, izlash muammosi EMAS
  ⭐ XOR uchun yashirin qatlam SHART

Nima ko'rsatdi: 2.5-bo'lim.

Misol 4 — Perseptron va logistik regressiya

python
"""Step va sigmoid: nima farqi bor (real numpy/sklearn)."""

import numpy as np
from sklearn.linear_model import LogisticRegression, Perceptron
from sklearn.metrics import accuracy_score


def main() -> None:
    rng = np.random.default_rng(7)
    A = rng.normal([-1.5, -1.0], 1.0, size=(120, 2))
    B = rng.normal([1.5, 1.0], 1.0, size=(120, 2))
    X = np.vstack([A, B])
    y = np.r_[np.zeros(120), np.ones(120)]

    print("=== 1. Aktivatsiya funksiyalari ===")
    z = np.array([-4.0, -1.0, -0.1, 0.0, 0.1, 1.0, 4.0])
    step = (z > 0).astype(float)
    sigmoid = 1 / (1 + np.exp(-z))
    print(f"  {'z':>6} {'step(z)':>9} {'sigmoid(z)':>12}")
    for i in range(len(z)):
        print(f"  {z[i]:>6.1f} {step[i]:>9.0f} {sigmoid[i]:>12.4f}")
    print("  step - sakrash, sigmoid - silliq o'tish")

    print("\n=== 2. Hosilalar ===")
    h = 1e-5
    step_hosila = ((z + h > 0).astype(float)
                   - (z - h > 0).astype(float)) / (2 * h)
    sig_hosila = sigmoid * (1 - sigmoid)
    print(f"  {'z':>6} {'step hosilasi':>15} {'sigmoid hosilasi':>18}")
    for i in range(len(z)):
        print(f"  {z[i]:>6.1f} {step_hosila[i]:>15.1f} "
              f"{sig_hosila[i]:>18.6f}")
    print("  ⭐ step hosilasi z=0 dan boshqa joyda NOL")
    print("  gradient tushish uchun yaroqsiz")

    print("\n=== 3. Ikkala modelni o'rgatamiz ===")
    p = Perceptron(max_iter=1000, tol=1e-3, random_state=0).fit(X, y)
    lr = LogisticRegression(max_iter=2000).fit(X, y)
    print(f"  {'model':<22} {'aniqlik':>9} {'w':>20} {'b':>8}")
    for nom, m in [("Perceptron", p), ("LogisticRegression", lr)]:
        a = accuracy_score(y, m.predict(X))
        print(f"  {nom:<22} {a:>9.4f} "
              f"{str(m.coef_[0].round(3)):>20} {m.intercept_[0]:>8.3f}")

    print("\n=== 4. Chiqish turi ===")
    namuna = X[[0, 1, 120, 121]]
    print(f"  {'nuqta':<20} {'perseptron':>11} {'logreg P(1)':>13}")
    for i, x in enumerate(namuna):
        pp = int(p.predict(x.reshape(1, -1))[0])
        lp = float(lr.predict_proba(x.reshape(1, -1))[0, 1])
        print(f"  {str(x.round(2)):<20} {pp:>11} {lp:>13.4f}")
    print("  perseptron faqat SINF, logreg ISHONCH darajasini beradi")

    print("\n=== 5. Chegaraga yaqin nuqtalar ===")
    masofa = np.abs(lr.decision_function(X))
    yaqin = np.argsort(masofa)[:5]
    print(f"  {'masofa':>9} {'P(1)':>8} {'haqiqiy':>8}")
    for i in yaqin:
        print(f"  {masofa[i]:>9.4f} "
              f"{lr.predict_proba(X[i:i + 1])[0, 1]:>8.4f} "
              f"{y[i]:>8.0f}")
    print("  logreg chegaraga yaqin nuqtalarda ~0.5 beradi")
    print("  ⭐ Ehtimollik - qaror qabul qilish uchun ZARUR")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Aktivatsiya funksiyalari ===
       z   step(z)   sigmoid(z)
    -4.0         0       0.0180
    -1.0         0       0.2689
    -0.1         0       0.4750
     0.0         0       0.5000
     0.1         1       0.5250
     1.0         1       0.7311
     4.0         1       0.9820
  step - sakrash, sigmoid - silliq o'tish

=== 2. Hosilalar ===
       z   step hosilasi   sigmoid hosilasi
    -4.0             0.0           0.017663
    -1.0             0.0           0.196612
    -0.1             0.0           0.249376
     0.0         50000.0           0.250000
     0.1             0.0           0.249376
     1.0             0.0           0.196612
     4.0             0.0           0.017663
  ⭐ step hosilasi z=0 dan boshqa joyda NOL
  gradient tushish uchun yaroqsiz

=== 3. Ikkala modelni o'rgatamiz ===
  model                    aniqlik                    w        b
  Perceptron                0.9792        [2.944 1.026]    1.000
  LogisticRegression        0.9833        [2.477 1.557]    0.591

=== 4. Chiqish turi ===
  nuqta                 perseptron   logreg P(1)
  [-1.5 -0.7]                    0        0.0146
  [-1.77 -1.89]                  0        0.0012
  [1.04 1.74]                    1        0.9972
  [1.42 1.08]                    1        0.9969
  perseptron faqat SINF, logreg ISHONCH darajasini beradi

=== 5. Chegaraga yaqin nuqtalar ===
     masofa     P(1)  haqiqiy
     0.0032   0.5008        1
     0.3498   0.5866        1
     0.3961   0.5977        1
     0.4945   0.3788        0
     0.6576   0.6587        0
  logreg chegaraga yaqin nuqtalarda ~0.5 beradi
  ⭐ Ehtimollik - qaror qabul qilish uchun ZARUR

Nima ko'rsatdi: 2.6-bo'lim.


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

Noto'g'ri fikr To'g'risi
"Neyron miya neyroni kabi" Juda soddalashtirilgan matematik model
"Qatlam ko'paysa kuch ortadi" Aktivatsiyasiz — yo'q, baribir chiziqli
"Bias ixtiyoriy" Usiz chegara koordinata boshidan o'tadi
"Perseptron har doim yaqinlashadi" Faqat chiziqli ajraladigan ma'lumotda
"XOR — izlash muammosi" Chegara: bitta chiziq yeta olmaydi
"Step yaxshi aktivatsiya" Hosilasi nol — o'rgatib bo'lmaydi
"Perseptron = logistik regressiya" Chiqish, loss va xossalar boshqa
"Yashirin qatlam sehrli" U shunchaki koordinatani almashtiradi

6. Keng tarqalgan xatolar va yechimlari

1. Aktivatsiyasiz qatlamlar

python
a = (X @ W1) @ W2                    # ⚠️ baribir chiziqli
a = f(f(X @ W1 + b1) @ W2 + b2)      # ✅

2. Bias yo'q

python
z = X @ w                            # ⚠️ chegara (0,0) dan o'tadi
z = X @ w + b                        # ✅

3. Perseptronni ajralmaydigan ma'lumotda

python
while xatolar > 0: ...               # ⚠️ abadiy aylanadi
for _ in range(davrlar): ...         # ✅ + eng yaxshisini saqlang

4. Step bilan gradient

python
grad = hosila(step)(z)               # ⚠️ hamma joyda nol
grad = sigmoid(z) * (1 - sigmoid(z)) # ✅

5. Og'irliklarni nol bilan boshlash

python
W1 = np.zeros((2, 8))                # ⚠️ 8 neyron bir xil qoladi
W1 = rng.normal(0, 0.5, (2, 8))      # ✅ simmetriyani buzadi

6. XOR ni bitta neyron bilan

python
Perceptron().fit(X_xor, y_xor)       # ⚠️ 0.75 dan oshmaydi
MLPClassifier(hidden_layer_sizes=(2,))  # ✅

7. Chegarani ehtimollik deb o'qish

python
p.predict(x)                          # ⚠️ 0/1, ishonch yo'q
lr.predict_proba(x)                   # ✅

7. Integratsiya — bu bilim qayerda kerak bo'ladi

  • 14-qism (o'tilgan): Logistik regressiya
  • 10-qism (o'tilgan): Matritsa ko'paytmasi
  • 20.2-dars: Aktivatsiya funksiyalari
  • 20.4-dars: Oldinga tarqalish
  • 21-qism: PyTorch

8. Eng yaxshi amaliyotlar

  1. Har doim bias qo'shing.

  2. Aktivatsiyasiz qatlam qo'shmang.

  3. Og'irliklarni tasodifiy boshlang.

  4. Davrlar soniga chegara qo'ying.

  5. Chiqish sifatida ehtimollik oling.

  6. Kirishlarni masshtablang.

  7. Avval chiziqli modelni sinang.

  8. Qatlamni koordinata almashtirish deb o'ylang.


9. Amaliy topshiriq

Vazifa 1: Bashorat qiling

python
1.  # neyron necha qadamdan iborat?
2.  # bias nima qiladi?
3.  # aktivatsiyasiz 5 qatlam nimaga teng?
4.  # perseptron qachon yaqinlashadi?
5.  # XOR nega yechilmaydi?
6.  # yashirin qatlam nima qiladi?
7.  # step hosilasi nechaga teng?
8.  # perseptron ehtimollik beradimi?
9.  # og'irlikni nol qilsa nima bo'ladi?
10. # chegara tenglamasi qanday?
11. # xato = +1 bo'lsa w qayoqqa suriladi?
12. # eta nima?
Javoblar
  1. Ikki: chiziqli va nochiziqli
  2. Chegarani suradi
  3. Bitta chiziqli qatlamga
  4. Ma'lumot chiziqli ajralganda
  5. 1 lar diagonal joylashgan
  6. Koordinatani almashtiradi
  7. Nol (z=0 dan boshqa joyda)
  8. Yo'q, faqat sinf
  9. Bir qatlamdagi neyronlar bir xil qoladi
  10. w·x + b = 0
  11. x yo'nalishida
  12. O'rganish tezligi

Vazifa 2: Xatolarni tuzating

python
1.  a = (X @ W1) @ W2

2.  z = X @ w

3.  while xatolar > 0: ...

4.  W1 = np.zeros((2, 8))

5.  Perceptron().fit(X_xor, y_xor)
Javoblar
python
1.  a = f(f(X @ W1 + b1) @ W2 + b2)

2.  z = X @ w + b

3.  for _ in range(davrlar): ...

4.  W1 = rng.normal(0, 0.5, (2, 8))

5.  MLPClassifier(hidden_layer_sizes=(2,))

Vazifa 3: Neyron

Modellang:

  1. AND
  2. OR
  3. Bias
  4. Chegara

Vazifa 4: Perseptron

Modellang:

  1. Qoida
  2. Tarix
  3. Boshlang'ich
  4. Real ma'lumot

Vazifa 5: XOR

Modellang:

  1. Tarmoq
  2. Hisob
  3. Yangi fazo
  4. Bitta neyron

Vazifa 6: Taqqoslash

Modellang:

  1. Aktivatsiya
  2. Hosila
  3. Modellar
  4. Chiqish

Vazifa 7: O'ylash

Hamkasbingiz aytdi: "Men 50 qatlamli tarmoq qurdim, lekin u chiziqli regressiyadan yaxshi ishlamayapti." Birinchi navbatda nimani tekshirasiz?

Javob

Birinchi savol: qatlamlar orasida aktivatsiya bormi?

Aktivatsiyasiz 50 qatlam matematik jihatdan bitta qatlamga teng:

python
W_umumiy = W1 @ W2 @ W3 @ ... @ W50     # shunchaki bitta matritsa

Bu eng keng tarqalgan xato va uni tekshirish bir daqiqa oladi:

python
for nom, qatlam in model.named_children():
    print(nom, type(qatlam).__name__)
# Linear, Linear, Linear, ... -> ReLU yo'q -> muammo shu

Agar aktivatsiya bo'lsa, keyingi tekshiruvlar:

Tekshiruv Nima izlaymiz Belgi
Kirish masshtabi X.std() 1 atrofidami 1000 bo'lsa — gradient portlaydi
Og'irlik boshlanishi Nol emasmi, juda kichik emasmi Hammasi bir xil chiqish
O'rganish tezligi Loss kamayayaptimi Yassi yoki NaN
Gradient oqimi Birinchi qatlam gradienti ~0 bo'lsa — yo'qolayotgan gradient
Ma'lumot hajmi Namuna / parametr nisbati 50 qatlam uchun juda kam
Vazifa turi Bog'liqlik chindan nochiziqlimi Chiziqli bo'lsa — 50 qatlam ortiqcha

Muhim nuans: 50 qatlam o'zi muammo bo'lishi mumkin. Chuqur tarmoqda gradient orqaga tarqalganda har qatlamda ko'payib boradi va yo'qolib yoki portlab ketadi. Shuning uchun zamonaviy chuqur tarmoqlarda BatchNorm, residual ulanishlar va ehtiyotkor boshlash ishlatiladi (20.8-dars).

Amaliy tartib:

  1. Aktivatsiyani tekshiring
  2. 50 qatlamni 2 qatlamga tushiring va taqqoslang
  3. 2 qatlam chiziqlidan yaxshi bo'lsa — chuqurlikni asta oshiring
  4. 2 qatlam ham yaxshi bo'lmasa — muammo ma'lumotda yoki vazifada

Eng muhimi: chiziqli regressiyadan yaxshi ishlamayotgan tarmoq ko'pincha chiziqli tarmoqdir.

Nimani mustahkamlaydi: 2.1, 2.5-bo'limlar.


Xulosa

Bu darsda neyronning ichini ochdik.

Eng muhim uch fikr:

  1. Neyron ikki qadamdan iborat: chiziqli va nochiziqli. z = w·x + b kirishlarni og'irliklar bilan aralashtiradi, a = f(z) esa natijani egadi. Ikkinchi qadamsiz qancha qatlam qo'ysangiz ham hammasi bitta matritsaga yig'iladi — bu 1-misolda raqam bilan ko'rsatildi. Bias esa chegarani koordinata boshidan ajratadi.

  2. Perseptron qoidasi oddiy, lekin cheklangan. w += eta * xato * x — atigi bitta qator, va Novikoff teoremasi bo'yicha ma'lumot chiziqli ajraladigan bo'lsa u chekli qadamda to'xtaydi. Ajralmasa — abadiy aylanadi. XOR da 20 000 tasodifiy chiziqdan eng yaxshisi ham 4 tadan 3 tasini topdi.

  3. Yashirin qatlam — koordinata almashtirish. XOR ni yechgan tarmoq sehrgarlik qilmadi: u (0,1) va (1,0) nuqtalarini yangi fazoda ayni nuqtaga ko'chirdi, shundan keyin oxirgi qatlam oddiy chiziq chizdi. Chuqur o'rganishning butun g'oyasi shu — oson ajraladigan tasvir qurish.

Keyingi darsda aktivatsiya funksiyalarini batafsil ko'ramiz: sigmoid, tanh, ReLU va uning avlodlari; qaysi biri qachon, nima uchun ReLU standart bo'lib qolgani va "o'lgan neyron" muammosi.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
20.1-dars: Neyron va perseptron — IlmHamroh