Tiga nilai yang sama dapat disimpan dalam tiga bentuk berbeda, yaitu (n,), (n, 1), dan (1, n). Tampilan cetak ketiganya berbeda, demikian pula perilakunya pada broadcasting. Topik ini membahas semantik ketiga bentuk tersebut, cara mengubah vektor satu dimensi menjadi vektor kolom atau vektor baris, dan penjumlahan dua vektor yang menghasilkan matriks.
Tiga bentuk, tiga semantik#
Bentuk (n,) adalah array satu dimensi, yaitu urutan nilai tanpa arah baris maupun kolom. Bentuk (n, 1) adalah array dua dimensi dengan satu kolom yang sering disebut vektor kolom, sedangkan (1, n) adalah array dua dimensi dengan satu baris yang disebut vektor baris. Kedua vektor tersebut tetap berdimensi dua meskipun hanya memuat n nilai, dan perbedaan itu terbaca dari atribut ndim. Ketiga bentuk memuat nilai yang sama, tetapi tata letak cetaknya berbeda, sehingga pembeda yang andal adalah atribut bentuk, bukan nilai yang tersimpan.
Perbedaan semantik ini penting pada broadcasting karena dimensi diperiksa berpasangan. Vektor kolom diperluas sepanjang dimensi kolomnya, sedangkan vektor baris diperluas sepanjang dimensi barisnya. Ketiga bentuk menyimpan jumlah memori yang sama, yaitu n elemen, sehingga perbedaannya murni pada interpretasi dimensinya. Diagram berikut membandingkan ketiga bentuk untuk nilai yang sama, yaitu 1, 2, dan 3.
Mengubah vektor 1D menjadi kolom atau baris#
Indeks np.newaxis menyisipkan dimensi baru berukuran 1 pada posisi penulisannya. Penulisan a[:, np.newaxis] menambahkan dimensi di belakang sehingga (3,) menjadi (3, 1), sedangkan a[np.newaxis, :] menambahkan dimensi di depan sehingga menjadi (1, 3). Alternatif lain adalah a.reshape(-1, 1), yang menggunakan placeholder -1 agar panjang sisa dihitung otomatis. Indeks np.newaxis sendiri hanyalah alias untuk None di Python, sehingga a[:, None] menghasilkan bentuk yang sama, tetapi penulisan np.newaxis lebih disukai karena maksudnya terbaca.
import numpy as np
a = np.array([1, 2, 3])
kolom = a[:, np.newaxis]
baris = a[np.newaxis, :]
print("a :", a.shape, "ndim", a.ndim)
print("kolom :", kolom.shape, "ndim", kolom.ndim)
print("baris :", baris.shape, "ndim", baris.ndim)a : (3,) ndim 1
kolom : (3, 1) ndim 2
baris : (1, 3) ndim 2Angka ndim menegaskan bahwa kolom dan baris adalah array dua dimensi, sedangkan a tetap array satu dimensi. Contoh konkret yang membedakan kedua jenis bentuk tersebut adalah pengurangan rata-rata kolom. Rata-rata per kolom dari matriks (2, 3) berbentuk (3,), dan bentuk itu sudah cocok dengan dimensi terakhir matriks, sehingga tidak perlu dimensi baru.
import numpy as np
m = np.arange(1, 7).reshape(2, 3)
rata_kolom = m.mean(axis=0)
print("rata kolom :", rata_kolom)
print("m - rata :")
print(np.round(m - rata_kolom, 2))rata kolom : [2.5 3.5 4.5]
m - rata :
[[-1.5 -1.5 -1.5]
[ 1.5 1.5 1.5]]Setiap kolom dikurangi rata-ratanya sendiri, dan hasilnya tetap berbentuk (2, 3). Apabila yang diinginkan adalah pengurangan per baris, rata-ratanya dihitung dengan axis=1 lalu hasilnya diubah menjadi (2, 1) terlebih dahulu, karena penyelarasan (2, 3) dengan (2,) akan gagal.
import numpy as np
a = np.array([1, 2, 3])
kolom = a[:, np.newaxis]
sama = np.array_equal(kolom, a.reshape(-1, 1))
print("hasil sama:", sama)
print(kolom)hasil sama: True
[[1]
[2]
[3]]Kedua cara menghasilkan nilai yang identik, dan pilihannya hanya soal gaya penulisan. Yang menentukan perilaku broadcasting adalah bentuk akhirnya, bukan cara bentuk itu diperoleh.
Dua penjumlahan yang berbeda#
Menjumlahkan dua vektor satu dimensi dengan panjang sama menghasilkan vektor satu dimensi baru, karena kedua bentuk (3,) diselaraskan tanpa perluasan. Menjumlahkan vektor kolom dengan vektor baris menghasilkan matriks, karena masing-masing diperluas pada dimensi yang berbeda. Secara matematis, setiap sel hasil memuat .
import numpy as np
x = np.array([1, 2, 3])
y = np.array([10, 20, 30])
print("1D + 1D:")
print(x + y)
luar = x[:, np.newaxis] + y[np.newaxis, :]
print("kolom + baris:")
print(luar)1D + 1D:
[11 22 33]
kolom + baris:
[[11 21 31]
[12 22 32]
[13 23 33]]Polanya disebut operasi luar (outer) karena hasilnya memuat seluruh pasangan nilai dari kedua operand. Bentuk (3, 1) menyumbang dimensi baris, sedangkan (1, 3) menyumbang dimensi kolom, dan keduanya bertemu tanpa tabrakan karena nilainya 1. Urutan operand tidak mengubah hasilnya, karena (1, 3) bertemu (3, 1) diselaraskan dengan cara yang sama. Pasangan bentuk lain dapat diperiksa dengan pola yang sama. Dua vektor kolom (3, 1) diselaraskan tanpa perluasan dan menghasilkan vektor kolom baru, sedangkan dua vektor baris (1, 3) menghasilkan vektor baris baru. Perluasan hanya terjadi ketika dimensi yang sejajar bernilai 1, sehingga bentuk hasil selalu mengikuti dimensi yang lebih panjang.
Jebakan yang sering terjadi adalah menambahkan vektor (n,) ke matriks dua dimensi. Bentuk (3,) diselaraskan sebagai vektor baris pada dimensi terakhir, bukan sebagai kolom. Apabila maksudnya adalah menambahkan v[i] ke baris ke-i, hasilnya keliru tanpa memunculkan pesan error apa pun.
import numpy as np
m = np.arange(1, 10).reshape(3, 3)
v = np.array([100, 200, 300])
hasil = m + v
print("bentuk hasil:", hasil.shape)
print(hasil)bentuk hasil: (3, 3)
[[101 202 303]
[104 205 306]
[107 208 309]]Setiap baris menerima vektor [100, 200, 300] yang sama, sehingga hasilnya adalah penjumlahan per kolom. Apabila maksudnya adalah menambahkan v[i] ke baris ke-i, v harus diubah menjadi (3, 1) terlebih dahulu dengan v[:, np.newaxis]. Kesalahan arah semacam ini sulit dilacak karena bentuk keluarannya tetap (3, 3) dan tampak wajar. Pemeriksaan yang efektif dilakukan terhadap bentuk operand sebelum operasi dijalankan, bukan terhadap bentuk hasilnya.
Rencana broadcasting dapat diprediksi sebelum array disusun. Pemanggilan np.broadcast_shapes((3, 1), (1, 3)) mengembalikan (3, 3), sehingga arah perluasan dapat diperiksa satu baris tanpa membuat array terlebih dahulu. Pemeriksaan sekecil ini cukup untuk menangkap kesalahan arah sebelum hasilnya digunakan lebih jauh.
Ringkasan#
- Bentuk
(n,)adalah array satu dimensi,(n, 1)adalah vektor kolom, dan(1, n)adalah vektor baris. a[:, np.newaxis],a[np.newaxis, :], dana.reshape(-1, 1)mengubah vektor satu dimensi menjadi bentuk dua dimensi.- Vektor kolom ditambah vektor baris menghasilkan matriks
(n, n)melalui perluasan pada dua dimensi. - Vektor
(n,)yang bertemu matriks(m, n)diartikan sebagai vektor baris pada dimensi terakhir.
Referensi#
- Broadcasting — NumPy — Dokumentasi resmi aturan broadcasting, termasuk contoh penjumlahan vektor kolom dengan vektor baris.
- Indexing on ndarrays — NumPy
— Dokumentasi resmi pengindeksan, termasuk penggunaan
np.newaxisuntuk menambah dimensi.