Döngüyü vektörleştir
Zorluk: Kolay Çözüldünumpy
Bir dizideki (array) sayıların karelerini toplayan sum_of_squares(x) fonksiyonunu, döngü kullanmadan yaz. Bu hesabı bir for döngüsüyle kolayca yazabilirsin.
Bu problemde vektörleştirmeyi (vectorization) kullanırsın: hesabı array’e bir seferde uygulanan NumPy işlemleriyle yazarsın.
x, şekli (shape) (n,) olan bir array’dir. Hesap iki adımdır:
- Her elemanın karesini al.
- Kareleri topla.
Formülü şudur:
Örneğin için olur. Eksi işaret karede kaybolur. Tek bir Python float döndür.
Örnekler
Girdi: x = [1.0, 2.0, 3.0, 4.0]
Çıktı: 30.0
Girdi: x = []
Çıktı: 0.0
Girdi: x = [-3.0, 0.5, -1.5, 2.0, -0.25]
Çıktı: 15.5625
İpucu 1
x ** 2, her elemanın karesini içeren yeni bir array verir. NumPy array’lerinde ** gibi işlemler eleman bazında (element-wise) çalışır. Elemanlar üzerinde dolaşmana gerek yok.
İpucu 2
np.sum, karelerin array’ini tek bir sayıya indirir. Sırayı karıştırma: önce kareler, sonra toplam.
İpucu 3
Döndürmeden önce sonucu float(...) ile sade bir Python float’una çevirebilirsin. Kareleri np.sum ile topla ve sonucu çevir.
Gereksinimler
x,(n,)shape’inde, float’lardan oluşan bir array’dir. Boş olabilir (n = 0); boş array’de sonuç0.0’dır.- Dönüş değeri tek bir
float: array ya da liste değil.np.sum’ın verdiğinp.float64de kabul edilir.float(...)ile çevirmek zorunda değilsin. - Önce kareyi al, sonra topla. Toplamın karesi farklı bir sayıdır:
- Elemanlar üzerinde döngü (
for,while) ya da liste üreteci (list comprehension) kullanma: tek bir NumPy ifadesi yeter. x’i değiştirme. Fonksiyon bittiğinde çağıran kodun array’i aynı kalır.
Karelerin toplamı makine öğrenmesinde sürekli karşına çıkar. Ortalama kare hatada (mean squared error, MSE) her hatanın karesi alınıp toplanır. Bir vektörün uzunluğunun karesi de şu toplamdır:
Hesabın kendisi basit. Bu problemin asıl konusu, hesabı nasıl yazdığındır.
Python döngüsü ile NumPy aynı hesabı farklı yapar:
| Python döngüsü | NumPy | |
|---|---|---|
| Çalışma | Her eleman yorumlayıcıdan geçer. | Tek çağrı bütün array’i derlenmiş koda verir. |
| Eleman başına iş | Çok | Çok daha az |
Bir milyon elemanlı bir array’de fark genellikle onlarca kat olur. Hesabı elemanlar üzerinde bir döngü olarak değil, bütün array’e uygulanan işlemler olarak yazmaya vectorization denir.
Döngüyle yazılmış bir çözüm de aynı sayıyı verir. Döngünün istenmemesinin nedeni sonuç değil, alışkanlıktır.
Sonraki derslerde kayıp (loss) değerini, tahminleri ve gradyanları binlerce örnek için tek seferde hesaplayacaksın. Hepsi bu biçimde yazılır. Bir hesabı “elemanlar üzerinde dolaş” yerine “tüm array’e şu işlemi uygula” diye düşünebilmek, NumPy ile çalışmanın temelidir.
Daha fazlası için NumPy hızlı başlangıç dersine bak.
Önce kareleri al, sonra topla ve sonucu bir Python float’una çevir:
import numpy as npdef sum_of_squares(x: np.ndarray) -> float: return float(np.sum(x ** 2))
Sık yapılan hata, karelerin toplamı yerine toplamın karesini almaktır (np.sum(x) ** 2). için elemanlar birbirini götürür ve sonuç çıkar. Doğru cevap ‘dir.
Kare, toplamadan önce her elemana ayrı ayrı uygulanmalıdır.
x @ x de aynı sonucu tek işlemle verir. Bir vektörün kendisiyle iç çarpımı (dot product), karelerin toplamıdır.
Bu problemde bir sorun mu var?