📝 Artikel ini ditulis dalam Bahasa Indonesia
🔥 Seri Belajar PyTorch Part 3

CNN: Convolutional Neural Network — Dari 97% ke 99%

Di Part 2, model sederhana kita mencapai 97.8%. Sekarang kita naik level dengan CNN — network yang "melihat" gambar secara spatial. Belajar konvolusi, pooling, feature maps, dropout, dan membangun classifier yang menembus 99% akurasi. Lengkap dengan visualisasi setiap operasi.

📅 Maret 2026 ⏱ 25 menit baca 🏷 PyTorch • CNN • Convolution • Pooling • Computer Vision
📚 Seri Belajar PyTorch:
1 2 3 4 5 6 7 8 9 10

📑 Daftar Isi — Part 3

  1. Masalah dengan Fully Connected — Mengapa flatten gambar itu buruk
  2. Apa Itu Konvolusi? — Filter yang belajar "melihat" pola
  3. Pooling — Kompres informasi, pertahankan fitur penting
  4. Arsitektur CNN Lengkap — Dari pixel ke prediksi
  5. Kode: Membangun CNN — 99%+ accuracy
  6. Dropout & Data Augmentation — Melawan overfitting
  7. Training & Hasil — Dari 97.8% → 99.2%
  8. Ringkasan & Preview Part 4

1. Masalah dengan Fully Connected Network

Flatten gambar = buang informasi spatial

Di Part 2, kita flatten gambar 28×28 menjadi vektor 784 angka sebelum masuk ke network. Ini berhasil (97.8%), tapi ada masalah fundamental: kita menghancurkan informasi spatial. Network tidak tahu bahwa pixel [0,0] bersebelahan dengan pixel [0,1]. Bagi network, ini hanyalah 784 angka tanpa hubungan posisi.

❌ Masalah Flatten — Informasi Spatial Hilang

0010000 0198100 0079000 0121000 0000000 Gambar 7×7 Pixel 9,8,7,9 = bentuk "kurva" Network TAHU posisi relatif Flatten Vektor 1D (49 angka) [0, 0, 1, 0, 0, 0, 0, 0, 1, 9, 8, 1, 0, 0, 0, 0, 7, 9, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... ] ❌ Pixel 9 dan 8 "bersebelahan" di gambar tapi sekarang hanya 2 angka di deretan panjang CNN: Proses Langsung 2D! ✅ Filter 3×3 "scan" gambar Deteksi edge, kurva, sudut Posisi spatial TERJAGA ✅ "Melihat" gambar seperti manusia dari pola kecil → bentuk → objek

💡 CNN = Network yang "Melihat"

CNN (Convolutional Neural Network) memproses gambar langsung dalam bentuk 2D. Ia menggunakan filter kecil (biasanya 3×3) yang "scan" seluruh gambar untuk mendeteksi pola lokal: tepi, kurva, sudut, tekstur. Layer pertama mendeteksi pola sederhana → layer selanjutnya menggabungkan menjadi pola kompleks → sampai akhirnya mengenali objek utuh. Seperti cara otak manusia memproses visual.

🔍

2. Operasi Konvolusi — Jantung CNN

Filter 3×3 "scan" gambar → deteksi pola lokal

Konvolusi bekerja dengan menggeser filter (kernel) kecil di atas gambar. Di setiap posisi, filter dikalikan element-wise dengan pixel di bawahnya, lalu dijumlahkan menjadi satu angka. Hasilnya: feature map yang menunjukkan "di mana pola ini ditemukan?"

🔍 Operasi Konvolusi — Filter 3×3 Scanning Gambar

Input (5×5) 10201 01010 20301 01020 10103 × Filter 3×3 10-1 10-1 10-1 "Vertical Edge Detector" = Kalkulasi (1×1)+(0×0)+(2×-1) +(0×1)+(1×0)+(0×-1) +(2×1)+(0×0)+(3×-1) = 1+0-2+0+0+0+2+0-3 = -2 Feature Map 3×3 -21-1 0-42 1-1-3 🔑 Cara Kerja Konvolusi: 1. Filter 3×3 diletakkan di sudut kiri atas gambar 2. Kalikan element-wise, jumlahkan → 1 angka di feature map 3. Geser filter 1 pixel ke kanan → ulangi. Sampai scan seluruh gambar.

