aidoc.uz

4-qism · Ma'lumotlar bilan ishlash·19-bob

NumPy: raqamli hisoblashning poydevori

ndarray nima va nega u Python ro'yxatidan 20–100 baravar tez, dtype va shape, indekslash va boolean maskalar, view va copy, broadcasting, o'qlar (axis) bo'yicha agregatsiya, chiziqli algebra, tasodifiy sonlar va embedding'lar bilan amaliyot.

NumPy — Python'dagi butun ilmiy va ML ekotizimining poydevori. Pandas ichida NumPy massivlari, scikit-learn NumPy massivlarini qabul qiladi, PyTorch tensorlari NumPy massivlariga deyarli bir xil ishlaydi (va bir-biriga aylanadi), rasmlar — NumPy massivlari, embedding'lar — NumPy massivlari. Bu bobni yaxshi o'zlashtirsangiz, PyTorch'ga o'tish ancha oson bo'ladi: tensor operatsiyalarining 80% i — shu yerdagi g'oyalar.

uv add numpy
import numpy as np      # har doim shu taxallus bilan
▶ Video dars· freeCodeCamp.org· 58:09· ingliz tilida
Python NumPy Tutorial for Beginners

NumPy massivlari, indekslash, matematik amallar va broadcasting'ga amaliy kirish.

YouTube'da ochish ↗

1. Nega NumPy: tezlik va xotira#

1-bobda ko'rgan edik: sof Python'da har bir son — alohida obyekt (28 bayt), ro'yxat esa ularga ko'rsatkichlar massivi, va har bir amalda tip tekshiriladi. NumPy massivi esa — xotirada ketma-ket joylashgan, bir xil tipdagi xom sonlar:

NumPy ndarray
  • Bitta uzluksiz xotira bloki
  • Hamma elementlar bir xil tipda (masalan, float64 — 8 bayt)
  • Amallar C'da, bitta tsiklda — tip bir marta tekshiriladi
  • SIMD protsessor ko'rsatmalari, BLAS kutubxonalari
Python list
  • Ko'rsatkichlar massivi + har bir son alohida obyekt
  • Har element istalgan tipda bo'lishi mumkin
  • Har bir amalda interpretator tip tekshiradi
  • Million son ≈ 36 MB (NumPy'da ≈ 8 MB)

Real o'lchov (million son kvadratlari yig'indisi):

import time
import numpy as np
 
n = 1_000_000
lst = list(range(n))
arr = np.arange(n)
 
t = time.perf_counter(); s1 = sum(x * x for x in lst); print(time.perf_counter() - t)   # ~0.038 s
t = time.perf_counter(); s2 = (arr * arr).sum();      print(time.perf_counter() - t)   # ~0.0016 s

~25 baravar tezroq, va bu oddiy amal uchun. Murakkabroq amallarda (matritsa ko'paytmasi) farq yuzlab–minglab baravarga yetadi. Bu usul — vektorlashtirish (vectorization): siklni Python'da yozish o'rniga, butun massiv ustida bitta amal.

2. ndarray — asosiy tushunchalar#

a = np.array([1, 2, 3])
a.dtype       # dtype('int64') — elementlar tipi
a.shape       # (3,) — har o'lchamdagi uzunlik (tuple!)
a.ndim        # 1 — o'lchamlar soni
a.size        # 3 — jami elementlar
a.nbytes      # 24 — 3 × 8 bayt
 
m = np.arange(12).reshape(3, 4)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]
m.shape       # (3, 4) — 3 qator, 4 ustun
m.T.shape     # (4, 3) — transpoze

Shape — NumPy va PyTorch'ning eng muhim tushunchasi. ML'dagi xatolarning katta qismi — shape mos kelmasligi. Har doim shape haqida o'ylang va kerak bo'lsa print(x.shape) qiling.

