Model deep learning memproses data dalam bentuk array angka, dan NumPy adalah pustaka Python yang paling banyak dipakai untuk mengelolanya. Baik PyTorch maupun TensorFlow meniru cara kerja NumPy, dari nama fungsi sampai aturan bentuk array. Menguasai NumPy membantu kita memahami cara framework menyimpan data, menghitung statistik batch, dan membaca pesan galat tentang shape. Chapter ini membahas pembuatan array, atribut dasar shape, dtype, dan ndim, lalu membandingkan performa list Python dengan ndarray.
Dari List Python ke ndarray #
List Python bersifat fleksibel: satu list boleh berisi angka, teks, bahkan list lain. Fleksibilitas tersebut membuat setiap elemen disimpan sebagai objek Python lengkap yang tersebar di memori dan harus diproses satu per satu — lambat dan boros memori saat data berukuran besar.
Class ndarray dari NumPy menyimpan data secara berbeda: seluruh elemen menempati satu blok memori berdampingan, seluruh elemen wajib bertipe sama (dtype), dan operasi aritmetika dijalankan oleh kode C yang sudah dikompilasi. Desain inilah yang menjadikan NumPy fondasi komputasi ilmiah di Python.
Membuat dan Membaca Array #
Kita mulai dari bentuk paling dasar: membuat array dari list Python lalu memeriksa tiga atribut utamanya.
import numpy as np
# Membuat ndarray dari list Python
vektor = np.array([1.0, 2.0, 3.0])
matriks = np.array([[1, 2, 3], [4, 5, 6]])
print("vektor :", vektor)
print("matriks:\n", matriks)
# Tiga atribut paling sering diperiksa
print("shape vektor :", vektor.shape)
print("dtype vektor :", vektor.dtype)
print("ndim vektor :", vektor.ndim)
print("shape matriks :", matriks.shape)
print("dtype matriks :", matriks.dtype)
# float32: dtype standar deep learning
fitur = np.array([1.0, 2.0, 3.0], dtype=np.float32)
print("dtype float32 :", fitur.dtype)
print("itemsize :", fitur.itemsize, "byte per elemen")
# Fungsi pembuatan array yang paling sering dipakai
print("zeros :\n", np.zeros((2, 3)))
print("ones :", np.ones(4))
print("arange :", np.arange(0, 10, 2))
print("linspace :", np.linspace(0.0, 1.0, 5))Output yang Dihasilkan:
vektor : [1. 2. 3.]
matriks:
[[1 2 3]
[4 5 6]]
shape vektor : (3,)
dtype vektor : float64
ndim vektor : 1
shape matriks : (2, 3)
dtype matriks : int64
dtype float32 : float32
itemsize : 4 byte per elemen
zeros :
[[0. 0. 0.]
[0. 0. 0.]]
ones : [1. 1. 1. 1.]
arange : [0 2 4 6 8]
linspace : [0. 0.25 0.5 0.75 1. ]Mari kita telaah kode di atas baris per baris:
- Baris 5 (
vektor = np.array([1.0, 2.0, 3.0])): fungsinp.arraymengubah list Python menjadi ndarray. NumPy menebak tipe data dari isi list; angka desimal menghasilkanfloat64. - Baris 6 (
matriks = np.array([[1, 2, 3], [4, 5, 6]])): list bersarang dua tingkat menjadi array dua dimensi. Angka bulat menghasilkandtypeint64. - Baris 11-15 (
print("shape ...")): atributshapemelaporkan ukuran per dimensi,dtypetipe elemen, danndimjumlah dimensi. Vektor satu dimensi ber-shape(3,)— koma menandakan tuple satu elemen. - Baris 18 (
fitur = np.array(..., dtype=np.float32)): parameterdtypememaksa tipe data tertentu. Nilaifloat32hanya memakai 4 byte per elemen (itemsize), setengah darifloat64. - Baris 23-26:
np.zerosmembuat array nol,np.onesmembuat array berisi satu,np.arange(0, 10, 2)membuat nilai berjarak tetap, dannp.linspace(0.0, 1.0, 5)membuat 5 nilai berjarak rata dari 0.0 sampai 1.0.
Batch Fitur dalam Bentuk Array #
Kerangka data paling umum di deep learning adalah batch: baris array mewakili contoh data dan kolom mewakili fitur. Berkas batch-fitur.py menunjukkan pola tersebut pada batch 4x3.
import numpy as np
np.random.seed(42)
# Satu batch berisi 4 contoh data, tiap contoh punya 3 fitur
X = np.random.rand(4, 3).astype(np.float32)
print("X:")
print(X)
print("shape :", X.shape) # (jumlah contoh, jumlah fitur)
print("dtype :", X.dtype)
print("ndim :", X.ndim)
# Satu baris = satu contoh data
contoh_pertama = X[0]
print("contoh pertama :", contoh_pertama, "| shape:", contoh_pertama.shape)
# Satu kolom = nilai satu fitur di seluruh contoh
fitur_kedua = X[:, 1]
print("fitur kedua :", fitur_kedua, "| shape:", fitur_kedua.shape)
# Statistik per fitur tanpa perulangan manual
print("rata-rata per fitur :", X.mean(axis=0))
print("nilai maksimum :", X.max(axis=0))Output yang Dihasilkan:
X:
[[0.37454012 0.9507143 0.7319939 ]
[0.5986585 0.15601864 0.15599452]
[0.05808361 0.8661761 0.601115 ]
[0.7080726 0.02058449 0.96990985]]
shape : (4, 3)
dtype : float32
ndim : 2
contoh pertama : [0.37454012 0.9507143 0.7319939 ] | shape: (3,)
fitur kedua : [0.9507143 0.15601864 0.8661761 0.02058449] | shape: (4,)
rata-rata per fitur : [0.4348387 0.4983734 0.6147533]
nilai maksimum : [0.7080726 0.9507143 0.96990985]Mari kita telaah kode di atas baris per baris:
- Baris 4 (
np.random.seed(42)): generator pseudorandom NumPy menghasilkan urutan sama setiap eksekusi bila seed ditetapkan, sehingga contoh ini deterministik. - Baris 7 (
X = np.random.rand(4, 3).astype(np.float32)):np.random.rand(4, 3)membuat array 4x3 berisi nilai acak [0, 1), lalu.astype(np.float32)mengubah tipenya. - Baris 15 (
contoh_pertama = X[0]): indeks satu angka mengambil satu baris, yaitu satu contoh data dengan 3 fitur — bentuknya menjadi(3,). - Baris 19 (
fitur_kedua = X[:, 1]): titik dua memilih seluruh baris, angka1memilih kolom kedua — hasilnya nilai fitur kedua dari keempat contoh. - Baris 23-24 (
X.mean(axis=0)): parameteraxis=0menyuruh NumPy menghitung statistik menuruni baris, menghasilkan satu nilai per fitur tanpa perulangan manual.
List Python vs ndarray: Memori dan Kecepatan #
List Python dan ndarray tampak mirip sampai kita mengolah satu juta elemen. Berkas list-vs-ndarray.py menyimpan data yang sama di kedua wadah, lalu mengukur pemakaian memori dan waktu penjumlahan seluruh elemen.
import sys
import time
import numpy as np
np.random.seed(42)
N = 1_000_000
# Data yang sama disimpan di dua wadah berbeda
data_numpy = np.random.rand(N)
data_list = data_numpy.tolist()
# --- Perbandingan memori ---
memori_list = sys.getsizeof(data_list) + N * sys.getsizeof(data_list[0])
memori_numpy = data_numpy.nbytes
print(f"memori list Python : {memori_list / 1e6:.1f} MB")
print(f"memori ndarray : {memori_numpy / 1e6:.1f} MB")
print(f"rasio : {memori_list / memori_numpy:.1f}x lebih besar")
# --- Perbandingan kecepatan penjumlahan ---
mulai = time.perf_counter()
total_loop = 0.0
for nilai in data_list:
total_loop += nilai
waktu_loop = time.perf_counter() - mulai
mulai = time.perf_counter()
total_numpy = float(np.sum(data_numpy))
waktu_numpy = time.perf_counter() - mulai
print(f"waktu perulangan Python : {waktu_loop:.4f} detik")
print(f"waktu np.sum : {waktu_numpy:.4f} detik")
print(f"percepatan : {waktu_loop / waktu_numpy:.0f}x")
print("hasil penjumlahan sama :", np.isclose(total_loop, total_numpy))Output yang Dihasilkan:
memori list Python : 32.0 MB
memori ndarray : 8.0 MB
rasio : 4.0x lebih besar
waktu perulangan Python : 0.0782 detik
waktu np.sum : 0.0007 detik
percepatan : 108x
hasil penjumlahan sama : TrueMari kita telaah kode di atas baris per baris:
- Baris 15-16 (
data_numpy = np.random.rand(N)…): satu juta nilai acak disimpan sebagai ndarrayfloat64, lalu.tolist()menyalinnya sebagai list Python agar keduanya terbandingkan adil. - Baris 19-20 (
sys.getsizeof ...): memori list dihitung dari ukuran wadah list ditambah ukuran setiap objekfloat(24 byte per objek); memori ndarray cukup dibaca dari atributnbytes— 8 byte per elemenfloat64karena seluruh elemen berdampingan. - Baris 25-33 (
for nilai in data_list:dannp.sum): perulangan Python menjumlahkan per elemen — setiap iterasi membaca satu objekfloatdan mengikat hasil baru.np.summenjumlahkan seluruh elemen dalam satu panggilan kode C tanpa perulangan Python, sehingga jauh lebih cepat. - Baris 38 (
np.isclose(...)): hasil kedua cara diperiksa dengan toleransi numerik, bukan operator==, karena penjumlahan pecahan biner bisa berbeda di digit-digit terakhir.
Angka waktu di atas diukur sekali dengan time.perf_counter() pada satu mesin, jadi nilai pastinya berbeda pada komputer Anda — namun polanya konsisten: ndarray jauh lebih ringan dan lebih cepat, dan itulah alasan framework deep learning membangun perhitungan di atas operasi array, bukan perulangan Python.
Fungsi Pembuatan Array untuk Deep Learning #
Tabel berikut merangkum fungsi pembuatan array yang paling sering muncul di kode deep learning:
| Fungsi | Contoh | Kegunaan umum di deep learning |
|---|---|---|
np.array(data, dtype=...) | np.array([[1.0], [2.0]], dtype=np.float32) | Mengubah dataset manual menjadi array siap latih |
np.zeros(shape) | np.zeros((128, 10)) | Menampung hasil prediksi atau akumulasi gradien |
np.ones(shape) | np.ones(3) | Nilai awal bias dan tensor konstanta |
np.arange(...) | np.arange(5) | Urutan indeks, misalnya penomoran epoch |
np.linspace(...) | np.linspace(0.0, 1.0, 5) | Titik ambang dan sumbu kurva evaluasi |
np.random.rand(...) | np.random.rand(4, 3) | Data sintetis untuk menguji bentuk kode |
np.random.randn(...) | np.random.randn(100) | Data berdistribusi normal, menyerupai inisialisasi bobot |
Dokumentasi resmi NumPy memuat daftar lengkap fungsi pembuatan array di numpy.org/doc/stable/reference/routines.array-creation dan penjelasan atribut ndarray di numpy.org/doc/stable/reference/arrays.ndarray .
Sejauh ini kita memproses array yang bentuknya sudah sama. Pertanyaan berikutnya: apa yang terjadi ketika NumPy menjumlahkan dua array berbentuk berbeda, misalnya vektor dengan matriks? Jawabannya adalah aturan broadcasting — bahan Chapter berikutnya.