Sering kali data yang kita pegang berupa vektor 1-D, tetapi operasi berikutnya memintanya sebagai baris atau kolom di dalam array 2-D. Alat standar untuk keperluan itu adalah np.newaxis — sebuah alias None yang menyisipkan sumbu baru berukuran satu, sehingga vektor dapat dibentuk ulang menjadi vektor baris (1, n) atau vektor kolom (n, 1) tanpa menyalin data.

Bab ini membahas:

  • Menyisipkan sumbu baru dengan np.newaxis.
  • Menghasilkan matriks jenis outer dari dua vektor.
  • Pola penerapan yang paling sering dipakai: normalisasi per baris dengan keepdims.

Menyisipkan sumbu baru #

Satu vektor, dua arah penyisipan sumbu:

python
import numpy as np

a = np.array([10, 20, 30, 40])
baris = a[np.newaxis, :]
kolom = a[:, np.newaxis]

print(baris.shape)
print(kolom.shape)
print(baris)
print(kolom)

Output yang Dihasilkan:

text
(1, 4)
(4, 1)
[[10 20 30 40]]
[[10]
 [20]
 [30]
 [40]]
  1. Baris 4 (a[np.newaxis, :]): sumbu baru disisipkan di depan, menghasilkan vektor baris (1, 4) — satu baris berisi empat nilai.
  2. Baris 5 (a[:, np.newaxis]): sumbu baru disisipkan di belakang, menghasilkan vektor kolom (4, 1) — empat baris berisi satu nilai.
  3. Baris 7-10: kedua hasil adalah view terhadap a, karena penyisipan sumbu hanya mengubah metadata bentuk dan strides, bukan isinya.

Kedua ekspresi setara dengan a.reshape(1, 4) dan a.reshape(4, 1); pilihan np.newaxis lazim dipakai karena posisi sumbaru terbaca langsung dari tanda kurung.

EkspresiBentuk hasilPeran
a[np.newaxis, :](1, n)vektor baris
a[:, np.newaxis](n, 1)vektor kolom
a.sum(axis=1, keepdims=True)(n, 1)total per baris, siap dibroadcast
a.sum(axis=1)(n,)sumbu hasil hilang — berisiko salah arah

Matriks jenis outer dari dua vektor #

Vektor kolom (3, 1) dan vektor baris (1, 4) adalah pasangan broadcasting yang paling terkenal: perluasan keduanya menghasilkan matriks penuh berukuran (3, 4).

python
import numpy as np

u = np.array([1, 2, 3])
v = np.array([10, 20, 30, 40])

m = u[:, np.newaxis] * v[np.newaxis, :]

print(m.shape)
print(m)

Output yang Dihasilkan:

text
(3, 4)
[[ 10  20  30  40]
 [ 20  40  60  80]
 [ 30  60  90 120]]
  1. Baris 5 (u[:, np.newaxis]): kolom vektor (3, 1); setiap elemen u menempati satu baris.
  2. Baris 5 (v[np.newaxis, :]): baris vektor (1, 4); seluruh v menempati satu baris.
  3. Baris 5 (perkalian): penyelarasan (3, 1) versus (1, 4) menghasilkan (3, 4); elemen (i, j) berisi u[i] * v[j] — pola yang dikenal sebagai perkalian outer, setara dengan np.outer(u, v).

Normalisasi per baris dengan keepdims #

Pola penerapan np.newaxis yang paling sering muncul: membagi tiap baris dengan total barisnya sendiri. Method sum(axis=1, keepdims=True) menghasilkan (3, 1) — bentuk yang tepat untuk dibroadcast menyamping:

python
import numpy as np

p = np.array([[4., 8., 6.],
              [10., 5., 5.],
              [3., 3., 9.]])

total = p.sum(axis=1, keepdims=True)
normal = p / total

print(total)
print(total.shape)
print(normal)
print(normal.sum(axis=1))

Output yang Dihasilkan:

text
[[18.]
 [20.]
 [15.]]
(3, 1)
[[0.22222222 0.44444444 0.33333333]
 [0.5        0.25       0.25      ]
 [0.2        0.2        0.6       ]]
[1. 1. 1.]
  1. Baris 7 (keepdims=True): sumbu yang diratakan dipertahankan sebagai kolom tunggal, sehingga total berbentuk (3, 1); baris pertama adalah total 18 untuk baris pertama p.
  2. Baris 8 (p / total): (3, 4) dibagi (3, 1) — tiap baris dibagi totalnya sendiri, dan tiap baris normal berjumlah 1 seperti terlihat pada baris terakhir output.

Apa yang terjadi bila keepdims ditinggalkan? Hasil sum berbentuk (3,), dan pembagian tetap berjalan tanpa error — tetapi dengan arah yang salah:

python
import numpy as np

p = np.array([[4., 8., 6.],
              [10., 5., 5.],
              [3., 3., 9.]])

print(p.sum(axis=1).shape)
print(p / p.sum(axis=1))

Output yang Dihasilkan:

text
(3,)
[[0.22222222 0.4        0.4       ]
 [0.55555556 0.25       0.33333333]
 [0.16666667 0.15       0.6       ]]
  1. Baris 7 (shape): tanpa keepdims, hasil sum berbentuk (3,) — vektor baris.
  2. Baris 8 (p / p.sum(axis=1)): penyelarasan (3, 4) versus (1, 3) memperluas (3,) menyamping, sehingga total baris [18, 20, 15] justru terpakai sebagai pembagi per kolom. Nilai p[0, 1] dibagi 20, bukan 18.