Ma'lumotOdatiy shape
Bitta embedding(768,)
Embedding'lar to'plami(n_docs, 768)
Jadval (tabular)(n_samples, n_features)
Kulrang rasm(H, W)
Rangli rasm(H, W, 3) — NumPy/PIL; (3, H, W) — PyTorch
Rasmlar batch'i(batch, 3, H, W)
Matn token'lari batch'i(batch, seq_len)
Transformer yashirin holati(batch, seq_len, d_model)

dtype#

np.array([1, 2.5]).dtype           # float64 — bitta float hammasini float qiladi
np.array([1, "a"]).dtype           # <U21 — satr! (sonlar satrga aylandi — odatda xato belgisi)
np.zeros(3, dtype=np.float32)      # ML'da ko'pincha float32 — xotira 2× kam, GPU uchun standart
a.astype(np.float32)               # tipni o'zgartirish (yangi massiv)

Massiv yaratish#

np.zeros((2, 3))                # nollar
np.ones(3)                      # birlar
np.full((2, 2), 7)              # bir xil qiymat
np.eye(3)                       # birlik matritsa
np.arange(0, 1, 0.25)           # [0.  0.25 0.5  0.75] — range kabi, qadam bilan
np.linspace(0, 1, 5)            # [0.  0.25 0.5  0.75 1.] — 5 ta teng taqsimlangan nuqta (oxiri kiradi)
np.empty((1000, 768))           # ishga tushirilmagan — tez, lekin ichida "axlat"
np.zeros_like(a)                # a bilan bir xil shape va dtype

3. Indekslash va slicing#

1D — ro'yxat kabi. Ko'p o'lchamda — har o'lcham uchun vergul bilan:

m = np.arange(12).reshape(3, 4)
 
m[1]           # [4 5 6 7] — 1-qator
m[1, 2]        # 6 — 1-qator, 2-ustun (m[1][2] ham ishlaydi, lekin sekinroq)
m[:, 1]        # [1 5 9] — 1-ustun (hamma qatorlar)
m[:2, 1:3]     # [[1 2] [5 6]] — qism-matritsa
m[-1]          # oxirgi qator
m[::2]         # har ikkinchi qator

Boolean maskalar — eng kuchli vosita#

x = np.array([3, -1, 4, -1, 5])
 
x > 0                    # [ True False  True False  True] — mask
x[x > 0]                 # [3 4 5] — filtrlash
(x > 0).sum()            # 3 — nechtasi (True = 1)
(x > 0).mean()           # 0.6 — ulushi
x[(x > 0) & (x < 5)]     # [3 4] — & (va), | (yoki), ~ (emas); QAVSLAR SHART
np.where(x > 0, x, 0)    # [3 0 4 0 5] — shartli tanlash (ReLU!)
x[x < 0] = 0             # mask bo'yicha qiymat berish

Fancy indexing — indekslar ro'yxati bilan#

x[[0, 2, 4]]                      # [3 4 5]
labels = np.array([2, 0, 1])
probs = np.array([[0.1, 0.2, 0.7],
                  [0.8, 0.1, 0.1],
                  [0.3, 0.4, 0.3]])
probs[np.arange(3), labels]       # [0.7 0.8 0.4] — har qatordan to'g'ri sinf ehtimoli

Oxirgi qator — cross-entropy loss hisoblashning asosi.

4. View va copy — 2-bobning NumPy versiyasi#

Slicing nusxa yaratmaydi — view qaytaradi: o'sha xotiraga boshqa "oyna". View orqali o'zgartirish asl massivni o'zgartiradi:

m = np.arange(12).reshape(3, 4)
row = m[0]          # view
row[0] = 100
m[0, 0]             # 100 — asl massiv o'zgardi!
 
safe = m[0].copy()  # haqiqiy nusxa
safe[0] = 99
m[0, 0]             # 100 — o'zgarmadi
AmalNatija
Slicing a[1:3], a[:, 0]View
reshape, .T, ravel (odatda)View
Boolean mask a[a > 0]Copy
Fancy indexing a[[0, 2]]Copy
Arifmetika a + 1Yangi massiv
.copy()Copy

Python ro'yxatida lst[1:3] — nusxa; NumPy'da — view. Bu farq ko'p odamni aldaydi. Shubha bo'lsa: np.shares_memory(a, b).

