PyTorch menyimpan seluruh data yang diprosesnya — nilai piksel gambar, bobot layer, nilai loss, sampai gradien — di dalam satu struktur bernama tensor. Tensor adalah generalisasi dari konsep yang sudah kita kenal pada section prasyarat: skalar adalah tensor rank 0, vektor rank 1, matriks rank 2, dan di atas keduanya tensor N-D menampung struktur data yang lebih kaya. Berbeda dengan np.ndarray, torch.Tensor membawa dua kemampuan tambahan yang menjadi fondasi deep learning: pemindahan ke GPU dan pencatatan gradien otomatis. Chapter ini membangun intuisi tangga rank, memetakan shape wadah data deep learning seperti batch gambar dan batch teks, lalu membandingkan torch.Tensor dengan ndarray NumPy secara langsung lewat kode yang berjalan.

Dari Skalar ke Tensor N-D #

Rank sebuah tensor adalah jumlah sumbunya, sedangkan shape mencatat panjang tiap sumbu berurutan. Satu angka harga saham cukup satu skalar; satu vektor fitur menggambarkan satu contoh data; satu matriks mengemas satu batch contoh. Ketika data punya struktur lebih kaya, rank naik: satu gambar RGB adalah tensor 3D, dan satu kumpulan gambar menjadi tensor 4D. Tabel berikut memetakan tangga tersebut ke contoh deep learning:

RankNama umumContoh pemakaianShape khas
0skalarsatu nilai loss, satu learning rate()
1vektorfitur satu contoh, bias satu layer(fitur,)
2matriksbatch fitur, bobot layer linear(batch, fitur)
3tensor 3Dbatch teks: token × fitur(batch, token, fitur)
4tensor 4Dbatch gambar: channel × tinggi × lebar(batch, channel, tinggi, lebar)
5tensor 5Dbatch cuplikan video(batch, channel, waktu, tinggi, lebar)

Tensor sebagai Wadah Data Deep Learning #

Dua wadah yang paling sering kita jumpai adalah batch gambar 4D (N, C, H, W) dan batch teks 3D (batch, token, fitur). Berkas tangga_rank.py menelusuri keduanya sekaligus tangga rank dari skalar hingga tensor 4D:

python
"""Menelusuri tangga rank tensor PyTorch sampai wadah data deep learning."""

import torch

skalar = torch.tensor(7.0)
vektor = torch.tensor([1.0, 2.0, 3.0])
matriks = torch.tensor([[1.0, 2.0],
                        [3.0, 4.0]])
batch_teks = torch.arange(24, dtype=torch.float32).reshape(2, 3, 4)
batch_gambar = torch.arange(24, dtype=torch.float32).reshape(2, 3, 2, 2)

daftar = [
    ("skalar (satu harga)", skalar),
    ("vektor (fitur 1 contoh)", vektor),
    ("matriks (batch 2 contoh)", matriks),
    ("3D: batch teks (2,3,4)", batch_teks),
    ("4D: batch gambar (2,3,2,2)", batch_gambar),
]
for nama, t in daftar:
    print(f"{nama:28s} | rank {t.dim()} | shape {tuple(t.shape)} | {t.numel()} elemen")

print()
print("channel pertama gambar pertama, batch_gambar[0, 0]:")
print(batch_gambar[0, 0])

Output yang Dihasilkan:

text
skalar (satu harga)          | rank 0 | shape () | 1 elemen
vektor (fitur 1 contoh)      | rank 1 | shape (3,) | 3 elemen
matriks (batch 2 contoh)     | rank 2 | shape (2, 2) | 4 elemen
3D: batch teks (2,3,4)       | rank 3 | shape (2, 3, 4) | 24 elemen
4D: batch gambar (2,3,2,2)   | rank 4 | shape (2, 3, 2, 2) | 24 elemen

channel pertama gambar pertama, batch_gambar[0, 0]:
tensor([[0., 1.],
        [2., 3.]])

Mari kita telaah kode di atas baris per baris:

  1. Baris 5-8 (empat variabel pertama): torch.tensor membuat tensor langsung dari angka atau list Python bersarang; penulisan 7.0 membuat elemen bertipe float32, tipe standar deep learning.
  2. Baris 9-10 (torch.arange(...).reshape(...)): 24 angka berurutan disusun menjadi batch teks (2, 3, 4) — 2 kalimat, 3 token, 4 nilai fitur per token — dan batch gambar (2, 3, 2, 2) mengikuti konvensi NCHW dengan 2 gambar, 3 channel, dan piksel 2×2.
  3. Baris 19-20 (perulangan cetak): t.dim() melaporkan rank, tuple(t.shape) bentuk, dan t.numel() jumlah elemen. Perhatikan skalar: rank 0 dengan shape () — sepasang kurung kosong.
  4. Baris 23-24 (batch_gambar[0, 0]): dua indeks mengunci sumbu batch dan sumbu channel, menyisakan matriks 2×2 milik channel pertama gambar pertama — bukti bahwa satu “gambar” di dalam tensor 4D tetap tersusun dari angka biasa.

