Asosiy qismga o'tish

Shaklni o'zgartirish va matritsa ko'paytirish

6-bob 9 kod bloki 1573 so'z

Sahna: bir xil sonlar, boshqa savol

12 oylik savdo bitta qatorda keldi: 12 ta son. Rahbar esa choraklar bo'yicha jadval so'raydi — 4 chorak, har birida 3 oy. Sonlar o'sha-o'sha, faqat shakli boshqa. Bu bobda shakl bilan ishlashni, keyin esa ML ning eng muhim amalini — matritsa ko'paytirishni o'rganamiz.

reshape: o'sha sonlar, yangi shakl

python7 qator
import numpy as np

oylar = np.array([42, 38, 51, 47, 55, 60, 58, 62, 49, 53, 66, 71])
chorak = oylar.reshape(4, 3)
print(chorak)
print("chorak yig'indisi:", chorak.sum(axis=1))
print(oylar.reshape(2, -1).shape, oylar.reshape(-1, 1).shape)
Chiqish
[[42 38 51]
 [47 55 60]
 [58 62 49]
 [53 66 71]]
chorak yig'indisi: [131 162 169 190]
(2, 6) (12, 1)

reshape(4, 3) — 12 ta sonni 4 qator, 3 ustunga qator bo'yicha joylaydi: birinchi uchta son — birinchi qator. Shart bitta: elementlar soni o'zgarmasligi kerak (4 × 3 = 12).

-1 — "buni o'zing hisobla": reshape(2, -1) — 2 qator, ustunlar 12 / 2 = 6. reshape(-1, 1) — bitta ustunli jadval: scikit-learn bitta xususiyatni aynan shu (n, 1) shaklda kutadi.

python4 qator
try:
    oylar.reshape(5, -1)
except ValueError as xato:
    print("ValueError:", xato)
Chiqish
ValueError: cannot reshape array of size 12 into shape (5,newaxis)

12 ni 5 ga bo'lib bo'lmaydi — NumPy taxmin qilmaydi, xato beradi.

ravel va flatten: yana bitta qatorga

python5 qator
yassi = chorak.ravel()
nusxa = chorak.flatten()
print(yassi)
print("ravel xotirasi umumiy:", np.shares_memory(chorak, yassi))
print("flatten xotirasi umumiy:", np.shares_memory(chorak, nusxa))
Chiqish
[42 38 51 47 55 60 58 62 49 53 66 71]
ravel xotirasi umumiy: True
flatten xotirasi umumiy: False

Ikkalasi bir xil natija beradi, farqi 3-bobdagi view/copy da: ravel iloji bo'lsa view (tez, xotira sarflamaydi), flatten har doim copy (xavfsiz). O'zgartirmoqchi bo'lmasangiz — ravel.

Transpose: qator va ustunni almashtirish

python2 qator
print(chorak.T)
print(chorak.shape, "->", chorak.T.shape)
Chiqish
[[42 47 58 53]
 [38 55 62 66]
 [51 60 49 71]]
(4, 3) -> (3, 4)

.T qatorlarni ustunga aylantiradi: endi har ustun — bitta chorak. Bu ham view: hech narsa ko'chirilmaydi, NumPy faqat "qanday o'qish" tartibini almashtiradi.

Yangi o'q qo'shish: None va expand_dims

4-bobdagi (n,) va (n, 1) farqini eslang. Ba'zan aynan 1 o'lchamli o'qni qo'shish kerak bo'ladi:

python2 qator
narx = np.array([5_000, 12_000, 18_000])
print(narx.shape, narx[:, None].shape, narx[None, :].shape, np.expand_dims(narx, 0).shape)
Chiqish
(3,) (3, 1) (1, 3) (1, 3)

narx[:, None] — ustunga aylantiradi (3, 1); narx[None, :] — bitta qatorli jadval (1, 3). Broadcasting da qaysi tomonga "cho'zilishini" shu bilan boshqarasiz.

Birlashtirish: concatenate va stack

vstack ostiga, hstack yoniga qo'shadi; stack yangi o'q ochadi

vstack ostiga, hstack yoniga qo'shadi; stack yangi o'q ochadi