5. Vektorlashgan amallar va ufunc'lar#

Arifmetika har bir element uchun bajariladi:

a = np.array([1.0, 2.0, 3.0])
a + 1, a * 2, a ** 2, 1 / a
np.sqrt(a), np.exp(a), np.log(a), np.abs(a)      # "universal functions" (ufunc)
np.maximum(a, 2)                                  # [2. 2. 3.] — element bo'yicha max
np.clip(a, 1.5, 2.5)                              # [1.5 2.  2.5]

Sof Python sikli yozishdan oldin har doim so'rang: "buni bitta massiv amali bilan qilsa bo'ladimi?" — deyarli har doim bo'ladi.

# ❌ Python sikli
result = np.empty(len(x))
for i in range(len(x)):
    result[i] = max(x[i], 0)
 
# ✅ Vektorlashgan
result = np.maximum(x, 0)

6. Agregatsiya va axis#

m = np.arange(12).reshape(3, 4)
 
m.sum()            # 66 — hammasi
m.sum(axis=0)      # [12 15 18 21] — USTUNLAR bo'yicha (qatorlar "yig'iladi")
m.sum(axis=1)      # [ 6 22 38] — QATORLAR bo'yicha
m.mean(axis=0), m.std(axis=0), m.min(axis=1), m.max()
m.argmax(axis=1)   # har qatordagi maksimum indeksi — sinf bashorati!

axisni eslab qolish usuli: axis=k — k-o'lcham yo'qoladi. Shape (3, 4) massivda sum(axis=0) → shape (4,); sum(axis=1) → (3,).

m: shape (3, 4)
3 ta namuna × 4 ta xususiyat
m.mean(axis=0) → shape (4,)
har xususiyatning o'rtachasi (normalizatsiya uchun)
m.mean(axis=1) → shape (3,)
har namunaning o'rtachasi
axis=0 — pastga qarab (har ustun bitta songa), axis=1 — o'ngga qarab (har qator bitta songa)

keepdims=True — yo'qolgan o'lchamni 1 sifatida saqlaydi, broadcasting uchun qulay: m.sum(axis=1, keepdims=True) → shape (3, 1).

NaN bilan: np.mean([1, np.nan, 3]) → nan; np.nanmean(...) → 2.0.

7. Broadcasting#

Turli shape'li massivlar o'rtasida amal qanday bajariladi?

A = np.arange(6).reshape(2, 3)      # (2, 3)
b = np.array([10, 20, 30])          # (3,)
A + b
# [[10 21 32]
#  [13 24 35]]   — b har bir qatorga qo'shildi

Qoida: shape'lar o'ngdan solishtiriladi; har bir o'lcham juftligi yo teng, yo ulardan biri 1 bo'lishi kerak (yoki o'lcham yo'q). 1 bo'lgan o'lcham boshqasiga "cho'ziladi" (xotirada nusxalanmasdan).

A shapeB shapeNatijaIzoh
(2, 3)(3,)(2, 3)B har qatorga
(2, 3)(2, 1)(2, 3)B har ustunga
(n, d)(d,)(n, d)Har namunadan o'rtachani ayirish
(n, 1)(1, m)(n, m)"Tashqi" amal — hamma juftliklar
(2, 3)(2,)❌3 ≠ 2 — xato
A + np.array([1, 2])
# ValueError: operands could not be broadcast together with shapes (2,3) (2,)
A + np.array([[1], [2]])            # ✅ (2, 1) — har qatorga o'z soni

Amaliy misol: standartlashtirish (z-score)#

rng = np.random.default_rng(42)
X = rng.normal(loc=5, scale=2, size=(1000, 3))     # 1000 namuna, 3 xususiyat
 
mu = X.mean(axis=0)            # (3,)
sigma = X.std(axis=0)          # (3,)
Z = (X - mu) / sigma           # (1000, 3) - (3,) → broadcasting
 
Z.mean(axis=0).round(6)        # [0. 0. 0.]
Z.std(axis=0)                  # [1. 1. 1.]