torch.Tensor versus np.ndarray #

PyTorch sengaja meniru antarmuka NumPy agar kebiasaan kita dari section sebelumnya tetap berlaku: operator +, *, indexing [1, 2], sampai fungsi sum berperilaku serupa. Perbedaannya ada pada tiga hal: tensor punya atribut device (bisa dipindah ke GPU), tensor bisa mencatat gradien lewat requires_grad, dan tensor mendukung komputasi terdiferensiasi penuh. Tabel berikut merangkum perbandingannya:

Aspeknp.ndarraytorch.Tensor
Bentuk dan indexingshape, X[1, 2]sama persis
Tipe datadtype NumPy (float64 bawaan)dtype torch (float32 bawaan)
Lokasi dataRAM CPU sajadevice: cpu atau cuda
Gradien otomatistidak adarequires_grad + autograd
Konversi dua arah—torch.from_numpy, t.numpy()

Berkas tensor_vs_numpy.py menguji perbandingan tersebut pada data yang sama, termasuk jembatan memori dua arah antara keduanya:

python
"""Membandingkan torch.Tensor dan np.ndarray pada data yang sama."""

import numpy as np
import torch

data = [[1.0, 2.0, 3.0],
        [4.0, 5.0, 6.0]]
arr = np.array(data)
t = torch.tensor(data)

print("NumPy : shape", arr.shape, "| dtype", arr.dtype)
print("Torch : shape", tuple(t.shape), "| dtype", t.dtype, "| device", t.device)
print("Torch punya requires_grad :", t.requires_grad)

print()
t_dari_arr = torch.from_numpy(arr)
arr[0, 0] = 99.0
print("from_numpy berbagi memori  -> t_dari_arr[0, 0] =", t_dari_arr[0, 0].item())

t_numpy = t.numpy()
t_numpy[1, 2] = -7.0
print("t.numpy() berbagi memori   -> t[1, 2]         =", t[1, 2].item())

t_salinan = torch.tensor(arr)
arr[0, 0] = 1.0
print("torch.tensor(arr) menyalin -> t_salinan[0, 0]  =", t_salinan[0, 0].item())

Output yang Dihasilkan:

text
NumPy : shape (2, 3) | dtype float64
Torch : shape (2, 3) | dtype torch.float32 | device cpu
Torch punya requires_grad : False

from_numpy berbagi memori  -> t_dari_arr[0, 0] = 99.0
t.numpy() berbagi memori   -> t[1, 2]         = -7.0
torch.tensor(arr) menyalin -> t_salinan[0, 0]  = 99.0

Mari kita telaah kode di atas baris per baris:

  1. Baris 8-9 (dua pembuatan): np.array menyimpulkan dtype float64 (presisi ganda), sedangkan torch.tensor memilih float32 — pilihan yang lebih hemat memori dan menjadi standar pelatihan model. Perbedaan default ini penting diingat saat memindahkan data lintas pustaka.
  2. Baris 11-13 (atribut): tensor menampilkan dua atribut tambahan dibanding ndarray: device tempat datanya berada dan requires_grad yang saat ini False.
  3. Baris 16-18 (torch.from_numpy): tensor hasil from_numpy berbagi blok memori dengan arr, terbukti dari perubahan arr[0, 0] yang langsung terlihat pada tensor tanpa penyalinan apa pun.
  4. Baris 20-22 (t.numpy()): arah sebaliknya juga berbagi memori — tensor t dan tampilan NumPy-nya menunjuk data yang sama, sehingga penulisan t_numpy[1, 2] mengubah t juga.
  5. Baris 24-26 (torch.tensor(arr)): berbeda dari from_numpy, konstruktor torch.tensor selalu menyalin data; setelah arr[0, 0] diganti menjadi 1.0, salinan tetap menyimpan 99.0.

Dokumentasi lengkap tipe tensor tersedia di docs.pytorch.org/docs/stable/tensors.html . Kini kita mengenal tensor sebagai wadah datanya; langkah berikutnya adalah membaca dan mengubah bentuk wadah tersebut — shape, dim, dan operasi penyusunan ulangnya dibahas pada Chapter berikutnya.