DataLens

Operasi tensor dan broadcasting

Lakukan perhitungan element-wise, perkalian matriks, dan reduksi sepanjang dimensi pada tensor, dengan aturan broadcasting yang sama seperti NumPy dan beberapa kebiasaan khas PyTorch.

Level: Dasar · 7 menit baca

Latihan modul ini

Soal-soal untuk pelajaran ini berjalan di browser-mu dan langsung mengecek jawabanmu.

Idenya

Neural network sebagian besar terdiri dari tiga operasi yang diulang berkali-kali: perkalian matriks, fungsi element-wise, dan reduksi (jumlah, rata-rata). Kamu sudah mengenal ketiganya dari NumPy. Modul ini memetakannya ke PyTorch dan menunjukkan segelintir perbedaan yang sering menjebak.

Perhitungan element-wise

Perhitungan tensor terlihat persis seperti NumPy. Harga dikali unit menghasilkan revenue per produk, dan mengalikan dengan 1,11 menambahkan PPN ke setiap harga sekaligus:

import torch

prices = torch.tensor([185.0, 320.0, 95.0])
units = torch.tensor([9.0, 10.0, 12.0])
print(prices * units)
print(prices * 1.11)
print(torch.sqrt(units), units.exp().round())
tensor([1665., 3200., 1140.])
tensor([205.3500, 355.2000, 105.4500])
tensor([3.0000, 3.1623, 3.4641]) tensor([  8103.,  22026., 162755.])

Operator bekerja elemen demi elemen, dan sebagian besar fungsi NumPy punya kembaran di PyTorch (torch.sqrt, torch.exp, torch.log, torch.abs, torch.clamp), biasanya juga tersedia sebagai method (units.exp()).

Perkalian matriks

Operasi yang menjadi dasar jaringan saraf adalah perkalian matriks. Kamu sudah melihatnya dengan data toko: setiap baris jumlah pesanan dikali daftar harga menghasilkan total pesanan itu. Cara kerjanya sama di PyTorch:

order_qty = torch.tensor([[2.0, 1.0, 3.0],
                          [0.0, 2.0, 0.0]])
price_vec = torch.tensor([95.0, 320.0, 55.0])
print(order_qty @ price_vec)
print(torch.matmul(order_qty, price_vec))
tensor([675., 640.])
tensor([675., 640.])

@ adalah operator yang sama seperti di modul aljabar linear NumPy, dengan aturan shape yang sama: (n, k) @ (k, m) → (n, m). Sebuah layer neural network persis X @ W.T + b, seperti yang akan kamu lihat di materi nn.Module.

Reduksi sepanjang dimensi

PyTorch menyebut axis sebagai dimensi (dim alih-alih axis), tetapi aturannya sama: dimensi yang kamu sebut akan hilang.

units = torch.tensor([[120.0, 135.0, 150.0],
                      [ 80.0,  85.0,  90.0]])      # stores × months
print(units.sum())
print(units.sum(dim=0))         # per month
print(units.mean(dim=1))        # per store
print(units.max(dim=1))
tensor(660.)
tensor([200., 220., 240.])
tensor([135.,  85.])
torch.return_types.max(
values=tensor([150.,  90.]),
indices=tensor([2, 2]))

Perhatikan max(dim=...): ia mengembalikan sekaligus nilai maksimum dan posisinya (indices), seperti max dan argmax NumPy dalam satu panggilan. Gunakan .values dan .indices, atau unpack: best, where = units.max(dim=1).

keepdim=True mempertahankan dimensi yang direduksi dengan ukuran 1, siap untuk broadcasting:

share = units / units.sum(dim=1, keepdim=True)
print(share.round(decimals=3))
tensor([[0.2960, 0.3330, 0.3700],
        [0.3140, 0.3330, 0.3530]])

Broadcasting

Aturannya identik dengan NumPy: bandingkan shape dari kanan; ukurannya harus sama atau bernilai 1.

targets = torch.tensor([[130.0], [85.0]])      # one target per store: shape (2, 1)
print(units - targets)
monthly_price = torch.tensor([95.0, 100.0, 105.0])  # one price per month: shape (3,)
print(units * monthly_price)
tensor([[-10.,   5.,  20.],
        [ -5.,   0.,   5.]])
tensor([[11400., 13500., 15750.],
        [ 7600.,  8500.,  9450.]])

Operasi in-place

Method yang diakhiri garis bawah mengubah tensor in place (langsung di tempat):

w = torch.tensor([1.0, 2.0, 3.0])
w.add_(10)
print(w)
w.mul_(0.5)
print(w)
tensor([11., 12., 13.])
tensor([5.5000, 6.0000, 6.5000])

w.add_(10) mengubah w; w.add(10) (atau w + 10) mengembalikan tensor baru. Optimizer memperbarui bobot secara in-place dengan cara ini. Di kodemu sendiri, utamakan versi tanpa garis bawah kecuali ada alasannya: lebih aman (tidak ada perubahan mengejutkan pada tensor yang dipakai bersama) dan cocok dengan autograd.

Perbandingan dan mask

Memilih nilai berdasarkan kondisi, seperti hari-hari ramai dengan lebih dari 60 order, juga bekerja persis seperti di NumPy:

daily = torch.tensor([42, 38, 51, 47, 60, 75, 68])
busy = daily > 60
print(busy)
print(daily[busy], busy.sum().item(), busy.float().mean().item())
print(torch.where(busy, daily, torch.zeros_like(daily)))
tensor([False, False, False, False, False,  True,  True])
tensor([75, 68]) 2 0.2857142984867096
tensor([ 0,  0,  0,  0,  0, 75, 68])

Mask boolean, torch.where, dan .sum() dari sebuah mask semuanya berperilaku seperti versi NumPy-nya. Satu perbedaan: tensor boolean harus dikonversi (.float()) sebelum diambil rata-ratanya.

Ide utama

Kalau kamu bisa melakukannya di NumPy, hampir pasti kamu bisa melakukannya di PyTorch dengan logika shape yang sama. Perbedaannya ada di nama (dim vs axis), max yang mengembalikan nilai dan indeks, default float32, dan method bergaris bawah untuk perubahan in-place.

Mengapa ini penting untuk kode yang bersih

Menulis kode model sebagai operasi atas seluruh tensor, alih-alih loop Python atas setiap contoh, adalah yang membuatnya cepat di GPU, dan menjaga kodenya dekat dengan rumus matematika di atas kertas: logits = x @ W.T + b alih-alih tiga loop bersarang. Kebiasaan vektorisasi dari track NumPy berlaku langsung.

Rangkuman

Latihan modul ini

Soal-soal untuk pelajaran ini berjalan di browser-mu dan langsung mengecek jawabanmu.

Berikutnya: NumPy ↔ tensor; device (CPU/GPU) →