Bitta qator — sikllarsiz. scikit-learn'ning StandardScaleri ichkarida aynan shuni qiladi.

8. Shape'ni o'zgartirish#

img = np.zeros((32, 32, 3))
 
img.reshape(-1).shape              # (3072,) — -1: "qolganini o'zing hisobla"
img.reshape(32 * 32, 3).shape      # (1024, 3) — piksellar ro'yxati
img[None].shape                    # (1, 32, 32, 3) — yangi o'lcham (batch)
np.expand_dims(img, 0).shape       # xuddi shu
img.transpose(2, 0, 1).shape       # (3, 32, 32) — HWC → CHW (PyTorch formati)
np.squeeze(np.zeros((1, 5, 1))).shape   # (5,) — 1 o'lchamlarni olib tashlash
 
np.concatenate([a, b], axis=0)     # mavjud o'q bo'yicha ulash
np.stack([a, b], axis=0)           # YANGI o'q yaratib ulash
np.vstack, np.hstack               # qulay qisqartmalar

9. Chiziqli algebra#

X = np.array([[1.0, 2.0], [3.0, 4.0]])
W = np.array([[1.0, 0.0], [0.0, 2.0]])
 
X @ W               # matritsa ko'paytmasi → [[1. 4.] [3. 8.]]
X * W               # ELEMENT bo'yicha ko'paytma → [[1. 0.] [0. 8.]] — boshqa narsa!
np.dot([1, 2], [3, 4])         # 11 — skalyar ko'paytma
np.linalg.norm([3, 4])         # 5.0 — vektor uzunligi
np.linalg.inv(X)               # teskari matritsa
np.linalg.solve(X, [1, 2])     # X @ x = b tenglamasini yechish (inv'dan barqarorroq)

Neyron tarmoq qatlami — aynan shu: y = X @ W + b. Shape'lar: (batch, in) @ (in, out) + (out,) → (batch, out).

10. Tasodifiy sonlar#

rng = np.random.default_rng(42)       # ✅ zamonaviy API: alohida generator, seed bilan
 
rng.random(3)                  # [0, 1) oralig'ida
rng.integers(0, 10, size=5)    # butun sonlar [0, 10)
rng.normal(0, 1, size=(2, 3))  # normal taqsimot
rng.choice(100, size=5, replace=False)
rng.permutation(5)             # [0 1 4 2 3] — aralashtirilgan indekslar
rng.shuffle(arr)               # joyida

Eski kodlarda np.random.seed(42) va np.random.rand(...) ko'rasiz — bu global holat (18-bobdagi random.seed muammosi). Yangi kodda default_rng ishlating.

Train/test bo'linishi indekslar orqali:

idx = rng.permutation(len(X))
split = int(0.8 * len(X))
X_train, X_test = X[idx[:split]], X[idx[split:]]
y_train, y_test = y[idx[:split]], y[idx[split:]]      # X va y bir xil indekslar bilan!

11. Raqamli barqarorlik#

ML'da ko'p uchraydigan ikki muammo:

np.exp(1000.0)        # inf — overflow (RuntimeWarning bilan)

