334 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Implementasi CNN pada MNIST dan Perbandingannya dengan MLP
## 1. Deskripsi
Program ini dibuat untuk menyelesaikan **Tugas No. 4: Implementasi CNN** menggunakan dataset **MNIST** dan framework **TensorFlow/Keras**.
Eksperimen bertujuan untuk:
- Membangun model **Convolutional Neural Network (CNN)** sederhana menggunakan `Conv2D` dan `MaxPooling2D` sebelum Dense layers.
- Membandingkan performanya dengan model **MLP terbaik** dari Tugas No. 1 (Model C — 3 hidden layer 256 → 128 → 64).
- Mengukur besar peningkatan (improvement) akurasi yang diperoleh.
- Menjelaskan mengapa CNN lebih efektif untuk data gambar dibandingkan MLP.
## 2. Dataset
Dataset yang digunakan sama dengan Tugas No. 1, yaitu **MNIST**, dataset gambar angka tulisan tangan 0 sampai 9.
Dataset dimuat menggunakan fungsi bawaan Keras:
``` python
keras.datasets.mnist.load_data()
```
Karakteristik dataset:
- 60.000 data training
- 10.000 data testing
- Ukuran gambar: 28 × 28 piksel
- Jumlah kelas: 10
- Kelas: angka 0 sampai 9
## 3. Preprocessing
Perbedaan utama preprocessing CNN dibandingkan MLP terletak pada **bentuk input**.
| Aspek | MLP (Tugas 1) | CNN (Tugas 4) |
|---|---|---|
| Bentuk input | `(N, 784)` — diratakan (flatten) | `(N, 28, 28, 1)` — tetap 2D + channel |
| Normalisasi | 0–255 → 0–1 | 0–255 → 0–1 |
| Struktur spasial | Hilang | Dipertahankan |
MLP meratakan gambar menjadi vektor 784 angka sehingga informasi posisi antar piksel hilang. CNN tetap memproses gambar dalam bentuk 2D aslinya dan hanya menambahkan dimensi channel (grayscale = 1).
``` python
x_train = x_train.astype("float32") / 255.0
x_test = x_test.astype("float32") / 255.0
# CNN membutuhkan dimensi channel
x_train = x_train.reshape(-1, 28, 28, 1)
x_test = x_test.reshape(-1, 28, 28, 1)
```
## 4. Arsitektur Model CNN
``` text
Input (28, 28, 1)
↓
Conv2D (32 filter, 3×3, ReLU) → (26, 26, 32)
↓
MaxPooling2D (2×2) → (13, 13, 32)
↓
Conv2D (64 filter, 3×3, ReLU) → (11, 11, 64)
↓
MaxPooling2D (2×2) → (5, 5, 64)
↓
Flatten → (1600)
↓
Dense (64, ReLU)
↓
Dropout (0.3)
↓
Output (10, Softmax)
```
Kode model:
``` python
model = keras.Sequential([
layers.Input(shape=(28, 28, 1)),
layers.Conv2D(32, (3, 3), activation="relu"),
layers.MaxPooling2D((2, 2)),
layers.Conv2D(64, (3, 3), activation="relu"),
layers.MaxPooling2D((2, 2)),
layers.Flatten(),
layers.Dense(64, activation="relu"),
layers.Dropout(0.3),
layers.Dense(10, activation="softmax"),
])
model.compile(
optimizer="adam",
loss="sparse_categorical_crossentropy",
metrics=["accuracy"],
)
```
### Rincian Jumlah Parameter
| Layer | Output Shape | Parameter |
|---|---|---|
| Conv2D (32) | (26, 26, 32) | 320 |
| MaxPooling2D | (13, 13, 32) | 0 |
| Conv2D (64) | (11, 11, 64) | 18.496 |
| MaxPooling2D | (5, 5, 64) | 0 |
| Flatten | (1600) | 0 |
| Dense (64) | (64) | 102.464 |
| Dropout (0.3) | (64) | 0 |
| Dense (10) | (10) | 650 |
| **Total** | | **121.930** |
Perhatikan bahwa dua layer konvolusi hanya menggunakan **18.816 parameter** untuk seluruh ekstraksi fitur, sedangkan satu Dense layer saja sudah menghabiskan 102.464 parameter. Ini menunjukkan efisiensi *parameter sharing* pada konvolusi.
## 5. Konfigurasi Training
Konfigurasi dibuat identik dengan Tugas No. 1 agar perbandingan adil.
| Parameter | Nilai |
|---|---|
| Optimizer | Adam |
| Loss Function | Sparse Categorical Crossentropy |
| Epochs | 10 |
| Batch Size | 128 |
| Validation Split | 10% |
| Hidden Activation | ReLU |
| Output Activation | Softmax |
| Regularisasi | Dropout (0.3) sebelum output layer |
## 6. Hasil Eksperimen
### 6.1 Progres Training CNN per Epoch
| Epoch | Train Accuracy | Validation Accuracy |
|---|---|---|
| 1 | 90,04% | 98,18% |
| 2 | 96,80% | 98,50% |
| 3 | 97,55% | 98,87% |
| 4 | 98,07% | 98,83% |
| 5 | 98,42% | 99,02% |
| 6 | 98,59% | 98,80% |
| 7 | 98,72% | 98,93% |
| 8 | 98,93% | 99,05% |
| 9 | 98,96% | 99,05% |
| 10 | 99,07% | 99,02% |
Validation accuracy sudah melampaui 98% sejak **epoch pertama** — sesuatu yang tidak pernah dicapai MLP bahkan setelah 10 epoch.
### 6.2 Perbandingan CNN vs MLP
| Model | Arsitektur | Jumlah Parameter | Test Accuracy | Waktu Training/Epoch |
|---|---|---|---|---|
| Model A (MLP) | 64 | 50.890 | 97,06% | 1,22 detik |
| Model B (MLP) | 128 → 64 | 109.386 | 97,24% | 1,29 detik |
| **Model C (MLP terbaik)** | 256 → 128 → 64 | 242.762 | **97,64%** | 2,50 detik |
| **Model CNN** | Conv32 → Pool → Conv64 → Pool → Dense64 | **121.930** | **99,03%** | 16,56 detik |
### 6.3 Besar Improvement
| Metrik | MLP Terbaik | CNN | Perubahan |
|---|---|---|---|
| Test Accuracy | 97,64% | 99,03% | **+1,39 poin persentase** |
| Test Loss | 0,0933 | 0,0297 | **−68,2%** |
| Error Rate | 2,36% | 0,97% | **−58,9% (relatif)** |
| Salah klasifikasi | 236 dari 10.000 | **97 dari 10.000** | 139 gambar lebih sedikit |
| Jumlah Parameter | 242.762 | 121.930 | **−49,8% (separuh lebih sedikit)** |
| Waktu/Epoch | 2,50 detik | 16,56 detik | +562% (lebih lambat) |
**Catatan penting mengenai interpretasi improvement:**
Kenaikan 1,39 poin persentase terlihat kecil, tetapi cara yang lebih tepat membacanya adalah lewat **error rate**. CNN memangkas hampir **59% kesalahan** yang masih dilakukan MLP. Pada skala industri, misalnya sistem pembacaan kode pos otomatis yang memproses 1 juta surat, perbedaan ini berarti sekitar **13.900 surat lebih sedikit yang salah baca**.
## 7. Analisis: Mengapa CNN Lebih Efektif untuk Data Gambar?
### 7.1 Mempertahankan Struktur Spasial
MLP meratakan gambar 28 × 28 menjadi vektor 784 angka. Setelah diratakan, piksel yang secara visual bersebelahan (misalnya piksel baris 1 kolom 28 dan baris 2 kolom 1) menjadi berjauhan, sementara model tidak punya cara mengetahui bahwa keduanya sebenarnya bertetangga. Informasi geometris gambar hilang sebelum training dimulai. CNN memproses gambar dalam bentuk 2D aslinya, sehingga pola lokal seperti tepi, sudut, dan lengkungan angka tetap utuh.
### 7.2 Local Receptive Field dan Parameter Sharing
Setiap filter konvolusi berukuran 3 × 3 hanya melihat area kecil gambar, lalu **digeser ke seluruh permukaan gambar dengan bobot yang sama**. Artinya, satu filter yang belajar mendeteksi garis diagonal dapat menemukan garis diagonal di mana pun posisinya.
Pada MLP, setiap posisi piksel punya bobotnya sendiri-sendiri, sehingga model harus mempelajari pola yang sama berulang kali untuk setiap posisi. Inilah alasan CNN mencapai akurasi lebih tinggi meskipun jumlah parameternya **separuh lebih sedikit** dari MLP terbaik.
### 7.3 Hierarki Fitur Otomatis
CNN membangun pemahaman secara bertingkat, mirip cara kerja sistem visual manusia:
``` text
Conv layer 1 → fitur sederhana: tepi, garis, gradien terang-gelap
↓
Conv layer 2 → kombinasi fitur: lengkungan, sudut, lingkaran kecil
↓
Dense layer → konsep utuh: "ini bentuk angka 8"
```
MLP tidak memiliki hierarki semacam ini karena semua piksel langsung dihubungkan ke semua neuron tanpa tahapan abstraksi spasial.
### 7.4 Translation Invariance melalui MaxPooling
`MaxPooling2D` mengambil nilai maksimum dari setiap area 2 × 2, sehingga pergeseran kecil posisi angka dalam gambar tidak banyak mengubah output. Model menjadi tahan terhadap variasi penulisan, misalnya angka yang ditulis sedikit lebih ke kiri atau lebih ke kanan. Pada MLP, pergeseran satu piksel saja mengubah seluruh vektor input dan dapat mengubah hasil prediksi.
### 7.5 Trade-off yang Perlu Dicatat
CNN unggul dalam akurasi dan efisiensi parameter, tetapi **waktu training per epoch jauh lebih lama** (16,56 detik vs 2,50 detik). Operasi konvolusi secara komputasi lebih mahal dibanding perkalian matriks pada Dense layer, karena filter harus digeser ke setiap posisi gambar. Perlu diingat bahwa pengukuran ini dilakukan pada CPU; pada GPU, selisih waktu ini mengecil drastis karena konvolusi sangat mudah diparalelkan.
## 8. Kesimpulan
1. Model CNN sederhana dengan dua blok `Conv2D` + `MaxPooling2D` berhasil mencapai **test accuracy 99,03%** pada MNIST.
2. Dibandingkan MLP terbaik dari Tugas No. 1 (97,64%), CNN memberikan improvement **+1,39 poin persentase**, atau setara dengan **pengurangan error rate sebesar 58,9%**.
3. CNN mencapai hasil tersebut dengan **jumlah parameter hampir separuh lebih sedikit**, membuktikan bahwa keunggulannya berasal dari *inductive bias* yang sesuai dengan sifat data gambar, bukan sekadar dari kapasitas model yang lebih besar.
4. Keunggulan CNN untuk data gambar berakar pada empat hal: preservasi struktur spasial, parameter sharing, hierarki fitur otomatis, dan translation invariance.
5. Konsekuensinya adalah waktu training per epoch yang lebih lama, sehingga pemilihan arsitektur tetap perlu mempertimbangkan ketersediaan sumber daya komputasi.
## 9. Teknologi
- Python 3.10 – 3.12
- TensorFlow 2.x
- Keras
- NumPy
- Matplotlib (untuk plot learning curve)
- MNIST
- **Visual Studio Code** (editor & runtime lokal)
## 10. Struktur Folder
```text
tugas-mnist/
├── .venv/ # virtual environment (tidak perlu di-commit)
├── task4_cnn.py # program utama CNN
├── README_No4_MNIST_CNN.md # dokumentasi ini
└── requirements.txt
```
Isi `requirements.txt`:
```text
tensorflow>=2.16
numpy
matplotlib
```
## 11. Cara Menjalankan di VS Code
### 11.1 Persiapan Awal (sekali saja)
**1. Install ekstensi yang dibutuhkan**
Buka panel Extensions di VS Code (`Ctrl+Shift+X`), lalu install:
- **Python** (Microsoft)
- **Pylance** (Microsoft)
- **Jupyter** (opsional, jika ingin menjalankan per-cell)
**2. Buka folder proyek**
`File → Open Folder…` lalu pilih folder `tugas-mnist`.
**3. Buat virtual environment**
Buka terminal terintegrasi dengan `` Ctrl+` `` lalu jalankan:
```bash
# Windows
python -m venv .venv
.venv\Scripts\activate
# macOS / Linux
python3 -m venv .venv
source .venv/bin/activate
```
**4. Pilih interpreter di VS Code**
Tekan `Ctrl+Shift+P` → ketik **Python: Select Interpreter** → pilih interpreter yang berada di dalam folder `.venv`. Langkah ini penting agar VS Code menjalankan kode memakai environment yang benar, bukan Python sistem.
**5. Install dependensi**
```bash
pip install -r requirements.txt
```
Catatan: jika pemasangan TensorFlow terasa berat atau tidak memiliki GPU, gunakan versi CPU yang ukurannya lebih ringan:
```bash
pip install tensorflow-cpu numpy matplotlib
```
### 11.2 Menjalankan Program
Ada tiga cara, pilih salah satu:
| Cara | Langkah |
|---|---|
| Tombol Run | Buka `task4_cnn.py`, klik tombol **▶ Run Python File** di kanan atas |
| Terminal | Jalankan `python task4_cnn.py` |
| Debug | Tekan `F5`, pilih konfigurasi **Python File** |
### 11.3 Hal yang Perlu Diperhatikan
**Dataset akan diunduh otomatis pada eksekusi pertama.** `keras.datasets.mnist.load_data()` mengunduh berkas `mnist.npz` (± 11 MB) dan menyimpannya di:
```text
Windows : C:\Users\<nama-user>\.keras\datasets\
macOS/Linux : ~/.keras/datasets/
```
Eksekusi berikutnya akan memakai cache tersebut, jadi tidak perlu koneksi internet lagi. Pastikan koneksi aktif saat menjalankan pertama kali.
**Waktu training di CPU.** Model CNN membutuhkan sekitar **15–20 detik per epoch** di CPU, sehingga total training 10 epoch memakan waktu sekitar **3 menit**. Ini wajar; jangan dikira program macet. Gunakan `verbose=2` agar progres tercetak rapi per epoch di terminal VS Code.
**Peringatan oneDNN/CUDA di awal output.** TensorFlow biasanya mencetak pesan seperti `Could not find cuda drivers` atau `oneDNN custom operations are on`. Pesan ini **normal dan bukan error** — artinya TensorFlow berjalan memakai CPU. Program tetap berjalan dengan benar. Jika ingin menyembunyikannya, tambahkan di baris paling atas program, sebelum `import tensorflow`:
```python
import os
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"
```
**Plot Matplotlib.** Saat dijalankan sebagai file `.py`, jendela plot akan terbuka terpisah dan program berhenti sampai jendela ditutup. Agar plot langsung tersimpan sebagai gambar tanpa mengganggu alur program, gunakan `plt.savefig("nama.png")` alih-alih `plt.show()`.
### 11.4 Langkah Pengerjaan Tugas
1. Jalankan program hingga selesai 10 epoch.
2. Catat **test accuracy**, **jumlah parameter** (dari `model.summary()`), dan **waktu training per epoch**.
3. Bandingkan hasilnya dengan tabel hasil MLP dari Tugas No. 1.
4. Hitung improvement, baik dalam poin persentase maupun pengurangan error rate.
5. Isi tabel pada bagian **Hasil Eksperimen** dengan angka aktual yang Anda peroleh.
Nilai akurasi yang Anda dapatkan mungkin berbeda tipis dari dokumen ini (biasanya di kisaran 98,9% – 99,2%) karena inisialisasi bobot bersifat acak. Untuk hasil yang dapat direproduksi, atur seed di awal program:
```python
import numpy as np, tensorflow as tf
tf.random.set_seed(42)
np.random.seed(42)
```