NumPy hızlı başlangıç
Makine öğrenmesi kodunun büyük kısmı, sayı tablolarına aynı işlemi uygulamaktır. Her satırı ölçeklersin, iki tablonun farkını alırsın, sonuçları ortalarsın. Bunu Python döngüleriyle de yazabilirsin, ama kod uzar ve yavaşlar.
NumPy sayıları dizi (array) denen tek bir nesnede toplar. Bir işlemi bütün elemanlara tek bir ifadeyle uygular; buna vektörleştirme (vectorization)vektörleştirme (vectorization): Bir işlemi Python döngüsüyle eleman eleman yazmak yerine bütün diziye tek bir ifadeyle uygulama; döngü NumPy'ın hızlı koduna geçer. denir. Büyüklükleri farklı iki array’in aynı işleme nasıl girdiğini yayınlama (broadcasting)yayınlama (broadcasting): Şekilleri (shape) farklı dizileri sağ uçtan hizalayıp boyutu 1 olan eksenlerini uzatarak aynı işleme sokan kural. kuralı belirler.
Bu derste şunları yapacaksın:
- Array kuracaksın.
- Bir Python döngüsünü tek bir ifadeye çevireceksin.
- Bir array’den parça seçeceksin.
- Satırlar ve sütunlar boyunca özetleyeceksin.
- İki array’in matris çarpımını (matrix product) alacaksın.
- Broadcasting kuralını öğreneceksin.
- Tekrarlanabilir rastgele sayılar üreteceksin.
Bu ders NumPy’ın yalnızca bu yolda gerekecek kısmını anlatır. Geri kalanı için NumPy belgelerine bakabilirsin.
Array, shape ve dtype
NumPy’ın array’i aynı türden sayıları yan yana saklar. Bir Python listesi ise her türden nesneyi tutabilir ve her eleman ayrı bir nesnedir.
Array kurmak
Bir array’i np.array ile bir listeden kurarsın. İç içe bir liste iki boyutlu bir array olur.
import numpy as npa = np.array([1.5, 2.0, 4.0]) # tek boyutluA = np.array([[1, 2, 3], [4, 5, 6]]) # iç içe liste: iki boyutluprint(a) # → [1.5 2. 4. ]print(A)# → [[1 2 3]# [4 5 6]]
np.zeros sıfırlardan, np.ones birlerden, np.arange ise 0’dan başlayan ardışık sayılardan array kurar. np.zeros((2, 3)) iki satır ve üç sütunluk bir array verir.
print(np.zeros((2, 3)))# → [[0. 0. 0.]# [0. 0. 0.]]print(np.ones((2, 3)))# → [[1. 1. 1.]# [1. 1. 1.]]print(np.arange(6)) # → [0 1 2 3 4 5]
Shape ve axis
Şekil (shape), array’in her boyutundaki eleman sayısını sıralayan bir demettir (tuple). a’nın shape’i (3,), yani tek boyut ve üç eleman. A’nın shape’i (2, 3), yani iki satır ve üç sütun.
a = np.array([1.5, 2.0, 4.0])A = np.array([[1, 2, 3], [4, 5, 6]])print(a.shape) # → (3,)print(A.shape) # → (2, 3)
Shape’teki her boyuta eksen (axis) denir. Axis 0 satırların sıralandığı yöndür, yani aşağı. Axis 1 sütunların sıralandığı yöndür, yani sağa. Bu numaraları sonraki bölümlerde yeniden kullanacaksın.
A = np.array([[1, 2, 3], [4, 5, 6]])# axis 0: satır sayısıprint(A.shape[0]) # → 2# axis 1: sütun sayısıprint(A.shape[1]) # → 3
dtype
dtype, elemanların türüdür. Bir array tek bir dtype taşır:
| Kurulduğu sayılar | dtype |
|---|---|
| ondalıklı sayılar | float64 |
| tam sayılar | int64 (bazı sistemlerde int32) |
| tam ve ondalıklı sayılar karışık | hepsi float64 |
print(np.array([1.5, 2.0, 4.0]).dtype) # → float64print(np.array([1, 2, 3]).dtype) # → int32 Linux ve macOS'ta int64print(np.array([1, 2.5, 3]).dtype) # → float64
Bir tam sayı array’ine ondalıklı bir sayı yazarsan sayı sessizce kesilir. A[0, 0] = 2.7 yazdığında o eleman 2 olur.
A = np.array([[1, 2, 3], [4, 5, 6]])A[0, 0] = 2.7print(A[0, 0]) # → 2
dtype’ı kendin de değiştirebilirsin. astype, yeni bir dtype’ta bir kopya verir ve A’ya dokunmaz. True ve False da astype(int) ile 1 ve 0 olur.
A = np.array([[1, 2, 3], [4, 5, 6]])print(np.array([True, False, True]).astype(int)) # → [1 0 1]# float64 kopyaF = A.astype(float)print(F.dtype) # → float64# kopyada ondalıklı sayı kesilmezF[0, 0] = 2.7print(F[0, 0]) # → 2.7print(A[0, 0]) # → 1
reshape ve hstack
reshape
reshape elemanları aynı sırayla tutup yalnızca shape’i değiştirir. NumPy elemanları satır satır okur ve yeni shape’e dizer. A.reshape(3, 2) şu matrisi verir:
A = np.array([[1, 2, 3], [4, 5, 6]])print(A.reshape(3, 2))# → [[1 2]# [3 4]# [5 6]]print(A.reshape(3, 2).shape) # → (3, 2)
Eleman sayısı değişemez. olduğundan A.reshape(4, 2) hata verir.
A = np.array([[1, 2, 3], [4, 5, 6]])try: A.reshape(4, 2)except ValueError as e: print(e) # → cannot reshape array of size 6 into shape (4,2)
Verdiğin sayılardan birinin yerine -1 yazarsan NumPy onu kendisi hesaplar. A.reshape(3, -1) de (3, 2) verir.
A = np.array([[1, 2, 3], [4, 5, 6]])print(A.reshape(3, -1).shape) # → (3, 2)print(A.reshape(-1, 2).shape) # → (3, 2)
Array’leri yan yana koymak
Bir sütunu bir array’in yanına eklemek için np.hstack var. extra = np.array([[7], [8]]) olsun. np.hstack([A, extra]), (2, 3) ile (2, 1)’i birleştirir ve (2, 4) shape’inde bir array verir.
np.hstack için iki koşul var:
- Satır sayıları eşit olmalıdır.
extrabir sütun, yani(2, 1)olmalıdır.(2,)shape’indeki bir array burada hata verir.
A = np.array([[1, 2, 3], [4, 5, 6]])extra = np.array([[7], [8]])print(np.hstack([A, extra]))# → [[1 2 3 7]# [4 5 6 8]]try: np.hstack([A, np.array([7, 8])])except ValueError as e: print(type(e).__name__) # → ValueError
Döngü yerine tek ifade
Vectorization, döngüyü Python’dan alıp NumPy’a verir ve hesabı hızlandırır.
Döngüyü tek ifadeye çevirmek
Dört sıcaklık değerini Celsius’tan Fahrenheit’a çevirelim. Formül şudur:
Formül, Celsius değerini 9/5 ile çarpıp 32 ekler. Python’da bunu bir döngüyle yazarsın. NumPy’da ise formülü doğrudan array’e uygularsın.
c = np.array([0.0, 20.0, 37.0, 100.0]) # Celsiusf_loop = []for x in c: f_loop.append(x * 9 / 5 + 32) # döngü: eleman elemanf = c * 9 / 5 + 32 # tek ifade, aynı sayılarprint(f) # → [ 32. 68. 98.6 212. ]# iki sonuç aynı mı?print(np.allclose(f_loop, f)) # → True
İkinci biçimde döngü yok. Üç işlem de bütün array’e uygulanır:
c * 9her elemanı 9 ile çarpar./ 5her elemanı 5’e böler.+ 32her elemana 32 ekler.
c = np.array([0.0, 20.0, 37.0, 100.0])print(c * 9) # → [ 0. 180. 333. 900.]print(c * 9 / 5) # → [ 0. 36. 66.6 180. ]print(c * 9 / 5 + 32) # → [ 32. 68. 98.6 212. ]
Eleman bazında (element-wise) işlemler
İki array arasındaki işlemler de aynı biçimde çalışır. NumPy aynı konumdaki elemanları çiftler. Buna eleman bazında işlem denir.
a = np.array([1, 2, 3])b = np.array([4, 5, 6])print(a + b) # → [5 7 9]print(b - a) # → [3 3 3]print(a * b) # → [ 4 10 18]print(a ** 2) # → [1 4 9]
** her elemanı verilen kuvvete yükseltir. a ** 2 her elemanın karesidir.
Listelerde + birleştirir, array’lerde toplar.
# iki liste: birleşirprint([1, 2] + [3, 4]) # → [1, 2, 3, 4]# iki array: eleman bazında toplanırprint(np.array([1, 2]) + np.array([3, 4])) # → [4 6]
Element-wise fonksiyonlar
np.sqrt, np.exp ve np.log gibi fonksiyonlar da element-wise çalışır. np.sqrt(a) her elemanın karekökünü alır.
print(np.sqrt(np.array([1, 4, 9]))) # → [1. 2. 3.]print(np.exp(np.array([0, 1]))) # → [1. 2.71828183]print(np.log(np.array([1, 10]))) # → [0. 2.30258509]
np.clip(b, 2, 5) değerleri 2 ile 5 arasında tutar. 2’den küçükleri 2’ye, 5’ten büyükleri 5’e çeker.
b = np.array([4, 5, 6])a = np.array([1, 2, 3])print(np.clip(b, 2, 5)) # → [4 5 5]print(np.clip(a, 2, 5)) # → [2 2 3]
* işareti de element-wise çalışır. a * b, iki array’in matris çarpımı değil, aynı konumdaki elemanların çarpımıdır. Matris çarpımının kendi operatörü var, onu aşağıda göreceksin.
P = np.array([[1, 2], [3, 4]])Q = np.array([[10, 20], [30, 40]])print(P * Q)# → [[ 10 40]# [ 90 160]]
Hız farkı
Python döngüsü ile NumPy arasındaki fark şudur:
- Python döngüsünün her turunda yorumlayıcı elemanın türüne bakar ve onu bir nesne olarak işler.
- NumPy aynı türden sayılar üzerinde derlenmiş tek bir döngü çalıştırır.
Büyük array’lerde aynı işlem döngüden çok daha hızlı biter. Hız tek kazanç değildir. c * 9 / 5 + 32 formülle neredeyse harfi harfine aynıdır ve döngüden daha rahat okunur.
Array’den parça seçmek
Bir array’den eleman seçmeye indeksleme (indexing), bir aralık seçmeye dilimleme (slicing) denir. Python listelerindeki gibi sayma 0’dan başlar. İki boyutlu bir array’de her axis için bir indeks yazarsın, aralarına virgül koyarak.
Bu bölümde şu array’e bakacağız:
B = np.arange(12).reshape(3, 4) onu kurar. NumPy 0’dan 11’e kadar on iki sayıyı üç satır ve dört sütuna dizer.
B = np.arange(12).reshape(3, 4)print(B)# → [[ 0 1 2 3]# [ 4 5 6 7]# [ 8 9 10 11]]
Indexing
B[1, 2], indeksi 1 olan satırla indeksi 2 olan sütunun kesiştiği elemandır. Sayma 0’dan başladığı için bu, ikinci satırla üçüncü sütundur.
Tek bir indeks yazarsan o satırın hepsi gelir.
B = np.arange(12).reshape(3, 4)print(B[1, 2]) # → 6print(B[0]) # → [0 1 2 3]
Negatif indeks sondan sayar. B[-1, -1] sağ alt köşedir.
B = np.arange(12).reshape(3, 4)print(B[-1, -1]) # → 11print(B[-1]) # → [ 8 9 10 11]print(B[0, -1]) # → 3
Slicing
başla:bitir biçimindeki bir dilim (slice) başlangıcı dahil eder, bitişi etmez. Tek başına : hepsi demektir.
B[:, 1]her satırın indeksi 1 olan elemanını, yani ikinci sütunu seçer.B[1:, :2]ikinci satırdan sona kadar olan satırlarla ilk iki sütunu seçer.- Bir axis için hiçbir şey yazmazsan o axis’in hepsi gelir. Bu yüzden
B[0]ileB[0, :]aynıdır.
B = np.arange(12).reshape(3, 4)print(B[:, 1]) # → [1 5 9]print(B[1:, :2])# → [[4 5]# [8 9]]print(B[0, :]) # → [0 1 2 3]print(B[1, 1:3]) # → [5 6]
Sayıyla ve dilimle seçmek
Bir axis’i tek bir sayıyla seçersen o axis shape’ten kalkar, dilimle seçersen kalır. B[0] için (4,), B[0:1] için (1, 4) çıkar.
B = np.arange(12).reshape(3, 4)print(B[1, 2].shape) # → ()print(B[0].shape) # → (4,)print(B[:, 1].shape) # → (3,)print(B[1:, :2].shape) # → (2, 2)print(B[0:1].shape) # → (1, 4)
İndeks listesiyle seçmek
scores, altı öğrencinin sınav puanlarıdır. Seçeceğin indeksleri bir listeyle ya da bir tam sayı array’iyle verebilirsin. Sonuç listedeki sırayla dizilir ve bir indeks tekrar edebilir.
Satırları böyle seçince her satır bütün sütunlarıyla gelir. B[[2, 0]] sonucunun shape’i (2, 4)’tür.
B = np.arange(12).reshape(3, 4)scores = np.array([72, 45, 88, 61, 95, 53])print(scores[[0, 2, 2]]) # → [72 88 88]print(scores[[5, 0]]) # → [53 72]print(B[[2, 0]])# → [[ 8 9 10 11]# [ 0 1 2 3]]print(B[[2, 0]].shape) # → (2, 4)
Mantıksal maske (boolean mask)
Bir karşılaştırma, array’in her elemanı için bir True ya da False üretir. Bu array’e mantıksal maske (boolean mask) denir. Maskeyi indeks olarak verirsen yalnızca True olan elemanlar kalır.
scores = np.array([72, 45, 88, 61, 95, 53])mask = scores >= 60print(mask) # → [ True False True True True False]print(scores[mask]) # → [72 88 61 95]# aynı şey tek satırdaprint(scores[scores >= 60]) # → [72 88 61 95]
İki koşulu şöyle birleştirirsin:
&(ve) ya da|(veya) kullan.- Her koşulu parantez içine al.
Python’un and ile or sözcükleri array’lerde çalışmaz. NumPy bunun için hata verir.
scores = np.array([72, 45, 88, 61, 95, 53])print(scores[(scores > 50) & (scores < 90)]) # → [72 88 61 53]print(scores[(scores < 50) | (scores > 90)]) # → [45 95]try: scores[(scores > 50) and (scores < 90)]except ValueError as e: print(type(e).__name__) # → ValueError
np.where
np.where(condition, x, y) koşulla aynı shape’te bir array verir. condition koşul demektir. Koşulun True olduğu her yerde x’ten, False olduğu yerde y’den eleman alır. x ile y birer sayı ya da array olabilir.
np.where(scores >= 60, scores, 0) geçenlerin puanını korur ve kalanları 0 yapar. np.where iki seçeneği de bütün elemanlar için hesaplar, sonra seçer.
scores = np.array([72, 45, 88, 61, 95, 53])print(np.where(scores >= 60, scores, 0)) # → [72 0 88 61 95 0]print(np.where(scores >= 60, 1, 0)) # → [1 0 1 1 1 0]
Array’i indirgemek
Bir array’i daha küçük bir sonuca indiren işlemlere indirgeme (reduction) denir. Toplam, ortalama, en büyük ve en küçük değer birer indirgemedir. Fonksiyonları np.sum, np.mean, np.max ve np.min’dir.
Burada yine şu array ile çalışalım:
Axis vermeden özetlemek
axis vermezsen bütün elemanlar tek bir sayıya iner. Sonucun shape’i ()’dir.
A = np.array([[8, 3, 1, 4], [2, 9, 6, 3], [5, 0, 11, 8]])print(np.sum(A)) # → 60print(np.mean(A)) # → 5.0print(np.max(A)) # → 11print(np.min(A)) # → 0
Axis boyunca özetlemek
axis argümanı, shape’ten hangi axis’in kalkacağını söyler. A’nın shape’i (3, 4).
axis=0verirsen axis 0 kalkar. Satırlar boyunca ilerleyip her sütunu kendi içinde toplarsın. Geriye(4,)kalır.axis=1verirsen axis 1 kalkar. Her satırı kendi içinde toplarsın. Geriye(3,)kalır.
A = np.array([[8, 3, 1, 4], [2, 9, 6, 3], [5, 0, 11, 8]])# 8+2+5, 3+9+0, 1+6+11, 4+3+8print(np.sum(A, axis=0)) # → [15 12 18 15]# 8+3+1+4, 2+9+6+3, 5+0+11+8print(np.sum(A, axis=1)) # → [16 20 24]print(np.sum(A, axis=0).shape) # → (4,)print(np.sum(A, axis=1).shape) # → (3,)
np.mean, np.max ve np.min aynı axis argümanını alır. np.sum(A, axis=0) yerine A.sum(axis=0) yazmak da aynı işi görür.
A = np.array([[8, 3, 1, 4], [2, 9, 6, 3], [5, 0, 11, 8]])print(np.mean(A, axis=0)) # → [5. 4. 6. 5.]print(np.max(A, axis=1)) # → [ 8 9 11]print(A.sum(axis=0)) # → [15 12 18 15]
Aşağıda işlemi ve axis’i seç ve sonucun shape’ine bak.
np.sum(A, axis=0)
A · shape (3, 4)
sonuç · shape (4,)
print çıktısı
[15 12 18 15]
sonuç[0] = 8 + 2 + 5 = 15 axis 0 shape'ten kalkar: (3, 4) → (4,)
Koşulu sağlayanları saymak
Boolean array’lerde True 1, False 0 sayılır. Bu yüzden bir maskenin toplamı, koşulu sağlayan eleman sayısıdır.
scores = np.array([72, 45, 88, 61, 95, 53])print(np.sum(scores >= 60)) # → 4
Karelerin toplamı
Karelerin toplamı iki adımdır: önce her elemanın karesini al, sonra kareleri topla. Önce element-wise **, sonra bir reduction gelir.
Formül, her ‘nin karesini alıp hepsini toplar. Toplamın karesi farklı bir sayıdır.
def sum_of_squares(x: np.ndarray) -> float: return float(np.sum(x ** 2))x = np.array([3.0, -4.0])print(sum_of_squares(x)) # → 25.0# toplamın karesi: yanlışprint(np.sum(x) ** 2) # → 1.0
Matris çarpımı
Matris çarpımının operatörü @ işaretidir. Bu bölümde A, v ve D array’leriyle çalışacağız.
Shape kuralı
Shape’leri (m, n) ve (n, k) olan iki array’i çarpabilirsin:
- İç boyutlar (
n) eşit olmalıdır. - Sonuç
(m, k)shape’inde çıkar. - Sonucun her elemanı şöyle çıkar: soldaki bir satırı sağdaki bir sütunla karşılıklı çarp, çarpımları topla.
left = np.ones((2, 3))right = np.ones((3, 4))print((left @ right).shape) # → (2, 4)
İç boyutlar uyuşmazsa NumPy hata verir. D @ v için (3, 2) ve (3,) karşılaşır, 2 ile 3 eşit değildir.
D = np.array([[1, 0], [0, 1], [1, 1]])v = np.array([2, 0, 1])try: D @ vexcept ValueError as e: print(type(e).__name__) # → ValueError
@ yerine * yazma. A * D bu shape’lerde hata verir: shape’ler farklı olduğu için aynı konumdaki elemanlar çiftlenemez.
A = np.array([[1, 2, 3], [4, 5, 6]])D = np.array([[1, 0], [0, 1], [1, 1]])try: A * Dexcept ValueError as e: print(e) # → operands could not be broadcast together with shapes (2,3) (3,2)
Hata mesajındaki broadcast kuralını son bölümde göreceksin.
Matris ile vektör
A’nın yanına v = np.array([2, 0, 1]) koyalım. A @ v için A’nın her satırı v ile karşılıklı çarpılıp toplanır:
Tek boyutlu v burada sütun gibi davranır. Eşleşen boyut sonuçtan kalkar.
A = np.array([[1, 2, 3], [4, 5, 6]])v = np.array([2, 0, 1])print(A @ v) # → [ 5 14]print((A @ v).shape) # → (2,)# ilk satırı elle: 1*2 + 2*0 + 3*1print(np.sum(A[0] * v)) # → 5
Bir veri matrisini bir vektörle çarpıp her satır için tek bir sayı üretmek, Model, parametre, kayıp dersinde karşına çıkacak.
İki matris
D = np.array([[1, 0], [0, 1], [1, 1]]) olsun. A @ D için shape’ler (2, 3) ve (3, 2) olur; sonuç (2, 2) çıkar.
A = np.array([[1, 2, 3], [4, 5, 6]])D = np.array([[1, 0], [0, 1], [1, 1]])print(A @ D)# → [[ 4 5]# [10 11]]# A'nın 0. satırı ile D'nin 1. sütunuprint(np.sum(A[0] * D[:, 1])) # → 5
Devrik (transpose)
A.T, A’nın devriğidir (transpose). Satırları sütun olur ve (2, 3) shape’i (3, 2)’ye döner. Matematikte diye yazılır:
A.T @ A’nın shape’i bu yüzden (3, 3)’tür. Tek boyutlu bir array’de .T bir şey yapmaz. v.T yine (3,)’tür.
A = np.array([[1, 2, 3], [4, 5, 6]])v = np.array([2, 0, 1])print(A.T)# → [[1 4]# [2 5]# [3 6]]print((A.T @ A).shape) # → (3, 3)print(v.T.shape) # → (3,)
Doğrusal denklem sistemi
Doğrusal bir denklem sistemini M @ x = c biçiminde çözmek için np.linalg.solve(M, c) var. M = np.array([[2, 1], [1, 3]]) ve c = np.array([4, 7]) için [1. 2.] verir. Sonuç sistemi sağlar, çünkü ve .
M = np.array([[2, 1], [1, 3]])c = np.array([4, 7])x = np.linalg.solve(M, c)print(x) # → [1. 2.]# sistemi sağlıyor mu?print(M @ x) # → [4. 7.]
Bunu Doğrusal regresyon dersinde kullanacaksın.
Farklı shape’ler bir arada
Broadcasting, shape’leri farklı iki array’i birlikte işleme sokan kuraldır. Element-wise işlemler aynı shape’i istiyor gibi görünür, ama A + 10 de çalışır. 10 her elemana eklenir.
Broadcasting kuralı
Sonuç shape’ini üç adımda bulursun:
- Shape’leri sağ uçtan hizala: son boyut son boyutla, bir önceki bir öncekiyle karşılaşır.
- Kısa shape’in soluna 1’ler ekle.
- Her boyut çiftinde büyüğünü al: sonucun o boyutu odur.
Her boyut çifti ya eşit olmalı ya da çiftten biri 1 olmalı. 1 olan boyut, öbürünün boyutuna uyacak kadar uzar.
A = np.array([[1, 2, 3], [4, 5, 6]])r = np.array([10, 20, 30])# A: (2, 3), r: (3,) → (1, 3) → (2, 3)print(A.shape, r.shape) # → (2, 3) (3,)print((A + r).shape) # → (2, 3)
Aşağıda bir shape çifti seç ve küçük array’in nasıl uzadığına bak.
| array | shape | axis 0 | axis 1 |
|---|---|---|---|
| a | (3, 4) | 3 | 4 |
| b | (4,) | 1 | 4 |
| sonuç | (3, 4) | 3 | 4 |
| 1 → 3 uzar | eşit |
a · (3, 4)
b · (4,)
sonuç · (3, 4)
b (4,) sağdan hizalanınca (1, 4) · b: axis 0 boyunca 1 → 3 uzar · sonuç (3, 4) sonuç[1, 2] = a[1, 2] + b[2] = 6 + 30 = 36
Sayı, satır ve sütun
A + 10 için shape’ler (2, 3) ve () olur. 10 her elemana eklenir ve sonuç (2, 3) kalır.
A = np.array([[1, 2, 3], [4, 5, 6]])print(A + 10)# → [[11 12 13]# [14 15 16]]
A’nın yanına r = np.array([10, 20, 30]) koyalım. A + r, tek satırlık ‘yi ‘nın iki satırına da ekler:
A = np.array([[1, 2, 3], [4, 5, 6]])r = np.array([10, 20, 30])print(A + r)# → [[11 22 33]# [14 25 36]]
s = np.array([[2], [3]]) için shape’ler (2, 3) ve (2, 1) olur. A * s birinci satırı 2 ile, ikinciyi 3 ile çarpar.
A = np.array([[1, 2, 3], [4, 5, 6]])s = np.array([[2], [3]])print(A * s)# → [[ 2 4 6]# [12 15 18]]
Uyuşmayan shape’ler
t = np.array([1, 2]) için A + t hata verir. t’nin shape’i (2,) olduğundan hizalanınca (1, 2) olur. A’nın son boyutu 3, t’ninki 2’dir.
A = np.array([[1, 2, 3], [4, 5, 6]])t = np.array([1, 2])try: A + texcept ValueError as e: print(e) # → operands could not be broadcast together with shapes (2,3) (2,)
Çözüm, t’yi bir sütuna çevirmektir. t.reshape(2, 1) (ya da t.reshape(-1, 1)) (2, 1) shape’indedir. A + t.reshape(2, 1), A’nın ilk satırına 1, ikinci satırına 2 ekler.
A = np.array([[1, 2, 3], [4, 5, 6]])t = np.array([1, 2])print(t.reshape(2, 1).shape) # → (2, 1)print(A + t.reshape(2, 1))# → [[2 3 4]# [6 7 8]]
İki yönde birden uzamak
Her iki array’de de 1 olan boyutlar olabilir. O zaman ikisi de kendi 1’ini uzatır: (4, 1) ile (1, 3) toplanınca (4, 3) çıkar.
İpucu
Aşağıdaki çıktıya bakmadan, shape’leri (4, 1) ve (1, 3) olan iki array’in toplamının shape’ini bul, sonra çıktıyla karşılaştır.
col = np.array([[0], [10], [20], [30]]) # (4, 1)row = np.array([[1, 2, 3]]) # (1, 3)print((col + row).shape) # → (4, 3)print(col + row)# → [[ 1 2 3]# [11 12 13]# [21 22 23]# [31 32 33]]
Sütunları merkezleme
Broadcasting’in sık kullanılan bir örneği, veri matrisinin sütunlarını merkezlemektir. Her sütundan o sütunun ortalamasını çıkarırsın, böylece her sütunun ortalaması 0 olur.
X’in shape’i (n, d), ortalamaların shape’i (d,)’dir. (d,) hizalanınca (1, d) olur ve her satıra uygulanır.
def center_columns(X: np.ndarray) -> np.ndarray: return X - X.mean(axis=0)X = np.array([[1.0, 10.0], [3.0, 20.0], [5.0, 30.0]])print(X.mean(axis=0)) # → [ 3. 20.]print(center_columns(X))# → [[ -2. -10.]# [ 0. 0.]# [ 2. 10.]]
(3,) ile (3, 1) farkı
Dikkat
(3,) ile (3, 1) aynı üç sayıyı taşır ama farklı array’lerdir. İkisini birbirinden çıkarırsan (3,) hizalanınca (1, 3) olur ve sonuç (3, 3) çıkar.
Hata yok, ama üç yerine dokuz sayı çıkar. Bu, NumPy kodunda sık rastlanan sessiz hatalardan biridir. Bir işlemden önce .shape’e bak.
u = np.array([1, 2, 3]) # (3,)u_col = u.reshape(3, 1) # (3, 1)print((u - u_col).shape) # → (3, 3)print(u - u_col)# → [[ 0 1 2]# [-1 0 1]# [-2 -1 0]]
Rastgele sayılar
Deneme verisi için rastgele sayılar gerekir, ama deneyin tekrar çalıştırılabilmesi için bu sayıların aynı çıkması gerekir.
Tohum (seed)
Önce rng = np.random.default_rng(0) ile bir rastgele sayı üreteci kurarsın. Parantezin içindeki sayı tohumdur (seed).
Aynı seed ile kurulan üreteç hep aynı sayıları verir, böylece sonuçlar tekrarlanabilir olur. rng.random(2), 0 ile 1 arasında iki sayı verir.
rng_a = np.random.default_rng(0)rng_b = np.random.default_rng(0)rng_c = np.random.default_rng(1)print(rng_a.random(2)) # → [0.63696169 0.26978671]# aynı seed, aynı sayılarprint(rng_b.random(2)) # → [0.63696169 0.26978671]# başka seed, başka sayılarprint(rng_c.random(2)) # → [0.51182162 0.9504637 ]
Eski np.random.seed ve np.random.rand tek bir küresel durumu paylaşır. Bu yolda hep kendi rng nesneni kullanacaksın.
Üreteçten sayı çekmek
Üreteç üç işe yarar:
| İfade | Verdiği |
|---|---|
rng.normal(size=(4, 2)) | ortalaması 0 ve standart sapması (standard deviation) 1 olan normal dağılımdan (4, 2) shape’inde bir array |
rng.random(3) | 0 ile 1 arasında üç sayı |
rng.permutation(5) | 0’dan 4’e kadar sayıların rastgele bir sıralaması, (5,) shape’inde |
rng = np.random.default_rng(0)print(rng.normal(size=(4, 2)).shape) # → (4, 2)print(rng.random(3)) # → [0.54362499 0.93507242 0.81585355]print(rng.permutation(5)) # → [2 1 3 4 0]
Üreteç her çağrıda kaldığı yerden devam eder. Bu yüzden değerler çağrıların sırasına bağlıdır.
Özet
- Shape her axis’in eleman sayısıdır,
dtypeelemanların türüdür. reshapeelemanları aynı sırayla yeni bir shape’e dizer.- Vectorization, bir işlemi eleman eleman yazmak yerine bütün array’e tek bir ifadeyle uygular.
+,-,*,**işlemleri ilenp.sqrtvenp.clipgibi fonksiyonlar element-wise çalışır.- Indexing tek bir elemanı, slicing bir aralığı seçer. Boolean mask koşula uyan elemanları seçer,
np.wherekoşula göre iki değerden birini alır. np.sumvenp.meangibi reduction’lar bir array’i küçültür.axisverirsen yalnızca o axis shape’ten kalkar.- Matris çarpımının operatörü
@işaretidir,A.Tdevriktir. - Broadcasting’de shape’ler sağ uçtan hizalanır ve her boyut çifti eşit ya da 1 olmalıdır.
(3,)ile(3, 1)farklı şeylerdir. rng = np.random.default_rng(seed)ile kurulan üreteç aynı seed’de aynı sayıları verir.
Terimler
| Türkçe | English |
|---|---|
| dizi | array |
| şekil | shape |
| eksen | axis |
| demet | tuple |
| standart sapma | standard deviation |
| eleman bazında | element-wise |
| vektörleştirme | vectorization |
| yayınlama | broadcasting |
| matris çarpımı | matrix product |
| devrik | transpose |
| indeksleme | indexing |
| dilimleme | slicing |
| mantıksal maske | boolean mask |
| indirgeme | reduction |
| tohum | seed |
Şimdi sıra sende
Ders tamamlandı. Sıradaki: ilk problem.
İlk problem: Döngüyü vektörleştir →Notların
Metinden bir bölüm seçip Not al'a basarak da ekleyebilirsin.
Bu derse dair söylemek istediğin bir şey var mı?