Tensor adalah perluasan vektor dan matriks ke dimensi berapa pun, dan tensor jugalah bahasa kerja seluruh kerangka deep learning: data masuk sebagai tensor, bobot disimpan sebagai tensor, gradient dikembalikan sebagai tensor. Setiap galat shape mismatch yang akan kita temui di PyTorch maupun TensorFlow pada dasarnya adalah ketidakcocokan bentuk tensor yang bisa dibaca langsung dari pesan galatnya. Pada chapter penutup section ini kita bedah anatominya — rank dan shape — lalu berlatih empat keluarga operasi yang paling sering dipakai, semuanya dengan angka kecil yang bisa dihitung ulang dengan mata.
Rank dan Shape: Anatomi Tensor #
Dua angka menjelaskan bentuk sebuah tensor. Rank (atau ndim) menghitung jumlah sumbunya; shape mencatat panjang tiap sumbu berurutan. Skalar ber-rank 0 tanpa sumbu, vektor ber-rank 1, matriks ber-rank 2, dan seterusnya. Diagram berikut menunjukkan tangga dimensinya:
Membaca shape dilakukan dari kiri ke kanan, satu angka satu sumbu. Shape (2, 3, 2, 4) berarti 2 gambar, masing-masing 3 channel, tinggi 2 piksel, lebar 4 piksel — total elemennya 2×3×2×4 = 48. Berkas rank_dan_shape.py menelusuri tangga tersebut dari skalar sampai batch gambar:
"""Menelusuri rank dan shape tensor dari skalar hingga batch gambar."""
import numpy as np
skalar = np.array(7)
vektor = np.array([1.0, 2.0, 3.0])
matriks = np.array([[1.0, 2.0], [3.0, 4.0]])
tensor3d = np.arange(8, dtype=float).reshape(2, 2, 2)
batch = np.arange(48, dtype=float).reshape(2, 3, 2, 4)
kumpulan = [
("skalar", skalar),
("vektor", vektor),
("matriks", matriks),
("tensor3d", tensor3d),
("batch", batch),
]
for nama, t in kumpulan:
print(f"{nama:8s} | rank {t.ndim} | shape {t.shape}")
print()
print("Isi tensor3d:")
print(tensor3d)
print("batch[0, 0] (channel pertama, gambar pertama):")
print(batch[0, 0])Output yang Dihasilkan:
skalar | rank 0 | shape ()
vektor | rank 1 | shape (3,)
matriks | rank 2 | shape (2, 2)
tensor3d | rank 3 | shape (2, 2, 2)
batch | rank 4 | shape (2, 3, 2, 4)
Isi tensor3d:
[[[0. 1.]
[2. 3.]]
[[4. 5.]
[6. 7.]]]
batch[0, 0] (channel pertama, gambar pertama):
[[0. 1. 2. 3.]
[4. 5. 6. 7.]]Mari kita telaah kode di atas baris per baris:
- Baris 5-9 (lima variabel): lima bentuk dasar dibuat dari nilai sederhana.
np.arange(8)menghasilkan vektor[0..7]yang langsung disusun ulang menjadi kubus 2×2×2, dannp.arange(48)menjadi batch 2×3×2×4 — total elemen harus tetap sama, itulah syarat reshape. - Baris 18-19 (perulangan cetak):
t.ndimmemberi rank,t.shapememberi bentuk. Perhatikan skalar: rank 0 dengan shape()— sepasang kurung kosong. - Baris 22-23 (
tensor3d): kubus 2×2×2 tercetak sebagai dua matriks 2×2 bersarang — NumPy merender tiap potongan sumbu pertama sebagai blok terpisah. - Baris 24-25 (
batch[0, 0]): indeks[0, 0]mengunci sumbu pertama (gambar ke-0) dan sumbu kedua (channel ke-0), menyisakan matriks 2×4 — piksel channel merah pada gambar pertama. Setiap indeks yang diberikan menghapus satu sumbu dari hasilnya.
Empat Keluarga Operasi Tensor #
Hampir semua manipulasi tensor yang kita lakukan sehari-hari terbagi ke empat keluarga berikut:
- Elementwise: operasi diterapkan pada tiap pasangan elemen seposisi (
A * 2,A + B); shape hasil mengikuti operand. Versi khususnya, broadcasting, menyelaraskan bentuk yang berbeda agar tetap bisa dipasangkan. - Reduksi: menggabungkan nilai sepanjang satu sumbu (
sum,mean,max); sumbu yang digabungkan dihapus dari shape hasil. - Reshape: menyusun ulang elemen yang sama ke bentuk baru; urutan data berjalan baris demi baris tetap dipertahankan.
- Transpose: menukar urutan sumbu; elemen benar-benar berpindah posisi.
Berkas operasi_tensor.py mendemonstrasikan keempatnya pada satu matriks kecil:
"""Operasi tensor: elementwise, reduksi, reshape, dan transpose."""
import numpy as np
X = np.array([[1.0, 2.0, 3.0],
[4.0, 5.0, 6.0]])
print("X shape awal:", X.shape)
kali = X * 10.0
tambah = X + np.array([100.0, 200.0, 300.0])
print("Elementwise X * 10:")
print(kali)
print("Elementwise X + vektor (broadcasting):")
print(tambah)
print("Reduksi total :", X.sum())
print("Reduksi kolom :", X.sum(axis=0))
print("Reduksi baris :", X.sum(axis=1))
rata2 = X.mean(axis=1, keepdims=True)
print("Mean per baris (keepdims=True):")
print(rata2)
print("Shape hasil :", rata2.shape)
print("Reshape (2,3) -> (3,2):")
print(X.reshape(3, 2))
print("Transpose X.T:")
print(X.T)
print("Shape X.T :", X.T.shape)Output yang Dihasilkan:
X shape awal: (2, 3)
Elementwise X * 10:
[[10. 20. 30.]
[40. 50. 60.]]
Elementwise X + vektor (broadcasting):
[[101. 202. 303.]
[104. 205. 306.]]
Reduksi total : 21.0
Reduksi kolom : [5. 7. 9.]
Reduksi baris : [ 6. 15.]
Mean per baris (keepdims=True):
[[2.]
[5.]]
Shape hasil : (2, 1)
Reshape (2,3) -> (3,2):
[[1. 2.]
[3. 4.]
[5. 6.]]
Transpose X.T:
[[1. 4.]
[2. 5.]
[3. 6.]]
Shape X.T : (3, 2)Mari kita telaah kode di atas baris per baris:
- Baris 9 (
kali = X * 10.0): elementwise klasik — setiap elemen dikalikan 10, shape tetap(2, 3). - Baris 10 (
tambah = X + np.array(...)): broadcasting — vektor(3,)“dilebarkan” ke setiap baris matriks(2, 3)sehingga penjumlahan tetap sah. Aturan lengkapnya dibahas pada panduan broadcasting NumPy . - Baris 16-18 (
sumdenganaxis): tanpaaxis, seluruh tensor digabungkan menjadi satu angka21.0;axis=0menggabungkan sepanjang baris menghasilkan total per kolom[5, 7, 9];axis=1menghasilkan total per baris[6, 15]. - Baris 20-23 (
keepdims=True): mean per baris tetap menyimpan sumbu dengan panjang 1 — shape(2, 1)alih-alih(2,). Bentuk ini sering dibutuhkan agar hasil reduksi bisa langsung di-broadcast kembali ke bentukX, misalnya saat menghitung selisih terhadap rata-rata. - Baris 25-26 (
reshape(3, 2)): elemen yang sama disusun ulang dengan urutan baca baris demi baris:[1, 2, 3, 4, 5, 6]menjadi tiga baris berisi dua kolom. - Baris 27-29 (
X.T): transpose menukar baris dan kolom — hasilnya juga berukuran(3, 2), tetapi isinya berbeda dari reshape: baris pertamaX.Tadalah kolom pertamaX. Kedua operasi ini sering tertukar dan menjadi sumber galat senyap.
Efek Operasi terhadap Shape #
Tabel berikut menjadi rangkuman cepat saat membaca atau menulis kode tensor:
| Operasi | Contoh pada X ber-shape (2, 3) | Shape hasil |
|---|---|---|
| Elementwise | X * 10.0 | (2, 3) — tetap |
| Broadcasting | X + vektor (3,) | (2, 3) — operand kecil dilebarkan |
| Reduksi penuh | X.sum() | () — semua sumbu digabungkan |
Reduksi axis=0 | X.sum(axis=0) | (3,) — satu sumbu dihapus |
Reduksi keepdims | X.mean(axis=1, keepdims=True) | (2, 1) — sumbu dipertahankan |
| Reshape | X.reshape(3, 2) | (3, 2) — elemen sama, tata letak baru |
| Transpose | X.T | (3, 2) — sumbu bertukar posisi |
| Indexing | X[0], batch[0, 0] | sumbu terindeks dihapus |
Seluruh operasi pada chapter ini berjalan di ndarray NumPy
, tetapi nama dan perilakunya dipindahkan hampir tanpa perubahan ke torch.Tensor dan tf.Tensor — reshape, transpose, sum(axis=...), dan broadcasting bekerja dengan semantik yang sama. Fondasi section ini kini lengkap: aljabar linear untuk menyusun model, kalkulus untuk melatihnya, probabilitas untuk menafsirkannya, siklus machine learning untuk mengelolanya, representasi numerik untuk menyiapkan datanya, dan operasi tensor untuk mengolahnya. Langkah berikutnya bukan matematika lagi, melainkan perangkat: menyiapkan lingkungan kerja Python lengkap dengan PyTorch dan TensorFlow di komputer Anda.