Ana içeriğe geç

Orta13 dk

Broadcasting

Önkoşul:NumPy: dizi düşüncesi

Kanca

5 bölge × 4 ürün kategorisi için bir fiyat matrisin var — şekli (5, 4). Her kategoriye ayrı bir kargo eklentisi eklemek istiyorsun — bu sadece 4 elemanlık bir liste, şekli (4,). Şekilleri bile uyuşmayan bu iki diziyi fiyat_matrisi + kategori_kargo yazarak nasıl topluyorsun, ve NumPy bunu nasıl anlıyor?

Sezgi

Broadcasting, NumPy’ın “şekilleri farklı iki diziyi, biri küçüğü büyüğe göre görünmez yere genişleterek” toplamasına izin veren kuraldır. NumPy, iki dizinin şekillerini SAĞDAN başlayarak karşılaştırır; her boyut çifti ya birbirine eşit olmalı ya da biri 1 olmalı — o zaman 1 olan taraf, diğerinin boyutuna “genişler”.

Dizi A — (3, 4)

Dizi B — (4,)

A (3, 4)

B (4,)

Sonuç (3, 4)

  • Dizi A
  • Dizi B
  • Sonuç

Uyumlu — A (3, 4) ve B (4,), sağdan hizalanınca (3, 4) şeklinde bir sonuç üretir.

Örnekleri dene: “Satır vektörü ile” örneğinde (5,4) + (4,) uyumlu çünkü sağdan hizalanınca ikinci boyutlar (4 ve 4) eşit. “Uyumsuz (hata)” örneğinde ise son boyutlar (4 ve 3) ne eşit ne de biri 1 — NumPy burada hata verir.

Mekanizma

Somut sayılarla ilerleyelim. 5 bölge × 4 kategorilik bir fiyat matrisi ve 4 elemanlık bir kargo vektörü:

Matris + vektör

# 5 bölge × 4 ürün kategorisi için taban fiyat matrisi (satır=bölge, sütun=kategori).
fiyat_matrisi = rng.integers(50, 200, size=(5, 4)).astype(float)
print("Fiyat matrisi şekli:", fiyat_matrisi.shape)
print(fiyat_matrisi)

# Her kategoriye ayrı bir kargo eklentisi uygulamak istiyoruz — TEK BOYUTLU bir dizi.
kategori_kargo = np.array([10, 25, 5, 15])
print("\nKargo eklentisi şekli:", kategori_kargo.shape)

# Broadcasting: (5,4) + (4,) döngü YAZMADAN her satıra aynı 4 elemanlı vektörü ekliyor.
toplam_fiyat = fiyat_matrisi + kategori_kargo
print("\nToplam fiyat (broadcasting ile):")
print(toplam_fiyat)
Fiyat matrisi şekli: (5, 4)
[[ 63. 166. 148. 115.]
 [114. 178.  62. 154.]
 [ 80.  64. 128. 196.]
 [160. 164. 157. 167.]
 [126.  69. 175. 117.]]

Kargo eklentisi şekli: (4,)

Toplam fiyat (broadcasting ile):
[[ 73. 191. 153. 130.]
 [124. 203.  67. 169.]
 [ 90.  89. 133. 211.]
 [170. 189. 162. 182.]
 [136.  94. 180. 132.]]

Tek satırda, döngü yazmadan, kargo eklentisi her satıra (her bölgeye) uygulandı. Bunun NEDEN çalıştığını adım adım görelim:

Hizalama adım adım

# NumPy şekilleri SAĞDAN hizalar. (4,) diziye önce hayali bir 1 eklenir: (1, 4).
# Sonra her boyut karşılaştırılır: eşit VEYA biri 1 olmalı.
print("Hizalama:")
print(f"  fiyat_matrisi.shape = {fiyat_matrisi.shape}")
print(f"  kategori_kargo.shape = {kategori_kargo.shape}  →  (1, 4) olarak hizalanır")
print(f"  Karşılaştırma: boyut 0: 5 vs 1 (1 olduğu için genişler) ✓")
print(f"                 boyut 1: 4 vs 4 (eşit) ✓")
print(f"  Sonuç şekli: {toplam_fiyat.shape}")