Softmaxni to'g'ridan-to'g'ri yozish xavfli. Barqaror versiya — maksimumni ayirish (matematik jihatdan natija o'zgarmaydi):

def softmax(logits: np.ndarray, axis: int = -1) -> np.ndarray:
    z = logits - logits.max(axis=axis, keepdims=True)
    e = np.exp(z)
    return e / e.sum(axis=axis, keepdims=True)
 
 
softmax(np.array([2.0, 1.0, 0.1]))      # [0.659 0.242 0.099]
softmax(np.array([1000.0, 1001.0]))     # [0.269 0.731] — inf yo'q

log(0) → -inf muammosi uchun: np.log(p + 1e-12) yoki np.log1p, np.clip(p, 1e-12, 1).

12. Amaliyot: embedding'lar bilan semantik qidiruv#

RAG tizimlarining yuragi — eng o'xshash hujjatlarni topish. Embedding'lar (matnlarning vektor ko'rinishi) tayyor deb hisoblaymiz:

import numpy as np
 
rng = np.random.default_rng(0)
doc_embeddings = rng.normal(size=(10_000, 768)).astype(np.float32)   # 10k hujjat
query = rng.normal(size=768).astype(np.float32)
 
 
def normalize(x: np.ndarray) -> np.ndarray:
    return x / np.linalg.norm(x, axis=-1, keepdims=True)
 
 
def top_k(query: np.ndarray, docs: np.ndarray, k: int = 5) -> tuple[np.ndarray, np.ndarray]:
    """Kosinus o'xshashlik bo'yicha eng yaqin k ta hujjat."""
    sims = normalize(docs) @ normalize(query)          # (10000, 768) @ (768,) → (10000,)
    idx = np.argpartition(-sims, k)[:k]                # O(n) — to'liq saralashdan tez
    idx = idx[np.argsort(-sims[idx])]                  # faqat k tasini saralash
    return idx, sims[idx]
 
 
idx, scores = top_k(query, doc_embeddings, k=5)
print(idx, scores.round(3))

Bu kod 10 000 hujjat ichidan millisekundlarda qidiradi. Hisob: normalizatsiya (broadcasting + axis), matritsa-vektor ko'paytmasi (@), argpartition bilan top-k. Vektor ma'lumotlar bazalari (FAISS, pgvector, Qdrant) aynan shu g'oyani millionlab vektorlar uchun indekslar bilan tezlashtiradi.

13. NumPy va boshqa kutubxonalar#

arr.tolist()                     # → Python ro'yxati (JSON uchun)
float(np.float64(1.5))           # → Python float (yoki .item())
np.save("emb.npy", arr); np.load("emb.npy")       # tez binar saqlash
 
# PyTorch bilan (xotira umumiy bo'lishi mumkin!):
# t = torch.from_numpy(arr)      arr = t.numpy()
# Pandas: df.to_numpy(), pd.DataFrame(arr, columns=[...])

Nima noto'g'ri ketishi mumkin#

XatoBelgisiTuzatish
Python sikli massiv ustidaSekinlikVektorlashgan amal
Slice'ni nusxa deb o'ylashAsl ma'lumot o'zgardi.copy()
and/or massivlar bilantruth value ... is ambiguous&, |, ~ va qavslar
* matritsa ko'paytmasi debNoto'g'ri natija, shape to'g'ri ko'rinishi mumkin@
Shape mos emasoperands could not be broadcastprint(a.shape, b.shape), reshape/None
Kutilmagan broadcasting (n,) va (n, 1)(n, n) massiv — jim xato!Shape'larni tekshiring, assert
uint8/int8 to'lib ketishiG'alati qiymatlarastype(np.float32)
np.exp katta soninf, nanMaksimumni ayirish (softmax)
np.mean NaN bilannannp.nanmean yoki tozalash
np.random.seed globalTakrorlanmaydigan natijanp.random.default_rng(seed)
json.dumps(np.float32(...))not JSON serializable.item() / .tolist()
Amaliy topshiriq

1. Vektorlashtiring

Ikki nuqtalar to'plami A (n×2) va B (m×2) orasidagi barcha juftlik masofalari matritsasini (n×m) avval ikki ichma-ich Python sikli bilan, keyin sikllarsiz broadcasting bilan hisoblang. n = m = 1000 uchun vaqtni solishtiring va natijalar bir xil ekanini np.allclose bilan tekshiring.

Maslahatni ko'rsatish

Masofalar: np.sqrt(((A[:, None, :] - B[None, :, :]) ** 2).sum(-1)) — broadcasting bilan (n, 1, d) - (1, m, d) → (n, m, d).

Amaliy topshiriq

2. Metrikalar

y_true va y_pred (0/1 massivlar) berilgan. Sikllarsiz accuracy, precision, recall, F1 hisoblang. Keyin ko'p sinfli holat uchun confusion matrix yasang (np.add.at yoki np.bincount bilan). Natijani 22-bobda scikit-learn bilan solishtiramiz.

Maslahatni ko'rsatish

TP = ((pred == 1) & (y == 1)).sum(); precision = TP / (TP + FP); confusion: np.zeros((k, k), int); np.add.at(cm, (y, pred), 1).

Amaliy topshiriq

3. Mini chiziqli regressiya

rng bilan sun'iy ma'lumot yarating: y = 3*x1 - 2*x2 + 1 + shovqin. Faqat NumPy bilan gradient descent orqali w va bni toping (MSE loss). Natijani np.linalg.lstsq yechimi bilan solishtiring. Bu — neyron tarmoqlar o'qitishning eng sodda shakli.

Maslahatni ko'rsatish

Gradient: grad_w = 2/n * X.T @ (X @ w + b - y); grad_b = 2/n * (X @ w + b - y).sum(). 500 qadam, lr=0.1.

Amaliy topshiriq

4. Rasm bilan ishlash

(64, 64, 3) uint8 tasodifiy "rasm" yarating. (a) kulrangga aylantiring (0.299 R + 0.587 G + 0.114 B), (b) [0, 1] ga normalizatsiya qiling, (c) gorizontal aks ettiring ([:, ::-1]), (d) markazdan 32×32 kesing, (e) 8 ta shunday rasmni (8, 3, 64, 64) PyTorch batch formatiga keltiring. Har qadamda shape va dtype'ni chiqaring.

Yodda saqlang
  • 01ndarray — bir xil tipdagi sonlarning uzluksiz bloki; vektorlashtirish sof Python'dan 20–100× tez.
  • 02shape — eng muhim tushuncha; dtype — ML'da ko'pincha float32; int'lar to'lib ketishi mumkin.
  • 03Boolean mask: x[x > 0], &, |, ~ va qavslar; np.where — shartli tanlash.
  • 04Slicing — view (asl ma'lumotni o'zgartiradi); mask va fancy indexing — copy.
  • 05axis=k — k-o'lcham yo'qoladi; keepdims=True broadcasting uchun.
  • 06Broadcasting: shape'lar o'ngdan solishtiriladi, teng yoki 1 bo'lishi kerak; (n,) va (n,1) dan ehtiyot bo'ling.
  • 07@ — matritsa ko'paytmasi, * — element bo'yicha.
  • 08default_rng(seed) — takrorlanuvchanlik; softmax'da maksimumni ayiring.

Mustahkamlash

Test va amaliy masalalar

Avval testni ishlang — har javobdan keyin izoh chiqadi. Keyin masalalarni shu yerning o'zida yechib, brauzerdagi haqiqiy Python bilan avtomatik tekshiring. Natijalaringiz kurs progressi sahifasida jamlanadi.

Test: topshirilmaganMasalalar: 0/3

Bilimni tekshirish

Bob bo'yicha test

12 ta savol · har javobdan keyin to'g'ri yoki xatoligi va izoh ko'rsatiladi · oxirida natija foizda.

Amaliy masalalar

Kodni yozing va «Tekshirish»ni bosing (yoki Ctrl/⌘ + Enter). Kodingiz shu brauzerda saqlanib turadi.

01Z-score standartlashtirish

standardize(X) — 2D massivning har ustunini o'rtacha 0, std 1 ga keltirsin (sikllarsiz, broadcasting). Std 0 bo'lgan ustunlar 0 bo'lsin (nolga bo'lish yo'q).

02Kosinus top-k qidiruv

top_k(query, docs, k) — docs (n×d) qatorlari orasidan query (d,) ga kosinus o'xshashligi eng yuqori k ta indeksni (kamayish tartibida) va o'xshashliklarni qaytarsin: (idx, sims). Sikl ishlatmang.

03Metrikalar sikllarsiz

metrics(y_true, y_pred) — 0/1 massivlar uchun {"accuracy", "precision", "recall", "f1"} lug'atini qaytarsin (NumPy, sikllarsiz). Nolga bo'linish holatida 0.0.