Kata “deep” di deep learning dulu saya dengar seperti istilah marketing. Ternyata artinya teknis dan sederhana: neural network dengan banyak hidden layer. Sedangkan GPU — awalnya saya kira itu cuma alat para korporat dengan budget besar. Dua asumsi itu saya luruskan di episode ini, termasuk pengalaman nyata belajar deep learning tanpa punya GPU sendiri.
Kenapa Namanya “Deep”
Yang membuat banyak layer spesial bukan sekadar jumlah parameternya, tapi hierarki abstraksi yang terbentuk. Pada model visi, layer awal belajar mendeteksi pola elementer seperti garis dan tepi. Layer tengah menggabungkannya jadi pola menengah seperti sudut dan tekstur. Layer dalam menggabungkan lagi jadi konsep tingkat tinggi seperti wajah atau objek. Setiap layer membangun di atas abstraksi layer sebelumnya.
Sebagai programmer, saya menyebutnya seperti arsitektur software yang sehat: helper functions kecil dirakit jadi modul, modul dirakit jadi service, service dirakit jadi sistem. Anda tidak menulis satu fungsi seribu baris untuk semuanya — dan deep network tidak mempelajari konsep mentah langsung dari piksel. Kedalaman memberi ruang bagi abstraksi bertingkat itu.
Kenapa Butuh GPU
Inti komputasi training adalah perkalian matriks raksasa, diulang jutaan kali. Kabar baiknya: operasi-operasi di dalam perkalian matriks saling independen — elemen hasil satu tidak menunggu elemen hasil lain. Ini pekerjaan yang bisa diparalelkan habis-habisan.
CPU dan GPU menjawab tantangan ini dengan filosofi berbeda. CPU punya segelintir core yang besar dan pintar, dioptimalkan untuk logika bercabang dan operasi serial. GPU punya ribuan core kecil dan sederhana, dioptimalkan untuk melakukan operasi identik atas data masif secara serentak. Training neural network hampir seluruhnya tipe kerja kedua, jadi GPU bisa puluhan kali lebih cepat — dan kecepatan itu bukan kemewahan, tapi syarat agar siklus eksperimen tidak memakan hari.
| Aspek | CPU | GPU |
|---|---|---|
| Jumlah core | Sedikit, besar, pintar | Ribuan, kecil, sederhana |
| Gaya kerja | Serial, logika kompleks | Paralel masif, operasi seragam |
| Cocok untuk | Web server, scripting, logika bisnis | Perkalian matriks, grafis, training model |
| Analogi | Empat senior engineer | Seribu intern yang disiplin |
Mencoba Sendiri di PyTorch
import time
import torch
device = "cuda" if torch.cuda.is_available() else "cpu"
print("device:", device)
a = torch.randn(2048, 2048, device=device)
b = torch.randn(2048, 2048, device=device)
start = time.time()
c = a @ b
if device == "cuda":
torch.cuda.synchronize() # pastikan komputasi benar-benar selesai
print("waktu matmul:", round(time.time() - start, 4), "detik")Jalankan skrip ini di laptop tanpa GPU lalu di Colab dengan GPU, dan perbedaannya tidak butuh penjelasan lagi. Satu catatan penting dari pengalaman sendiri: pemindahan data antara CPU dan GPU itu mahal. Pola yang benar adalah mengirim data ke device sekali di awal, mengolah semuanya di sana, lalu mengambil hasilnya di akhir — bukan bolak-balik di setiap langkah.
CNN vs RNN vs Transformer: Arsitektur Mana yang Kapan?
Saat memulai deep learning, pertanyaan yang sering muncul di kepala saya: “Model apa yang harus saya pakai?” Ternyata ada pola sederhana untuk memilih berdasarkan tipe data.
| Arsitektur | Cocok untuk | Kelebihan | Kekurangan |
|---|---|---|---|
| CNN (Convolutional Neural Network) | Gambar, video, data spasial | Efisien menangkap fitur lokal via filter | Kurang bagus untuk data sekuensial panjang |
| RNN / LSTM | Teks, time series, data sekuensial | Memahami konteks urutan | Sulit dilatih pada sekuens panjang, lambat |
| Transformer | Teks, gambar, audio — serbaguna | Paralel penuh, skala besar, state-of-the-art | RAM besar, butuh data banyak |
Sebagai analogi: CNN seperti kamera yang memindai gambar dari kiri ke kanan atas ke bawah, RNN seperti pembaca yang menelan kata satu per satu dari awal kalimat, Transformer seperti seseorang yang langsung melihat seluruh kalimat sekaligus dan memahami konteks setiap kata relatif terhadap yang lain. Pilihan arsitektur menentukan bagaimana Anda mendefinisikan model, memilih loss function, dan merancang pipeline data Anda.
Training Loop Lengkap: Neural Network dari Nol
Bagian yang paling mengubah pemahaman saya tentang deep learning adalah menulis training loop sendiri, bukan sekadar memanggil model.fit(). Berikut contoh neural network sederhana untuk klasifikasi dataset MNIST (digit tulisan tangan):
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
# 1. Definisikan model
class SimpleNet(nn.Module):
def __init__(self):
super().__init__()
self.flatten = nn.Flatten()
self.layers = nn.Sequential(
nn.Linear(28 * 28, 512),
nn.ReLU(),
nn.Linear(512, 256),
nn.ReLU(),
nn.Linear(256, 10)
)
def forward(self, x):
return self.layers(self.flatten(x))
# 2. Persiapan data
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])
train_ds = datasets.MNIST("./data", train=True, download=True, transform=transform)
train_loader = DataLoader(train_ds, batch_size=64, shuffle=True)
device = "cuda" if torch.cuda.is_available() else "cpu"
model = SimpleNet().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 3. Training loop
for epoch in range(5):
model.train()
total_loss = 0
for batch_x, batch_y in train_loader:
batch_x, batch_y = batch_x.to(device), batch_y.to(device)
optimizer.zero_grad()
output = model(batch_x)
loss = criterion(output, batch_y)
loss.backward() # backpropagation
optimizer.step() # update bobot
total_loss += loss.item()
print(f"Epoch {epoch+1}, Loss: {total_loss / len(train_loader):.4f}")Empat langkah inti di atas — forward pass, hitung loss, backward pass, update optimizer — adalah jantung setiap training deep learning. Begitu Anda memahami pola ini, beralih ke model yang lebih kompleks hanya soal mengganti arsitektur dan data, bukan konsep fundamentalnya.
GPU Memory Management: VRAM Budget dan Batch Size
Salah satu hal yang paling menyebalkan saat training di GPU: pesan CUDA out of memory. Ternyata ini soal matematika sederhana. VRAM GPU harus menampung tiga komponen utama sekaligus:
- Model parameters — bobot dan bias, ukurannya tetap untuk arsitektur tertentu
- Optimizer states — Adam menyimpan dua state per parameter (momentum + variance), jadi memakan 2x lipat dari parameter
- Activations — output per layer yang harus disimpan untuk backpropagation, ukurannya proporsional dengan batch size
Hubungan langsungnya: batch size lebih besar berarti activations lebih besar, berarti lebih banyak VRAM terpakai. Jika VRAM Anda terbatas (misalnya 8 GB di Colab gratis), batch size mungkin harus ditekan ke 16 atau bahkan 8. Ini bukan akhir dunia — gradient accumulation bisa meniru batch besar dengan mengakumulasi gradien dari beberapa batch kecil sebelum melakukan update optimizer.
accumulation_steps = 4 # simulasi batch_size = 64 dengan batch_size=16
optimizer.zero_grad()
for i, (x, y) in enumerate(train_loader):
x, y = x.to(device), y.to(device)
loss = criterion(model(x), y) / accumulation_steps
loss.backward() # gradien terakumulasi
if (i + 1) % accumulation_steps == 0:
optimizer.step() # update bobot di sini
optimizer.zero_grad() # reset gradienCara memantau pemakaian VRAM: jalankan torch.cuda.memory_summary() atau gunakan nvidia-smi di terminal. Jika VRAM mendekati batas, kurangi batch size atau gunakan mixed precision berikut.
Mixed Precision Training (FP16/BF16)
Secara default, PyTorch menggunakan FP32 (32-bit floating point) untuk semua komputasi. Mixed precision training menggunakan FP16 (16-bit) untuk sebagian operasi — menghemat VRAM hampir setengah dan mempercepat komputasi di GPU modern (Volta, Turing, Ampere). Konsepnya sederhana: model dan optimizer tetap dalam FP32, tapi forward/backward pass menggunakan FP16. PyTorch menyediakan torch.cuda.amp untuk ini secara otomatis.
from torch.cuda.amp import autocast, GradScaler
scaler = GradScaler()
for x, y in train_loader:
x, y = x.to(device), y.to(device)
optimizer.zero_grad()
with autocast(): # komputasi otomatis pakai FP16
output = model(x)
loss = criterion(output, y)
scaler.scale(loss).backward() # scale gradien untuk mencegah underflow
scaler.step(optimizer)
scaler.update()Dari pengalaman saya, mixed precision mengurangi pemakaian VRAM sekitar 30-40% dan mempercepat training hampir 2x di GPU yang mendukung Tensor Core (T4, A100). Untuk GPU yang lebih tua, keuntungannya lebih kecil. BF16 lebih stabil dari FP16 untuk angka yang sangat kecil atau sangat besar, tapi hanya tersedia di GPU Ampere ke atas (A100, H100).
Pilihan Cloud GPU: Tabel Perbandingan
Bagi yang tidak punya GPU sendiri (termasuk saya), cloud GPU adalah jalan keluar. Ini perbandingan yang saya susun dari pengalaman mencoba beberapa layanan:
| Layanan | GPU | VRAM | Harga per jam | Catatan |
|---|---|---|---|---|
| Google Colab (gratis) | T4 | 15 GB | Gratis (kuota terbatas) | Koneksi terputus sesekali, bagus untuk eksperimen awal |
| Google Colab Pro | T4 / A100 | 15-40 GB | $10/bulan | Lebih stabil, akses lebih lama |
| Kaggle Notebooks | 2x T4 | 2x 15 GB | Gratis (30 jam/minggu) | GPU ganda gratis, sangat bagus untuk pemula |
| Lambda Labs | A100 / H100 | 40-80 GB | $1.10-$3.29/jam | Performance tinggi, cocok training besar |
| RunPod | A100 / H100 | 40-80 GB | $0.64-$2.89/jam | Fleksibel, ada opsi serverless |
| Vast.ai | Bervariasi | Bervariasi | $0.20-$1.50/jam | Marketplace GPU, harga paling murah tapi kualitas bervariasi |
Saran saya: mulai dari Colab atau Kaggle gratis. Ketika project Anda mulai membutuhkan training lebih dari 30 menit atau model yang lebih besar, baru pertimbangkan layanan berbayar. Jangan tergoda menyewa A100 sebelum yakin pipeline data dan kode sudah benar — membayar GPU mahal untuk debug typo di kode training adalah pengalaman yang tidak ingin diulang.
Transfer Learning: Jangan Mulai dari Nol
Pelajaran terbesar kedua setelah menulis training loop: untuk banyak tugas, Anda tidak perlu melatih model dari nol. Transfer learning adalah konsep mengambil model yang sudah dilatih pada dataset besar (misalnya ImageNet dengan 1 juta gambar) dan mengadaptasinya untuk tugas spesifik Anda. Ini seperti mengambil framework web yang sudah jadi lalu hanya mengubah halaman tertentu, bukan menulis HTTP server sendiri.
import torch
import torch.nn as nn
from torchvision import models
# Muat model pretrained
model = models.resnet18(pretrained=True)
# Bekukan semua layer (feature extractor)
for param in model.parameters():
param.requires_grad = False
# Ganti classifier terakhir untuk tugas Anda
# Misalnya: klasifikasi 5 jenis bunga
model.fc = nn.Linear(model.fc.in_features, 5)
model = model.to(device)
print(f"Parameter yang dilatih: {sum(p.numel() for p in model.parameters() if p.requires_grad):,}")
print(f"Parameter total: {sum(p.numel() for p in model.parameters()):,}")Dengan ResNet18, parameter total sekitar 11 juta tapi yang dilatih hanya beberapa ribu di layer terakhir. Artinya: training lebih cepat, butuh data lebih sedikit, dan hasilnya seringkali lebih bagus daripada melatih dari nol. Saya pribadi menggunakan pendekatan ini untuk klasifikasi gambar di project pertama saya, dan akurasi langsung mencapai 90%+ tanpa ribet.
Batch Normalization dan Layer Normalization
Dua teknik normalisasi yang sering muncul di arsitektur deep learning, dan dulu saya bingung membedakannya:
Batch Normalization (BN) menormalisasi output setiap layer berdasarkan statistik mini-batch saat itu. Artinya, aktivasi satu data bergantung pada data lain dalam batch yang sama. BN sangat efektif untuk CNN dan training konvensional. Kelemahannya: batch size kecil membuat estimasi statistik tidak stabil, dan BN tidak bisa digunakan saat sequence length bervariasi (misalnya NLP).
Layer Normalization (LN) menormalisasi berdasarkan fitur per data individual, tanpa memperhatikan data lain dalam batch. Inilah mengapa LN menjadi standar di Transformer — ia tidak terpengaruh oleh batch size dan berfungsi dengan sequence length bervariasi. Perbedaan sederhana: BN menormalisasi ke “atas” (across batch), LN menormalisakan ke “samping” (across features).
Melawan Overfitting di Deep Learning
Deep learning dengan jutaan parameter sangat rentan overfitting — model menghafal data training tapi gagal pada data baru. Ini tiga teknik pertahanan yang saya gunakan hampir selalu:
Dropout secara acak “mematikan” beberapa neuron saat training (mengatur outputnya ke nol). Efeknya: setiap forward pass menggunakan arsitektur yang sedikit berbeda, memaksa model tidak mengandalkan satu jalur fitur tertentu. Saat inference, dropout dimatikan tapi bobot diskalakan otomatis. Tingkat dropout umum: 0.2-0.5 tergantung ukuran model.
Data augmentation membuat data training palsu dari data asli — memutar gambar, memotong, membalik, mengubah kecerahan. Model belajar fitur yang invarian terhadap transformasi tersebut. Contoh di PyTorch: transforms.RandomHorizontalFlip(), transforms.RandomRotation(15), transforms.ColorJitter(brightness=0.2). Biayanya nol (gratis), tapi dampaknya signifikan.
Weight decay menambahkan penalti ke loss function berdasarkan besar bobot — memaksa model tetap sederhana. Secara teknis, ini L2 regularization: loss + λ * Σ(w²). Di PyTorch, cukup atur weight_decay di optimizer: optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4). Nilai tipikal: 1e-4 hingga 1e-2.
Realita Belajar Tanpa GPU Mahal
Saya tidak punya GPU gaming, apalagi server. Yang saya pakai: Google Colab dan Kaggle Notebooks yang memberi akses GPU gratis dengan kuota harian. Konsekuensinya nyata: VRAM terbatas, jadi batch size harus kecil, dan pesan “CUDA out of memory” menjadi pemandangan rutin. Strategi yang menyelamatkan saya: batch kecil, mixed precision, model yang lebih ringkas, dan disiplin menghapus tensor besar yang tidak dipakai lagi.
Pengalaman pertama saya training model di GPU benar-benar membuka mata. Sebelumnya, model MNIST di CPU butuh hampir 10 menit untuk 5 epoch. Pindah ke Colab dengan T4, waktu yang sama tersisa sekitar 40 detik. Perbedaan itu mengubah cara saya berpikir tentang iterasi — bukan lagi “tunggu model selesai sambil ngopi”, tapi “edit kode, jalankan, lihat hasil, ulangi dalam hitungan menit.” Siklus iterasi yang cepat ini, bukan kecepatan GPU itu sendiri, yang sebenarnya paling berharga untuk belajar. Saya jadi berani mencoba ide-ide gila yang sebelumnya terlalu mahal dari sisi waktu untuk dieksplorasi.
Kapan Deep Learning Justru Berlebihan
Bagian yang jarang dibahas tutorial: deep learning bukan selalu jawaban. Untuk data tabular berukuran kecil-menengah — spreadsheet, log transaksi, data pelanggan — model klasik seperti gradient boosting sering menang dengan biaya jauh lebih murah. Prinsip yang saya pegang sama seperti prinsip ngoding: mulai dari baseline sederhana, naikkan kompleksitas hanya kalau metrik membuktikan perlu. Deep learning adalah palu luar biasa; pastikan masalah Anda memang paku.
Komentar Terbaru