# Elle döngüyle yapsaydık aynı sonucu bulurduk — ama 5 satır için 5 ayrı toplama gerekirdi.
elle = np.array([fiyat_matrisi[i] + kategori_kargo for i in range(5)])
print(f"\nElle döngü ile aynı mı? {np.allclose(elle, toplam_fiyat)}")
Hizalama:
  fiyat_matrisi.shape = (5, 4)
  kategori_kargo.shape = (4,)  →  (1, 4) olarak hizalanır
  Karşılaştırma: boyut 0: 5 vs 1 (1 olduğu için genişler) ✓
                 boyut 1: 4 vs 4 (eşit) ✓
  Sonuç şekli: (5, 4)

Elle döngü ile aynı mı? True

(4,) şekli, sağdan hizalanırken önce hayali bir (1, 4)’e dönüştürülür. Sonra boyut boyut karşılaştırılır: birinci boyutta 5 ile 1 — 1 olan taraf genişler; ikinci boyutta 4 ile 4 — zaten eşit. Elle yazdığımız döngüyle karşılaştırınca sonuç birebir aynı çıkıyor — broadcasting sadece bu döngüyü senin yerine, çok daha hızlı yapıyor.

Çoğu kişi “broadcasting her zaman çalışır, NumPy şekilleri otomatik uydurur” sanır. Değil, çünkü kural nettir: boyutlar eşit olmalı VEYA biri 1 olmalı — bu ikisi de sağlanmazsa NumPy hata verir, sessizce yanlış bir sonuç üretmez.

Matematik

Broadcasting kuralı
A:(d1,d2,,dn)A: (d_1, d_2, \ldots, d_n)B:(e1,e2,,em)B: (e_1, e_2, \ldots, e_m)sag˘dan hizala, her c¸ift ic¸in: di=ei veya di=1 veya ei=1\text{sağdan hizala, her çift için: } d_i = e_i \text{ veya } d_i=1 \text{ veya } e_i=1
AdımNe yapılır
1. HizalaKısa olan şeklin BAŞINA (sola) yeterince 1 eklenir, iki şekil de aynı uzunlukta olur
2. KarşılaştırSağdan sola, her boyut çifti kontrol edilir
3. GenişletBoyutlardan biri 1 ise, o taraf diğerinin boyutuna “kopyalanmış gibi” genişler (gerçekte bellekte kopyalanmaz)
4. UyumsuzsaHiçbir boyut çifti kuralı sağlamıyorsa ValueError fırlatılır

“Genişleme” bellekte gerçek bir kopyalama yapmaz — NumPy sadece aynı değeri tekrar tekrar okur gibi davranır. Bu yüzden broadcasting hem hızlı hem bellek dostudur.

Kod

Şimdi uyumsuz bir şekil deneyelim ve hatayı görüp düzeltelim:

Hata ve düzeltme

# Şimdi UYUMSUZ bir şekil deneyelim: her bölge için TEK bir sayı (5,) eklemeye çalışalım.
bolge_indirimi = np.array([5, 10, 0, 20, 15])  # 5 elemanlı — bölge sayısı kadar

try:
    hatali_sonuc = fiyat_matrisi + bolge_indirimi
except ValueError as hata:
    print(f"HATA: {hata}")
    print("Sebep: (5,4) ve (5,) sağdan hizalanınca son boyutlar 4 ve 5 — ikisi de 1 değil, eşit de değil.")

# Çözüm: bolge_indirimi'ni (5, 1) şekline getirip her SATIRA uygulanmasını sağlamak.
bolge_indirimi_dikey = bolge_indirimi.reshape(5, 1)
duzeltilmis_sonuc = fiyat_matrisi + bolge_indirimi_dikey
print(f"\nreshape(5,1) sonrası şekil: {bolge_indirimi_dikey.shape} — şimdi (5,4) ile uyumlu")
print(duzeltilmis_sonuc)
HATA: operands could not be broadcast together with shapes (5,4) (5,) 
Sebep: (5,4) ve (5,) sağdan hizalanınca son boyutlar 4 ve 5 — ikisi de 1 değil, eşit de değil.

reshape(5,1) sonrası şekil: (5, 1) — şimdi (5,4) ile uyumlu
[[ 68. 171. 153. 120.]
 [124. 188.  72. 164.]
 [ 80.  64. 128. 196.]
 [180. 184. 177. 187.]
 [141.  84. 190. 132.]]