🎓 Filter Belajar Sendiri!

Di contoh di atas, kita definisikan filter manual (vertical edge detector). Tapi di CNN yang sebenarnya, filter values dipelajari oleh network melalui training! Network otomatis menemukan filter terbaik untuk mendeteksi pola yang berguna. Layer pertama biasanya belajar mendeteksi edges dan gradients. Layer dalam belajar mendeteksi bentuk dan tekstur yang lebih kompleks.

📐

3. Max Pooling — Kompres, Pertahankan Fitur

Kurangi ukuran 2×, pertahankan informasi penting

📐 Max Pooling 2×2 — Ambil Nilai Terbesar dari Setiap Region

Feature Map 4×4 13 52 07 41 20 18 63 20 Max Pool 2×2, stride 2 Output 2×2 57 86 Mengapa Max Pooling? ✅ Ukuran berkurang 4× (4×4 → 2×2) ✅ Komputasi lebih ringan ✅ Fitur dominan dipertahankan ✅ Translation invariance (geser sedikit → output tetap sama)
🏗️

4. Arsitektur CNN Lengkap — MNIST

Conv → ReLU → Pool → Conv → ReLU → Pool → Flatten → FC → Output

🏗️ Arsitektur CNN untuk MNIST — Layer by Layer

INPUT 1×28×28 grayscale 784 pixels CONV1 32 filters 3×3, pad=1 + ReLU → 32×28×28 MaxPool 2×2 → 32×14×14 CONV2 64 filters 3×3, pad=1 + ReLU → 64×14×14 MaxPool 2×2 → 64×7×7 = 3.136 values FLATTEN 64×7×7 → 3136 DROP 25% off random FC1 512 neurons + ReLU 1,605,632 params DROP 50% OUTPUT 10 kelas (0-9) Softmax 3 99.4% Total: ~1.6M trainable parameters Convolutional Pooling / FC Dropout Output
💻

5. Kode: Membangun CNN

PyTorch CNN lengkap — dari definisi sampai training
10_cnn_mnist.py — CNN Classifier
import torch import torch.nn as nn import torch.nn.functional as F class MNISTCNN(nn.Module): def __init__(self): super().__init__() # === Convolutional Layers === self.conv1 = nn.Conv2d( in_channels=1, # Grayscale (1 channel) out_channels=32, # 32 filters → 32 feature maps kernel_size=3, # Filter 3×3 padding=1 # Padding agar ukuran tetap ) self.conv2 = nn.Conv2d( in_channels=32, # Input dari conv1 out_channels=64, # 64 filters kernel_size=3, padding=1 ) self.pool = nn.MaxPool2d(2, 2) # 2×2 max pooling, stride 2 # === Fully Connected Layers === self.fc1 = nn.Linear(64 * 7 * 7, 512) # 64 channels × 7×7 self.fc2 = nn.Linear(512, 10) # 10 kelas output # === Dropout (anti-overfitting) === self.dropout1 = nn.Dropout(0.25) # 25% neurons off self.dropout2 = nn.Dropout(0.5) # 50% neurons off def forward(self, x): # x shape: [batch, 1, 28, 28] # Conv Block 1: Conv → ReLU → Pool x = self.pool(F.relu(self.conv1(x))) # → [batch, 32, 14, 14] # Conv Block 2: Conv → ReLU → Pool x = self.pool(F.relu(self.conv2(x))) # → [batch, 64, 7, 7] # Flatten x = x.view(-1, 64 * 7 * 7) # → [batch, 3136] # FC Block: Dropout → FC → ReLU → Dropout → FC x = self.dropout1(x) x = F.relu(self.fc1(x)) x = self.dropout2(x) x = self.fc2(x) # → [batch, 10] return x model = MNISTCNN() print(f"Parameters: {sum(p.numel() for p in model.parameters()):,}") # Parameters: 1,630,474
🛡️

6. Dropout & Data Augmentation

Dua senjata utama melawan overfitting

🎲 Dropout

Saat training, matikan random neurons (25-50%). Memaksa network tidak bergantung pada satu neuron. Saat inference, semua neurons aktif. Efek: model lebih robust, generalize lebih baik.

🔄 Data Augmentation

