Asosiy qismga o'tish

Vektor va matritsa — ma'lumotning tili

12-bob 14 kod bloki 2933 so'z

Bu bobdagi kod shu fayllar bilan ishlaydio'z kompyuteringizda ishga tushiring

Sahna: nega matematika kerak

Siz 10-bobga qadar model qurdingiz, bahladingiz, xatolarini tahlil qildingiz. Matematika kerak bo'lmadi.

Shunday bo'lsa, nega endi kerak?

Chunki fit() ning ichida nima bo'layotganini bilmasangiz, siz uchta narsani qilolmaysiz:

  1. Model nega aynan shunday bashorat qilganini tushuntirish
  2. Model yiqilganda nega yiqilganini topish
  3. Yangi algoritmni o'rganganda uni oldingilariga bog'lash

Bu qism — kitobdagi eng "matematik" uch bob. Lekin qo'rqmang: bizga faqat uchta amal kerak bo'ladi, va ularning hammasini numpy bajaradi.

Agar matematikadan qo'rqsangiz

Bu bobni o'tkazib yuborib, 14-bobga o'tsangiz ham kitob ishlaydi. Keyin qaytib kelasiz.

Lekin bitta narsani bilib qo'ying: pastdagi skalyar ko'paytma — bu butun ML dagi eng muhim amal. U logistic regression da ham, neyron tarmoqda ham, Transformer da ham aynan bir xil ishlaydi.

Bitta qator — bu vektor

python13 qator
import pandas as pd
import numpy as np

df = pd.read_csv(DATA / "uy_ijara.csv")
son = ["xonalar", "maydon_m2", "metro_km", "mebel"]

bitta = df.loc[0, son]
print("Bitta kvartira (bitta qator):")
print(bitta.to_string())
print()
x = bitta.to_numpy(dtype=float)
print("numpy vektori:", x)
print("shakli (shape):", x.shape, " -> 4 ta son")
Chiqish
Bitta kvartira (bitta qator):
xonalar         2
maydon_m2    40.6
metro_km     1.43
mebel           1

numpy vektori: [ 2.   40.6   1.43  1.  ]
shakli (shape): (4,)  -> 4 ta son

Matematikada bu shunday yoziladi:

Qalin harf x — vektor (sonlar ro'yxati). Oddiy

— uning birinchi elementi.

Butun jadval — bu matritsa

python11 qator
X = df[son].to_numpy(dtype=float)
print("Butun jadval:")
print(f"  shakli: {X.shape}  ->  {X.shape[0]} qator (namuna), {X.shape[1]} ustun (xususiyat)")
print()
print("Birinchi 3 qator:")
print(X[:3])
print()
print("Matritsadan element olish:")
print(f"  X[0, 1] = {X[0, 1]}      -> 1-qator, 2-ustun (birinchi kvartiraning maydoni)")
print(f"  X[0]    = {X[0]}  -> butun 1-qator (bitta kvartira)")
print(f"  X[:, 1][:5] = {X[:, 1][:5]}  -> 2-ustunning birinchi 5 qiymati (maydonlar)")
Chiqish
Butun jadval:
  shakli: (1200, 4)  ->  1200 qator (namuna), 4 ustun (xususiyat)

Birinchi 3 qator:
[[  2.    40.6    1.43   1.  ]
 [  2.    55.5    4.18   1.  ]
 [  5.   114.     3.84   1.  ]]

Matritsadan element olish:
  X[0, 1] = 40.6      -> 1-qator, 2-ustun (birinchi kvartiraning maydoni)
  X[0]    = [ 2.   40.6   1.43  1.  ]  -> butun 1-qator (bitta kvartira)
  X[:, 1][:5] = [ 40.6  55.5 114.   72.1  46.4]  -> 2-ustunning birinchi 5 qiymati (maydonlar)

Qoida: qator — namuna, ustun — xususiyat. sklearn har doim shu shaklni kutadi: (n_samples, n_features).

`shape` ni har doim tekshiring

ML dagi xatolarning yarmi shakl mos kelmasligidan chiqadi:

ValueError: Found input variables with inconsistent numbers of samples: [840, 360]

Bu xatoni ko'rganingizda birinchi ish — print(X.shape, y.shape). Ikkinchi ish — qaysi biri noto'g'ri ekanini aniqlash.

Eng muhim amal: skalyar ko'paytma

Endi butun ML ning yuragiga keldik.

Savol: kvartiraning narxini bashorat qilish uchun nima qilamiz?

Har bir xususiyatga vazn beramiz va qo'shamiz:

python14 qator
# vaznlar: har bir xususiyat narxga qancha ta'sir qiladi
w = np.array([55.0, 7.5, -28.0, 90.0])
b = 180.0            # bias (boshlang'ich qiymat)

print("Vaznlar va ularning ma'nosi:")
for nom, vazn in zip(son, w):
    print(f"  {nom:12s} {vazn:>7.1f}")
print(f"  {'bias':12s} {b:>7.1f}")
print()
print("Bitta kvartira uchun bashorat — QO'LDA:")
qadamlar = [f"{x[i]:.2f} x {w[i]:.1f}" for i in range(len(w))]
print("  " + " + ".join(qadamlar) + f" + {b:.0f}")
bashorat_qolda = sum(x[i] * w[i] for i in range(len(w))) + b
print(f"  = {bashorat_qolda:.2f}")
Chiqish
Vaznlar va ularning ma'nosi:
  xonalar         55.0
  maydon_m2        7.5
  metro_km       -28.0
  mebel           90.0
  bias           180.0

Bitta kvartira uchun bashorat — QO'LDA:
  2.00 x 55.0 + 40.60 x 7.5 + 1.43 x -28.0 + 1.00 x 90.0 + 180
  = 644.46

Endi xuddi shu hisobni bitta amal bilan:

python4 qator
bashorat_dot = x @ w + b          # @ — skalyar ko'paytma belgisi
print(f"x @ w + b = {bashorat_dot:.2f}")
print(f"Qo'lda hisoblangan: {bashorat_qolda:.2f}")
print(f"Bir xilmi: {np.isclose(bashorat_dot, bashorat_qolda)}")
Chiqish
x @ w + b = 644.46
Qo'lda hisoblangan: 644.46
Bir xilmi: True

Mana shu — skalyar ko'paytma (dot product). Matematikada:

Bu formula butun kitobda takrorlanadi

  • Linear regression (14-bob): y = x @ w + b — aynan shu
  • Logistic regression (15-bob): sigmoid(x @ w + b) — ustiga bitta funksiya
  • Neyron tarmoq (29-bob): activation(x @ W + b) — shu amal, ko'p qatlamda takrorlangan
  • Transformer (35-bob): attention ichida ham skalyar ko'paytma

Ya'ni siz hozir bitta amalni o'rganyapsiz, va u kitobning oxirigacha yetadi.

Butun jadval uchun birdan: matritsa ko'paytirish

Bitta kvartira uchun bashorat qildik. 1200 tasi uchun-chi? Sikl yozamizmi?

python22 qator
import time

# 1-yo'l: sikl bilan
t0 = time.perf_counter()
bashoratlar_sikl = []
for i in range(len(X)):
    s = 0.0
    for j in range(X.shape[1]):
        s += X[i, j] * w[j]
    bashoratlar_sikl.append(s + b)
sikl_vaqti = time.perf_counter() - t0
bashoratlar_sikl = np.array(bashoratlar_sikl)

# 2-yo'l: matritsa ko'paytirish
t0 = time.perf_counter()
bashoratlar_vek = X @ w + b
vek_vaqti = time.perf_counter() - t0

print(f"Sikl bilan    : {sikl_vaqti*1000:.2f} ms")
print(f"X @ w bilan   : {vek_vaqti*1000:.4f} ms")
print(f"Natijalar bir xilmi: {np.allclose(bashoratlar_sikl, bashoratlar_vek)}")
print(f"Tezlik farqi  : {sikl_vaqti/max(vek_vaqti, 1e-9):.0f} barobar")
Chiqish
Sikl bilan    : 0.83 ms
X @ w bilan   : 0.0118 ms
Natijalar bir xilmi: True
Tezlik farqi  : 71 barobar

Bu tezlik farqi MENING kompyuterimda

Yuqoridagi "barobar" raqami sizda boshqa chiqadi — protsessor, numpy versiyasi, yuk hammasi ta'sir qiladi.

Lekin yo'nalish har doim bir xil: vektorlashtirilgan amal siklidan ancha tez. Sabab: numpy ichki qismi C tilida yozilgan va protsessorning SIMD ko'rsatmalaridan foydalanadi, Python sikli esa har qadamda interpretator orqali o'tadi.

Qoida: ML kodida for sikli ko'rsangiz, shubhalaning. Deyarli har doim vektorlashtirish yo'li bor.

python6 qator
print(f"X shakli      : {X.shape}")
print(f"w shakli      : {w.shape}")
print(f"X @ w shakli  : {(X @ w).shape}   -> har bir qator uchun bitta son")
print()
print("Birinchi 5 bashorat:", (X @ w + b)[:5].round(1))
print("Haqiqiy narxlar   :", df.narx_usd.head(5).to_numpy())
Chiqish
X shakli      : (1200, 4)
w shakli      : (4,)
X @ w shakli  : (1200,)   -> har bir qator uchun bitta son

Birinchi 5 bashorat: [ 644.5  679.2 1292.5  892.   509.8]
Haqiqiy narxlar   : [ 760  550 1415  985  550]

Vaznlarni men qo'lda yozdim, shuning uchun bashorat yaqin lekin aniq emas. 12-bobda model ularni o'zi topadi.

Shakl qoidasi: matritsa ko'paytirishning yagona sharti

python17 qator
A = np.array([[1., 2., 3.], [4., 5., 6.]])        # 2x3
B = np.array([[1., 0.], [0., 1.], [1., 1.]])      # 3x2
print(f"A shakli: {A.shape}")
print(f"B shakli: {B.shape}")
print(f"A @ B    : {(A @ B).shape}   <- 3 va 3 MOS keldi, natija 2x2")
print(A @ B)
print()
try:
    B @ A @ B @ A
except ValueError as e:
    pass
try:
    _ = A @ A
except ValueError as e:
    print("A @ A xato beradi:", str(e)[:62])
print()
print("QOIDA: (n x m) @ (m x k) = (n x k).  O'rtadagi ikki son MOS kelishi shart.")
Chiqish
A shakli: (2, 3)
B shakli: (3, 2)
A @ B    : (2, 2)   <- 3 va 3 MOS keldi, natija 2x2
[[ 4.  5.]
 [10. 11.]]

A @ A xato beradi: matmul: Input operand 1 has a mismatch in its core dimension 0

QOIDA: (n x m) @ (m x k) = (n x k).  O'rtadagi ikki son MOS kelishi shart.

Transpose — shaklni burish

python12 qator
print(f"X shakli   : {X.shape}")
print(f"X.T shakli : {X.T.shape}   <- qator va ustun almashdi")
print()
print("Nega kerak: ustunlar o'zaro bog'liqligini hisoblash uchun")
Xm = X - X.mean(axis=0)                      # markazlashtirish
kov = (Xm.T @ Xm) / (len(X) - 1)             # kovariatsiya matritsasi
print(f"Xm.T @ Xm shakli: {kov.shape}   <- 4x4, har ustun juftligi uchun bitta son")
print()
print("Korrelyatsiya (kovariatsiyadan normallashtirilgan):")
std = np.sqrt(np.diag(kov))
korr = kov / np.outer(std, std)
print(pd.DataFrame(korr.round(3), index=son, columns=son).to_string())
Chiqish
X shakli   : (1200, 4)
X.T shakli : (4, 1200)   <- qator va ustun almashdi

Nega kerak: ustunlar o'zaro bog'liqligini hisoblash uchun
Xm.T @ Xm shakli: (4, 4)   <- 4x4, har ustun juftligi uchun bitta son

Korrelyatsiya (kovariatsiyadan normallashtirilgan):
           xonalar  maydon_m2  metro_km  mebel
xonalar      1.000      0.940     0.036  0.013
maydon_m2    0.940      1.000     0.050  0.014
metro_km     0.036      0.050     1.000 -0.021
mebel        0.013      0.014    -0.021  1.000

xonalar va maydon_m2 orasida 0.94 — 3-bobda heatmap da ko'rgan raqam, endi qo'lda hisoblandi.

`X.T @ X` — PCA va normal tenglamaning yuragi

Bu ifoda kitobda yana ikki marta uchraydi: - 13-bobda normal tenglamada:

  • 26-bobda PCA da: kovariatsiya matritsasining xos vektorlari

Ikkisi ham aynan shu X.T @ X dan boshlanadi. Shuning uchun uni hozir tushunib olish foydali.

Broadcasting — numpy ning jim yordamchisi

python12 qator
print("Har bir ustundan uning o'rtachasini ayirish — SIKL KERAK EMAS:")
print(f"  X shakli          : {X.shape}")
print(f"  X.mean(axis=0)    : {X.mean(axis=0).shape}  -> 4 ta son")
markaz = X - X.mean(axis=0)
print(f"  X - mean natijasi : {markaz.shape}  <- numpy 4 ta sonni 1200 qatorga YOYDI")
print()
print(f"  Tekshiruv — yangi o'rtachalar: {markaz.mean(axis=0).round(10)}")
print()
print("Bu — broadcasting. StandardScaler ichida aynan shu bo'ladi:")
shkala = (X - X.mean(axis=0)) / X.std(axis=0)
print(f"  o'rtacha: {shkala.mean(axis=0).round(6)}")
print(f"  std     : {shkala.std(axis=0).round(6)}")
Chiqish
Har bir ustundan uning o'rtachasini ayirish — SIKL KERAK EMAS:
  X shakli          : (1200, 4)
  X.mean(axis=0)    : (4,)  -> 4 ta son
  X - mean natijasi : (1200, 4)  <- numpy 4 ta sonni 1200 qatorga YOYDI

  Tekshiruv — yangi o'rtachalar: [ 0.  0.  0. -0.]

Bu — broadcasting. StandardScaler ichida aynan shu bo'ladi:
  o'rtacha: [ 0.  0.  0. -0.]
  std     : [1. 1. 1. 1.]

4-bobda ishlatgan StandardScaler — bu ikki qatorlik amal. Endi uning ichini bilasiz.

Broadcasting jim xato ham qiladi

python3 qator
a = np.array([1, 2, 3])          # shakli (3,)
b = np.array([[1], [2], [3]])    # shakli (3, 1)
a + b                            # XATO BERMAYDI -> 3x3 matritsa qaytaradi!

Siz 3 elementli natija kutgandingiz, 9 element oldingiz. Kod ishlaydi, natija noto'g'ri.

Shuning uchun: har bir amaldan keyin shape ni tekshiring, ayniqsa o'zingiz yozgan hisoblarda.

python6 qator
a = np.array([1, 2, 3])
bb = np.array([[1], [2], [3]])
print(f"a shakli      : {a.shape}")
print(f"b shakli      : {bb.shape}")
print(f"a + b shakli  : {(a + bb).shape}   <- 3 ta son kutgandingiz, 9 ta oldingiz")
print(a + bb)
Chiqish
a shakli      : (3,)
b shakli      : (3, 1)
a + b shakli  : (3, 3)   <- 3 ta son kutgandingiz, 9 ta oldingiz
[[2 3 4]
 [3 4 5]
 [4 5 6]]

Norma — vektorning "uzunligi"

Regularizatsiya (16-bob) uchun bitta tushuncha kerak: vektor qanchalik "katta"?

python10 qator
v = np.array([3.0, 4.0])
print(f"v = {v}")
print()
print(f"L2 norma (Evklid)  : {np.linalg.norm(v, 2):.4f}   = sqrt(3^2 + 4^2)")
print(f"L1 norma (Manhattan): {np.linalg.norm(v, 1):.4f}   = |3| + |4|")
print()
print("Bizning vaznlarimiz uchun:")
print(f"  w = {w}")
print(f"  L2 norma: {np.linalg.norm(w, 2):.2f}")
print(f"  L1 norma: {np.linalg.norm(w, 1):.2f}")
Chiqish
v = [3. 4.]

L2 norma (Evklid)  : 5.0000   = sqrt(3^2 + 4^2)
L1 norma (Manhattan): 7.0000   = |3| + |4|

Bizning vaznlarimiz uchun:
  w = [ 55.    7.5 -28.   90. ]
  L2 norma: 109.39
  L1 norma: 180.50
python6 qator
show(pd.DataFrame([
    {"Norma": "L2 (kvadratlar yig'indisining ildizi)", "Formula": "sqrt(sum(w^2))",
     "Qayerda ishlatiladi": "Ridge regression — katta vaznni jazolaydi"},
    {"Norma": "L1 (mutlaq qiymatlar yig'indisi)", "Formula": "sum(|w|)",
     "Qayerda ishlatiladi": "Lasso — vaznni AYNAN nolga tushiradi"},
]))
NormaFormulaQayerda ishlatiladi
L2 (kvadratlar yig'indisining ildizi)sqrt(sum(w^2))Ridge regression — katta vaznni jazolaydi
L1 (mutlaq qiymatlar yig'indisi)sum(|w|)Lasso — vaznni AYNAN nolga tushiradi

16-bobda shu ikki norma ikki xil regularizatsiyani beradi — va nega Lasso xususiyat tanlaydi, L2 esa tanlamaydi, aynan shu farqdan chiqadi.

Bugun nima o'rgandik

python10 qator
show(pd.DataFrame([
    {"Tushuncha": "Vektor", "Kodda": "x = np.array([...])", "ML da": "Bitta namuna (bitta kvartira)"},
    {"Tushuncha": "Matritsa", "Kodda": "X.shape = (n, m)", "ML da": "n namuna, m xususiyat"},
    {"Tushuncha": "Skalyar ko'paytma", "Kodda": "x @ w + b", "ML da": "BITTA bashorat — eng muhim amal"},
    {"Tushuncha": "Matritsa ko'paytirish", "Kodda": "X @ w + b", "ML da": "HAMMA bashorat birdan"},
    {"Tushuncha": "Shakl qoidasi", "Kodda": "(n,m) @ (m,k) = (n,k)", "ML da": "Xatolarning yarmi shu yerda"},
    {"Tushuncha": "Transpose", "Kodda": "X.T", "ML da": "X.T @ X — normal tenglama va PCA"},
    {"Tushuncha": "Broadcasting", "Kodda": "X - X.mean(axis=0)", "ML da": "StandardScaler ning ichi"},
    {"Tushuncha": "L1 / L2 norma", "Kodda": "np.linalg.norm(w, 1/2)", "ML da": "Lasso va Ridge (16-bob)"},
]))
TushunchaKoddaML da
Vektorx = np.array([...])Bitta namuna (bitta kvartira)
MatritsaX.shape = (n, m)n namuna, m xususiyat
Skalyar ko'paytmax @ w + bBITTA bashorat — eng muhim amal
Matritsa ko'paytirishX @ w + bHAMMA bashorat birdan
Shakl qoidasi(n,m) @ (m,k) = (n,k)Xatolarning yarmi shu yerda
TransposeX.TX.T @ X — normal tenglama va PCA
BroadcastingX - X.mean(axis=0)StandardScaler ning ichi
L1 / L2 normanp.linalg.norm(w, 1/2)Lasso va Ridge (16-bob)

Keyingi bobda: vaznlarni men qo'lda yozdim. Model ularni qanday o'zi topadi?

Bu bobni bepul o'qidingiz.

Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.

Telegramda yozish Narxlar