(5,4) ve (5,) sağdan hizalanınca son boyutlar 4 ve 5 — uyuşmuyor, NumPy ValueError fırlatıyor. Çözüm: reshape(5,1) ile diziyi “dikey” hâle getirmek — artık (5,1), (5,4) ile sağdan hizalanınca ikinci boyutta 1 var, genişleyebiliyor.

Solda taban fiyat matrisinin ısı haritası, sağda kategori kargosu eklendikten sonraki hâli — sağdaki genel olarak daha koyu (daha yüksek fiyat).
Broadcasting, 4 elemanlık bir vektörü matrisin her satırına döngüsüz uyguladı.

Nerede işe yarar

Broadcasting, veri biliminde her yerde karşına çıkar:

  • Normalizasyon. Bir matrisin her sütunundan o sütunun ortalamasını çıkarmak (matris - matris.mean(axis=0)), 15. derste göreceğimiz ölçekleme işleminin temelidir.
  • Toplu düzeltme. Bir görüntü matrisinin her pikseline aynı parlaklık değerini eklemek.
  • Görüntü işleme ve derin öğrenme. Bir “batch” görüntüye aynı filtreyi uygulamak, PyTorch/TensorFlow’da broadcasting üzerine kuruludur.

Bu 3 hatayı yaparsın:

  1. Şekilleri kontrol etmeden toplama/çarpma yapıp beklenmedik bir ValueError almak.
  2. reshape ile boyutu doğru yöne çevirmeyi unutmak — (5,) ile (5,1) görünüşte benzer ama broadcasting’de çok farklı davranır.
  3. Broadcasting’in bellekte gerçek bir kopyalama yaptığını sanmak — aslında sadece “sanal” bir genişlemedir, ekstra bellek harcamaz.

Kendini test et

1. (5, 4) şeklinde bir matrise (4,) şeklinde bir dizi eklemek neden çalışır?
  1. Çalışmaz, hata verir
  2. (4,) önce (1,4)'e hizalanır, birinci boyutta 5 vs 1 olduğu için 1 olan taraf genişler (doğru cevap)
  3. NumPy şekilleri rastgele eşler
  4. Sadece kare matrislerde çalışır

Neden: Broadcasting kuralı sağdan hizalamayla başlar; (4,) diziye hayali bir 1 eklenerek (1,4) yapılır, sonra 5 vs 1 karşılaştırmasında 1 olan taraf genişler.

2. (5, 4) ile (5,) şekilleri neden uyumsuzdur?
  1. Toplam eleman sayıları farklı olduğu için
  2. Sağdan hizalanınca son boyutlar 4 ve 5 — ne eşit ne de biri 1 (doğru cevap)
  3. NumPy 1 boyutlu dizilerle çalışmaz
  4. Aslında uyumludur

Neden: (5,) şekli sağdan hizalanınca doğrudan son boyut olarak 5 ile karşılaştırılır; matrisin son boyutu 4. 4≠5 ve ikisi de 1 olmadığı için kural sağlanmaz.

3. `reshape(5,1)` ile bir (5,) diziyi dönüştürmek neden (5,4) bir matrisle uyumlu hâle getirir?
  1. reshape her zaman uyumluluk sağlar
  2. (5,1) şekli, ikinci boyutta 1 taşıdığı için sağdan hizalamada genişleyebilir (doğru cevap)
  3. reshape diziyi küçültür
  4. Hiçbir farkı yoktur

Neden: (5,1) ile (5,4) sağdan hizalanınca: ikinci boyut 1 vs 4 (1 olan genişler), birinci boyut 5 vs 5 (eşit) — ikisi de kuralı sağlar.

Özet

Özet

  • Broadcasting, farklı şekilli dizileri döngüsüz toplamayı/çarpmayı sağlayan bir NumPy kuralıdır.
  • Şekiller SAĞDAN hizalanır; her boyut çifti eşit olmalı veya biri 1 olmalı.
  • Kural sağlanmazsa NumPy ValueError fırlatır — sessizce yanlış sonuç üretmez.
  • reshape, bir dizinin boyutlarını broadcasting kurallarına uyacak şekilde yeniden düzenlemenin standart yoludur.
  • Broadcasting bellekte gerçek kopyalama yapmaz — hızlı ve bellek dostudur.
Sonraki adım: Vektörleştirme: döngüyü bırakmak →