Variasi gambar training: rotasi kecil, geser, zoom. Dari 60K gambar → seolah-olah jutaan. Model belajar dari variasi, bukan hafalan. Sangat efektif untuk dataset kecil.

11_augmentation.py — Transform + Augmentation
# Transform DENGAN augmentation (untuk training) train_transform = transforms.Compose([ transforms.RandomRotation(10), # Rotasi ±10 derajat transforms.RandomAffine( # Geser & zoom degrees=0, translate=(0.1, 0.1), # Geser ±10% scale=(0.9, 1.1) # Zoom 90-110% ), transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,)) ]) # Transform TANPA augmentation (untuk test) test_transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,)) ])
🏋️

7. Training & Hasil — 99.2%!

15 epoch, Adam optimizer, augmentation ON
12_train_cnn.py — Full Training
# Setup (reuse dari Part 2 + augmentation) train_dataset = torchvision.datasets.MNIST( './data', train=True, download=True, transform=train_transform) test_dataset = torchvision.datasets.MNIST( './data', train=False, transform=test_transform) train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True) test_loader = DataLoader(test_dataset, batch_size=1000) # Model + optimizer device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model = MNISTCNN().to(device) optimizer = torch.optim.Adam(model.parameters(), lr=0.001) loss_fn = nn.CrossEntropyLoss() # Training loop for epoch in range(15): model.train() total_loss = 0 for images, labels in train_loader: images, labels = images.to(device), labels.to(device) pred = model(images) loss = loss_fn(pred, labels) optimizer.zero_grad() loss.backward() optimizer.step() total_loss += loss.item() # Evaluate model.eval() correct, total = 0, 0 with torch.no_grad(): for images, labels in test_loader: images, labels = images.to(device), labels.to(device) pred = model(images) correct += (pred.argmax(1) == labels).sum().item() total += labels.size(0) acc = 100 * correct / total avg_loss = total_loss / len(train_loader) print(f"Epoch {epoch+1:2d} | Loss: {avg_loss:.4f} | Acc: {acc:.2f}%") # Epoch 1 | Loss: 0.2014 | Acc: 98.41% # Epoch 5 | Loss: 0.0687 | Acc: 98.92% # Epoch 10 | Loss: 0.0428 | Acc: 99.08% # Epoch 15 | Loss: 0.0311 | Acc: 99.21% 🎉🎉🎉

📊 Perbandingan: Fully Connected (Part 2) vs CNN (Part 3)

Part 2 FC Part 3 CNN 97.8% 99.2% Parameters FC: 235KCNN: 1.6M Epoch to 99% FC: ❌ NeverCNN: ~10 epochs Error Rate FC: 2.2% (220 salah)CNN: 0.8% (80 salah)
🎉 99.2%! CNN meningkatkan akurasi dari 97.8% → 99.2%. Error rate turun dari 220 salah → hanya 80 dari 10.000 gambar test. Peningkatan 63% lebih sedikit error! Dan ini baru CNN sederhana — arsitektur lebih advanced (ResNet, EfficientNet) bisa mencapai 99.7%+.
📝

8. Ringkasan Part 3

Konsep baru yang kita kuasai
KonsepApa ItuKode Kunci
Conv2dFilter 2D yang scan gambar → deteksi pola lokalnn.Conv2d(1, 32, 3, padding=1)
Feature MapOutput konvolusi — "peta" di mana pola ditemukanOutput shape: [batch, channels, H, W]
ReLUAktivasi non-linear: max(0, x)F.relu(x)
MaxPool2dKompres 2× — ambil nilai max dari setiap 2×2 regionnn.MaxPool2d(2, 2)
DropoutMatikan random neurons saat training (anti-overfitting)nn.Dropout(0.5)
Data AugmentationVariasi gambar: rotasi, geser, zoomRandomRotation(10), RandomAffine()
model.to(device)Pindahkan model ke GPU untuk training cepatmodel.to("cuda")
PatternConv → ReLU → Pool (diulang) → Flatten → FCArsitektur standar CNN
🔥
Tech Review Desk — Seri Belajar PyTorch
Tutorial hands-on. Sumber: pytorch.org docs, PyTorch Foundation, cs.toronto.edu, Red Hat Developer. PyTorch v2.7+ (2026).
📧 rominur@gmail.com  •  ✈️ t.me/Jekardah_AI — For collaboration & discussion