python6 qator
yanvar = np.array([[12, 15], [9, 11]])
fevral = np.array([[14, 13], [10, 16]])
print(np.vstack([yanvar, fevral]).shape)
print(np.hstack([yanvar, fevral]).shape)
print(np.stack([yanvar, fevral]).shape)
print(np.concatenate([yanvar, fevral], axis=1).shape)
Chiqish
(4, 2)
(2, 4)
(2, 2, 2)
(2, 4)
  • vstack — ostiga (qatorlar ko'payadi): yangi filiallar qo'shildi.
  • hstack — yoniga (ustunlar ko'payadi): yangi oy qo'shildi.
  • stack — yangi o'q: ikki jadval alohida "varaq" bo'lib qoladi, (2, 2, 2). Keyin [0] — yanvar, [1] — fevral.
  • concatenate(..., axis=...) — umumiy usul: axis=0 — vstack, axis=1 — hstack.

Matritsa ko'paytirish: bitta amalda butun tushum

Endi asosiy masala. 7 kun davomida 3 mahsulotdan necha dona sotilgani — jadval. Har mahsulotning narxi — ro'yxat. Har kunning tushumi qancha?

Matritsa ko'paytirish: (7, 3) @ (3,) → (7,), ichki o'lchamlar teng

Matritsa ko'paytirish: (7, 3) @ (3,) → (7,), ichki o'lchamlar teng

python10 qator
rng = np.random.default_rng(11)
miqdor = rng.integers(20, 120, size=(7, 3))
narx = np.array([5_000, 12_000, 18_000])

sikl_bilan = [sum(miqdor[k, m] * narx[m] for m in range(3)) for k in range(7)]
matritsa_bilan = miqdor @ narx
print(miqdor[0], "dona ×", narx, "so'm")
print("1-kun:", miqdor[0, 0], "*", narx[0], "+", miqdor[0, 1], "*", narx[1], "+", miqdor[0, 2], "*", narx[2], "=", matritsa_bilan[0])
print("bir xilmi:", np.array_equal(sikl_bilan, matritsa_bilan))
print(miqdor.shape, "@", narx.shape, "->", matritsa_bilan.shape)
Chiqish
[33 32 99] dona × [ 5000 12000 18000] so'm
1-kun: 33 * 5000 + 32 * 12000 + 99 * 18000 = 2331000
bir xilmi: True
(7, 3) @ (3,) -> (7,)

@ har kun (qator) uchun juftma-juft ko'paytirib, yig'adi: dona × narx, uchala mahsulot bo'yicha jami. Ichma-ich sikl bilan hisoblaganimiz bilan bir xil chiqdi — @ shuni bitta amalda qiladi.

Shakl qoidasi: (n, m) @ (m, k) → (n, k). Ichki o'lchamlar (bu yerda 3 va 3) teng bo'lishi shart — har mahsulotga bitta narx. Tashqi o'lchamlar natijaga qoladi.

Ikkita narx ro'yxati bo'lsa-chi — chakana va ulgurji? Narxni (3, 2) jadval qilamiz:

python16 qator
narxlar = np.array([[5_000, 4_200],
                    [12_000, 10_500],
                    [18_000, 16_000]])
tushum = miqdor @ narxlar
print(miqdor.shape, "@", narxlar.shape, "->", tushum.shape)
print((tushum / 1e6).round(2))

kunlar = np.array(["Du", "Se", "Ch", "Pa", "Ju", "Sh", "Ya"])
fig, ax = plt.subplots(figsize=(8, 3.2))
x = np.arange(7)
ax.bar(x - 0.2, tushum[:, 0] / 1e6, width=0.4, label="chakana narxda", color="#1a73e8")
ax.bar(x + 0.2, tushum[:, 1] / 1e6, width=0.4, label="ulgurji narxda", color="#b06000")
ax.set_xticks(x, kunlar)
ax.set_ylabel("mln so'm")
ax.legend()
plt.show()
Chiqish
(7, 3) @ (3, 2) -> (7, 2)
[[2.33 2.06]
 [2.73 2.4 ]
 [1.94 1.7 ]
 [2.91 2.56]
 [2.03 1.78]
 [3.35 2.96]
 [3.48 3.05]]

(7, 3) @ (3, 2) → (7, 2): har kun uchun ikki tushum — bitta amal, sikl yo'q.

* va @ — eng ko'p chalkashadigan juftlik

python4 qator
a = np.array([[1, 2], [3, 4]])
b = np.array([[10, 20], [30, 40]])
print("a * b — element-ma-element:\n", a * b)
print("a @ b — matritsa ko'paytirish:\n", a @ b)
Chiqish
a * b — element-ma-element:
 [[ 10  40]
 [ 90 160]]
a @ b — matritsa ko'paytirish:
 [[ 70 100]
 [150 220]]

* — har katak o'z jufti bilan (4-bob). @ — qator × ustun, yig'indi bilan. np.dot(a, b) ham 2D da @ bilan bir xil; yangi kodda @ o'qilishi osonroq. ML kitobidagi har bir chiziqli model X @ w + b — aynan shu amal.

Xulosa

  • reshape sonlarni yangi shaklga qatorma-qator joylaydi; -1 — o'lchamni o'zi hisoblaydi; elementlar soni mos bo'lishi shart.
  • ravel — iloji bo'lsa view, flatten — har doim copy.
  • .T — qator va ustunni almashtiradi (view).
  • [:, None] / [None, :] — 1 o'lchamli yangi o'q: broadcasting ni boshqarish.
  • vstack — ostiga, hstack — yoniga, stack — yangi o'q; concatenate(axis=...) — umumiy.
  • @: (n, m) @ (m, k) → (n, k), ichki o'lchamlar teng; * esa element-ma-element.

Mashqlar

  1. np.arange(24) ni (2, 3, 4) shaklga keltiring. [1, 2] nimani qaytaradi?
  2. miqdor jadvalining har mahsulot bo'yicha haftalik sonini @ bilan toping (maslahat: birlardan iborat vektor).
  3. (5, 2) @ (3, 2) ishlaydimi? Ishlamasa, qanday tuzatasiz?
  4. chorak.T.ravel() va chorak.ravel() natijasini solishtiring. Nega har xil?

Javoblar

  1. [20 21 22 23] — 1-varaq, 2-qator.
  2. np.ones(7) @ miqdor yoki miqdor.T @ np.ones(7) — har ustun yig'indisi (miqdor.sum(axis=0) bilan bir xil).
  3. Yo'q: ichki o'lchamlar 2 va 3. Ikkinchisini burish kerak: (5, 2) @ (3, 2).T → (5, 3).
  4. chorak.ravel() — oylar asl tartibda; chorak.T.ravel() — avval har chorakning 1-oyi, keyin 2-oyi: .T o'qish tartibini o'zgartirgan.

Bu bobni bepul o'qidingiz.

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

Telegramda yozish Narxlar