From 5ac0a227c4680f02cbfc509d4937845b6e8fb3e0 Mon Sep 17 00:00:00 2001 From: matthewflrnt Date: Mon, 21 Sep 2026 09:04:44 +0700 Subject: [PATCH] refactor: re-structure folder --- .gitignore | 15 + .gitignore/Plaintext | 4 - .vscode/settings.json | 3 - README.md | 111 ++++++ docs/PRESENTATION.md | 136 +++++++ docs/model_selection.md | 32 ++ experiments/01_mlp_comparison.py | 99 ++++++ experiments/02_regularization.py | 93 +++++ experiments/03_model_selection.py | 67 ++++ experiments/04_cnn_mnist.py | 148 ++++++++ requirements.txt | 13 + {task4-cnn => results/figures}/hasil_cnn.png | Bin .../figures/loss_regularization.png | Bin .../models}/model_c_regularized.keras | Bin .../models}/model_cnn_mnist.keras | Bin src/__init__.py | 4 + src/data_loader.py | 46 +++ src/models.py | 82 +++++ src/utils.py | 65 ++++ task-2-Regulation/model_c_regularization.py | 123 ------- task1-models/codingan.py | 224 ------------ task3-model-selection/model_selection.md | 23 -- .../model_selection_examples.py | 47 --- task4-cnn/README.md.md | 333 ------------------ task4-cnn/requirements.txt | 3 - task4-cnn/task4_cnn.py | 184 ---------- 26 files changed, 911 insertions(+), 944 deletions(-) create mode 100644 .gitignore delete mode 100644 .gitignore/Plaintext delete mode 100644 .vscode/settings.json create mode 100644 README.md create mode 100644 docs/PRESENTATION.md create mode 100644 docs/model_selection.md create mode 100644 experiments/01_mlp_comparison.py create mode 100644 experiments/02_regularization.py create mode 100644 experiments/03_model_selection.py create mode 100644 experiments/04_cnn_mnist.py create mode 100644 requirements.txt rename {task4-cnn => results/figures}/hasil_cnn.png (100%) rename task-2-Regulation/image.png => results/figures/loss_regularization.png (100%) rename {task-2-Regulation => results/models}/model_c_regularized.keras (100%) rename {task4-cnn => results/models}/model_cnn_mnist.keras (100%) create mode 100644 src/__init__.py create mode 100644 src/data_loader.py create mode 100644 src/models.py create mode 100644 src/utils.py delete mode 100644 task-2-Regulation/model_c_regularization.py delete mode 100644 task1-models/codingan.py delete mode 100644 task3-model-selection/model_selection.md delete mode 100644 task3-model-selection/model_selection_examples.py delete mode 100644 task4-cnn/README.md.md delete mode 100644 task4-cnn/requirements.txt delete mode 100644 task4-cnn/task4_cnn.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea48604 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +# Python +__pycache__/ +*.py[cod] +.venv/ +venv/ + +# Environments & IDEs +.env +.vscode/ +.idea/ +.ipynb_checkpoints/ + +# OS +.DS_Store +Thumbs.db diff --git a/.gitignore/Plaintext b/.gitignore/Plaintext deleted file mode 100644 index 8155565..0000000 --- a/.gitignore/Plaintext +++ /dev/null @@ -1,4 +0,0 @@ -venv/ -__pycache__/ -*.keras -.vscode/ \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 3d084e4..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "python.defaultInterpreterPath": "${workspaceFolder}/.venv/Scripts/python.exe" -} diff --git a/README.md b/README.md new file mode 100644 index 0000000..a88d662 --- /dev/null +++ b/README.md @@ -0,0 +1,111 @@ +# Praktikum Deep Learning - Kelompok 3 + +Repository ini berisi implementasi tugas dan eksperimen Deep Learning, mencakup perbandingan arsitektur Multi-Layer Perceptron (MLP), teknik regularisasi (Batch Normalization & Dropout), studi kasus pemilihan model (*Model Selection*), serta implementasi Convolutional Neural Network (CNN) pada dataset MNIST. + +--- + +## πŸ“ Struktur Folder Proyek + +Struktur direktori telah dirapikan secara modular sebagai berikut: + +```text +kelompok3-deeplearning/ +β”œβ”€β”€ .gitignore # Konfigurasi file & folder yang diabaikan git +β”œβ”€β”€ requirements.txt # Daftar pustaka / dependensi Python +β”œβ”€β”€ README.md # Dokumentasi utama proyek +β”œβ”€β”€ docs/ # Dokumentasi dan analisis tambahan +β”‚ └── model_selection.md # Analisis justifikasi pemilihan model (Tugas 3) +β”œβ”€β”€ src/ # Modul reusable / fungsi pembantu +β”‚ β”œβ”€β”€ __init__.py +β”‚ β”œβ”€β”€ data_loader.py # Loader & preprocessor dataset MNIST (MLP & CNN) +β”‚ β”œβ”€β”€ models.py # Definisi arsitektur model (MLP, Regularized MLP, CNN) +β”‚ └── utils.py # Callback timer, manajemen folder, plotting helper +β”œβ”€β”€ experiments/ # Skrip eksperimen & tugas utama +β”‚ β”œβ”€β”€ 01_mlp_comparison.py # Tugas 1: Perbandingan 3 arsitektur MLP +β”‚ β”œβ”€β”€ 02_regularization.py # Tugas 2: Eksperimen Regularisasi BatchNorm + Dropout +β”‚ β”œβ”€β”€ 03_model_selection.py # Tugas 3: Implementasi contoh arsitektur model +β”‚ └── 04_cnn_mnist.py # Tugas 4: Implementasi CNN MNIST & perbandingan vs MLP +└── results/ # Output dari eksperimen + β”œβ”€β”€ figures/ # Plot visualisasi (akurasi, loss curve, bar chart) + β”‚ β”œβ”€β”€ hasil_cnn.png + β”‚ └── loss_regularization.png + └── models/ # Bobot model terlatih (.keras) + β”œβ”€β”€ model_cnn_mnist.keras + └── model_c_regularized.keras +``` + +--- + +## πŸš€ Panduan Instalasi & Menjalankan + +### 1. Buat dan Aktifkan Virtual Environment + +```bash +# Linux / macOS +python3 -m venv .venv +source .venv/bin/activate + +# Windows (Command Prompt / PowerShell) +python -m venv .venv +.venv\Scripts\activate +``` + +### 2. Install Dependensi + +```bash +pip install -r requirements.txt +``` + +### 3. Menjalankan Eksperimen + +Semua skrip eksperimen berada di dalam folder `experiments/`: + +- **Eksperimen 1: Perbandingan Arsitektur MLP** + ```bash + python experiments/01_mlp_comparison.py + ``` + +- **Eksperimen 2: Regularisasi (BatchNorm + Dropout)** + ```bash + python experiments/02_regularization.py + ``` + +- **Eksperimen 3: Contoh Model Selection (LSTM, CNN, NLP, XGBoost)** + ```bash + python experiments/03_model_selection.py + ``` + +- **Eksperimen 4: CNN MNIST vs MLP** + ```bash + python experiments/04_cnn_mnist.py + ``` + +--- + +## πŸ“Š Ringkasan Hasil Eksperimen + +### 1. Perbandingan Arsitektur MLP (Tugas 1) +- **Model A (1 Hidden Layer - 64)**: ~97.06% Akurasi, 50,890 Parameter +- **Model B (2 Hidden Layers - 128 β†’ 64)**: ~97.24% Akurasi, 109,386 Parameter +- **Model C (3 Hidden Layers - 256 β†’ 128 β†’ 64)**: ~97.64% Akurasi, 242,762 Parameter + +### 2. Regularisasi pada Model C (Tugas 2) +- Penambahan **Batch Normalization** dan **Dropout (0.3)** terbukti menstabilkan proses training dan menekan *generalization gap* / overfitting pada kurva validasi. + +### 3. Keunggulan CNN vs MLP pada MNIST (Tugas 4) +| Metrik | MLP Terbaik (Model C) | CNN Sederhana | Perubahan | +| :--- | :--- | :--- | :--- | +| **Test Accuracy** | 97.64% | **99.03%** | **+1.39%** | +| **Error Rate** | 2.36% | **0.97%** | **-58.9% (relatif)** | +| **Jumlah Parameter** | 242,762 | **121,930** | **-49.8% (lebih efisien)** | +| **Salah Klasifikasi** | 236 / 10,000 | **97 / 10,000** | **139 gambar lebih sedikit** | + +--- + +## πŸ› οΈ Teknologi & Framework +- Python 3.10+ +- TensorFlow / Keras +- NumPy & Pandas +- Matplotlib & Seaborn +- XGBoost & Scikit-Learn + diff --git a/docs/PRESENTATION.md b/docs/PRESENTATION.md new file mode 100644 index 0000000..ae1fcfb --- /dev/null +++ b/docs/PRESENTATION.md @@ -0,0 +1,136 @@ +# πŸ“Š Presentasi Praktikum Deep Learning +**Kelompok 3** + +--- + +## 1. INTRODUKSI + +### πŸ“Œ Latar Belakang +Praktikum ini bertujuan untuk mengeksplorasi berbagai arsitektur jaringan saraf tiruan (Neural Network) dan teknik pelatihan, mulai dari Multi-Layer Perceptron (MLP), mitigasi overfitting melalui regularisasi, analisis pemilihan model (*Model Selection*), hingga Convolutional Neural Network (CNN) pada dataset MNIST dan domain data lainnya. + +### πŸ“¦ Dataset Utama: MNIST Handwritten Digits +* **Ukuran Dataset:** 60.000 citra training & 10.000 citra testing. +* **Format Data:** Citra grayscale berukuran $28 \times 28$ piksel. +* **Jumlah Kelas:** 10 kelas target (digit angka 0 sampai 9). +* **Preprocessing:** + * Normalisasi nilai piksel dari $[0, 255]$ menjadi rentang $[0.0, 1.0]$. + * Penyesuaian bentuk data (vektor 784 untuk MLP, tensor $28 \times 28 \times 1$ untuk CNN). + +--- + +## 2. PENJELASAN TUGAS 1: Eksperimen Arsitektur & Kedalaman MLP + +### 🎯 Tujuan +Menguji pengaruh kedalaman layer dan jumlah neuron terhadap akurasi model serta waktu pelatihan pada dataset MNIST. + +### πŸ—οΈ Konfigurasi 3 Model MLP +* **Model A (1 Hidden Layer):** Input (784) $\rightarrow$ `Dense(64, ReLU)` $\rightarrow$ `Dense(10, Softmax)` +* **Model B (2 Hidden Layer):** Input (784) $\rightarrow$ `Dense(128, ReLU)` $\rightarrow$ `Dense(64, ReLU)` $\rightarrow$ `Dense(10, Softmax)` +* **Model C (3 Hidden Layer):** Input (784) $\rightarrow$ `Dense(256, ReLU)` $\rightarrow$ `Dense(128, ReLU)` $\rightarrow$ `Dense(64, ReLU)` $\rightarrow$ `Dense(10, Softmax)` + +### πŸ“ˆ Hasil Eksperimen +| Model | Arsitektur Hidden Layer | Jumlah Parameter | Test Accuracy | Waktu Training / Epoch | +| :--- | :--- | :---: | :---: | :---: | +| **Model A** | `[64]` | 50.890 | 97,06% | 1,22 detik | +| **Model B** | `[128, 64]` | 109.386 | 97,24% | 1,29 detik | +| **Model C (Terbaik)** | `[256, 128, 64]` | 242.762 | **97,64%** | 2,50 detik | + +### πŸ’‘ Kesimpulan Tugas 1 +* **Model C** menghasilkan akurasi tertinggi (**97,64%**) karena mampu mempelajari representasi fitur yang lebih kompleks. +* Semakin dalam layer, jumlah parameter dan waktu komputasi per epoch meningkat secara signifikan. + +--- + +## 3. PENJELASAN TUGAS 2: Eksperimen Regularisasi pada Deep MLP + +### 🎯 Tujuan +Mengatasi permasalahan *overfitting* yang muncul pada Model C saat dilatih dalam durasi yang lebih panjang (20 epoch). + +### πŸ” Permasalahan pada Baseline (Tanpa Regularisasi) +* *Training loss* terus menurun mendekati 0, namun *validation loss* mulai naik dan berfluktuasi setelah epoch ke-7. +* Terjadi pelebaran *generalization gap* (model menghafal data training, bukan mempelajari pola umum). + +### πŸ›‘οΈ Solusi: Penerapan Batch Normalization & Dropout +* **Batch Normalization:** Menormalkan input di setiap layer, menstabilkan distribusi gradien, dan mempercepat konvergensi. +* **Dropout (rate = 0.3):** Mematikan 30% koneksi neuron secara acak selama training untuk mencegah *co-adaptation*. + +```text +Arsitektur Regularized: +Input (784) ──> Dense(256) ──> BatchNorm ──> ReLU ──> Dropout(0.3) + ──> Dense(128) ──> BatchNorm ──> ReLU ──> Dropout(0.3) + ──> Dense(64) ──> BatchNorm ──> ReLU ──> Dropout(0.3) + ──> Dense(10, Softmax) +``` + +### πŸ’‘ Kesimpulan Tugas 2 +* Penambahan BatchNorm dan Dropout berhasil menjaga kurva *validation loss* tetap stabil dan sejajar dengan *training loss*. +* Daya generalisasi model meningkat dan risiko overfitting berhasil ditekan secara efektif. + +--- + +## 4. PENJELASAN TUGAS 3: Analisis & Justifikasi Pemilihan Model (*Model Selection*) + +### 🎯 Tujuan +Menentukan dan menjustifikasi arsitektur model yang paling optimal berdasarkan karakteristik data input dan kebutuhan komputasi. + +### πŸ“‹ Hasil Pemilihan Model untuk 4 Skenario: + +#### (a) Prediksi Stok Barang dari 12 Bulan Historis Penjualan +* **Tipe Data:** Deret Waktu (*Time-Series*). +* **Arsitektur Terpilih:** **LSTM (Long Short-Term Memory)** *(Alternatif: XGBoost / SARIMA)*. +* **Justifikasi:** Data memiliki dependensi urutan waktu dan tren musiman. LSTM mampu mempertahankan memori jangka panjang melalui *cell state* dan mekanisme *gates* tanpa terkena *vanishing gradient*. + +#### (b) Klasifikasi Foto Produk Rusak vs Normal di Lini Produksi +* **Tipe Data:** Citra 2D (*Computer Vision*). +* **Arsitektur Terpilih:** **CNN (Convolutional Neural Network)**. +* **Justifikasi:** Pola kerusakan (goresan/retakan) terikat pada korelasi spasial piksel. CNN mengekstrak hierarki fitur visual secara bertingkat dan memiliki sifat *translation invariance* (tahan pergeseran). + +#### (c) Analisis Sentimen Review Google Play Store +* **Tipe Data:** Teks Bebas Bahasa Alami (*NLP / Sequential Text*). +* **Arsitektur Terpilih:** **LSTM dengan Word Embedding** *(Alternatif: Transformer / IndoBERT)*. +* **Justifikasi:** Ulasan teks adalah sekuens kata di mana arti kalimat sangat bergantung pada urutan. Embedding memetakan makna semantik kata, dan LSTM memahami konteks kalimat dari awal hingga akhir. + +#### (d) Prediksi Churn Pelanggan dari 15 Kolom Tabular +* **Tipe Data:** Tabular Terstruktur (*Structured Tabular Data*). +* **Arsitektur Terpilih:** **ML Klasik (XGBoost / LightGBM)**. +* **Justifikasi:** Pada data tabular dimensi kecil (15 fitur), model *gradient boosted trees* secara konsisten mengungguli deep learning dalam performa generalisasi, kecepatan latih, dan interpretasi fitur (*feature importance*). + +--- + +## 5. PENJELASAN TUGAS 4: Implementasi CNN pada MNIST vs MLP + +### 🎯 Tujuan +Membangun model CNN 2D sederhana dan membandingkan performanya secara kuantitatif dengan model MLP terbaik dari Tugas 1 (Model C). + +### πŸ—οΈ Arsitektur Model CNN +```text +Input (28, 28, 1) + ↓ +Conv2D (32 filter, 3Γ—3, ReLU) ──> Output: (26, 26, 32) +MaxPooling2D (2Γ—2) ──> Output: (13, 13, 32) + ↓ +Conv2D (64 filter, 3Γ—3, ReLU) ──> Output: (11, 11, 64) +MaxPooling2D (2Γ—2) ──> Output: (5, 5, 64) + ↓ +Flatten ──> Output: 1600 +Dense (64, ReLU) + Dropout (0.3) + ↓ +Dense (10, Softmax) ──> Output: Probabilitas 10 Kelas +``` + +### πŸ“Š Tabel Perbandingan Kuantitatif: CNN vs MLP Terbaik +| Metrik Evaluasi | MLP Terbaik (Model C) | Model CNN Sederhana | Analisis / Improvement | +| :--- | :---: | :---: | :--- | +| **Test Accuracy** | 97,64% | **99,03%** | **+1,39 poin persentase** | +| **Test Loss** | 0,0933 | **0,0297** | **Turun signifikan (-68,2%)** | +| **Error Rate** | 2,36% | **0,97%** | **Pengurangan error 58,9% (relatif)** | +| **Salah Klasifikasi** | 236 dari 10.000 | **97 dari 10.000** | **139 gambar lebih sedikit salah** | +| **Jumlah Parameter** | 242.762 | **121.930** | **Hemat 49,8% parameter (separuh bobot)** | +| **Waktu / Epoch (CPU)** | **2,50 detik** | 16,56 detik | Konvolusi membutuhkan komputasi lebih di CPU | + +### πŸ’‘ Mengapa CNN Lebih Unggul untuk Data Citra? +1. **Preservasi Struktur Spasial:** Memproses citra dalam format 2D asli sehingga korelasi antarpiksel tetangga tetap terjaga (tidak hilang seperti pada *flattening* MLP). +2. **Parameter Sharing:** Filter konvolusi yang sama digeser ke seluruh permukaan citra untuk mendeteksi pola yang sama di berbagai posisi. +3. **Hierarki Fitur Otomatis:** Layer awal mengekstrak garis tepi/sudut, sedangkan layer lanjutan menggabungkannya menjadi bentuk kurva dan pola angka utuh. +4. **Translation Invariance:** Fitur `MaxPooling2D` membuat prediksi model tetap konsisten meskipun posisi tulisan tangan sedikit bergeser. + diff --git a/docs/model_selection.md b/docs/model_selection.md new file mode 100644 index 0000000..aaab116 --- /dev/null +++ b/docs/model_selection.md @@ -0,0 +1,32 @@ +# Analisis Pemilihan Model (Model Selection) + +## (a) Prediksi stok barang dari 12 bulan historis penjualan + +**Arsitektur:** LSTM (atau ML Klasik seperti XGBoost / SARIMA sebagai alternatif kuat). + +**Justifikasi:** Data penjualan historis merupakan deret waktu (time-series) yang memiliki dependensi temporal, tren, dan pola musiman antar-bulan. LSTM dirancang khusus untuk memproses data sekuensial dengan mempertahankan informasi masa lalu melalui mekanisme cell state dan gates, sehingga mampu menangkap dinamika tren penjualan tanpa kehilangan memori jangka panjang. + +--- + +## (b) Klasifikasi foto produk rusak vs normal di lini produksi + +**Arsitektur:** CNN (Convolutional Neural Network). + +**Justifikasi:** Data citra memerlukan ekstraksi pola visual lokal seperti goresan, retakan, atau perbedaan warna yang terikat pada korelasi spasial antarpiksel. Operasi konvolusi pada CNN mampu mengekstraksi hierarki fitur visual (dari garis tepi hingga tekstur utuh) serta memiliki sifat translation invariance, sehingga cacat produk tetap terdeteksi meskipun posisinya bergeser. + +--- + +## (c) Analisis sentimen review Google Play Store + +**Arsitektur:** LSTM (atau variannya seperti Bi-LSTM / model berbasis Transformer). + +**Justifikasi:** Ulasan teks adalah data sekuensial linguistik di mana arti suatu kalimat sangat bergantung pada urutan dan konteks kata di sekitarnya. LSTM secara efektif menangani panjang kalimat yang bervariasi dan mampu mempertahankan konteks makna dari awal hingga akhir ulasan untuk menentukan polaritas sentimen positif atau negatif secara akurat. + +--- + +## (d) Prediksi churn pelanggan dari 15 kolom tabular + +**Arsitektur:** ML Klasik (seperti XGBoost, LightGBM, atau Random Forest). + +**Justifikasi:** Pada data tabular berdimensi kecil (15 fitur), model gradient boosted decision trees secara konsisten mengungguli deep learning dalam hal performa generalisasi, kecepatan latih, dan interpretasi fitur (feature importance). Jaringan saraf seperti ANN cenderung membutuhkan volume sampel yang jauh lebih besar dan rentan overfitting pada batas keputusan data tabular yang tidak terstruktur secara spasial. +3. **Gunakan Model ML Klasik Berbasis Pohon (XGBoost / LightGBM)** saat bekerja dengan data tabular berstruktur tetap karena akurasi lebih unggul, waktu latih cepat, dan memiliki interpretabilitas fitur yang tinggi. \ No newline at end of file diff --git a/experiments/01_mlp_comparison.py b/experiments/01_mlp_comparison.py new file mode 100644 index 0000000..b3f7215 --- /dev/null +++ b/experiments/01_mlp_comparison.py @@ -0,0 +1,99 @@ +import sys +import os +import time + +# Tambahkan root directory ke path agar dapat import dari src +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) + +from src.data_loader import load_mnist_for_mlp +from src.models import create_mlp_model + + +def main(): + print("=" * 60) + print("TUGAS 1: MEMUAT DATASET MNIST & EKSPERIMEN MLP") + print("=" * 60) + + # 1. Load Data + (x_train, y_train), (x_test, y_test) = load_mnist_for_mlp() + print(f"Data training : {x_train.shape}") + print(f"Data testing : {x_test.shape}") + + # 2. Konfigurasi 3 Model MLP + models_config = { + "Model A - 1 Hidden Layer": [64], + "Model B - 2 Hidden Layer": [128, 64], + "Model C - 3 Hidden Layer": [256, 128, 64] + } + + results = [] + EPOCHS = 10 + BATCH_SIZE = 128 + + # 3. Training & Evaluasi + for model_name, architecture in models_config.items(): + print("\n" + "=" * 60) + print(model_name) + print("=" * 60) + + model = create_mlp_model(architecture) + model.summary() + + print("\nMemulai training...") + start_time = time.time() + + model.fit( + x_train, + y_train, + epochs=EPOCHS, + batch_size=BATCH_SIZE, + validation_split=0.1, + verbose=1 + ) + + total_time = time.time() - start_time + average_time = total_time / EPOCHS + + test_loss, test_accuracy = model.evaluate(x_test, y_test, verbose=0) + total_parameters = model.count_params() + + results.append({ + "model": model_name, + "parameters": total_parameters, + "accuracy": test_accuracy * 100, + "time_per_epoch": average_time + }) + + print("\nHasil:") + print(f"Test Accuracy : {test_accuracy * 100:.2f}%") + print(f"Jumlah Parameter : {total_parameters:,}") + print(f"Waktu/Epoch : {average_time:.2f} detik") + + # 4. Ringkasan Perbandingan + print("\n\n" + "=" * 80) + print("HASIL PERBANDINGAN 3 MODEL MLP") + print("=" * 80) + print(f"{'Model':<30}{'Parameter':>15}{'Accuracy':>15}{'Time/Epoch':>15}") + print("-" * 80) + + for res in results: + print( + f"{res['model']:<30}" + f"{res['parameters']:>15,}" + f"{res['accuracy']:>14.2f}%" + f"{res['time_per_epoch']:>14.2f}s" + ) + + best_model = max(results, key=lambda x: x["accuracy"]) + print("\n" + "=" * 60) + print("MODEL DENGAN TEST ACCURACY TERTINGGI") + print("=" * 60) + print(f"Model : {best_model['model']}") + print(f"Test Accuracy : {best_model['accuracy']:.2f}%") + print(f"Jumlah Parameter : {best_model['parameters']:,}") + print(f"Waktu Training/Epoch: {best_model['time_per_epoch']:.2f} detik") + + +if __name__ == "__main__": + main() + diff --git a/experiments/02_regularization.py b/experiments/02_regularization.py new file mode 100644 index 0000000..a149351 --- /dev/null +++ b/experiments/02_regularization.py @@ -0,0 +1,93 @@ +import sys +import os +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt + +# Tambahkan root directory ke path agar dapat import dari src +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) + +from src.data_loader import load_mnist_for_mlp +from src.models import create_mlp_model, create_regularized_mlp_model +from src.utils import ensure_dir + + +def main(): + print("=" * 60) + print("TUGAS 2: EKSPERIMEN REGULARISASI (BASELINE vs BATCHNORM + DROPOUT)") + print("=" * 60) + + # 1. Load Data + (x_train, y_train), (x_test, y_test) = load_mnist_for_mlp() + + EPOCHS = 20 + BATCH_SIZE = 128 + + # 2. Baseline Model (Without Regularization) + print("\n" + "=" * 60) + print("TRAINING BASELINE MODEL (WITHOUT REGULARIZATION)") + print("=" * 60) + model_base = create_mlp_model([256, 128, 64]) + history_base = model_base.fit( + x_train, y_train, + epochs=EPOCHS, + batch_size=BATCH_SIZE, + validation_split=0.1, + verbose=1 + ) + + # 3. Regularized Model (BatchNorm + Dropout 0.3) + print("\n" + "=" * 60) + print("TRAINING REGULARIZED MODEL (WITH BATCHNORM + DROPOUT)") + print("=" * 60) + model_reg = create_regularized_mlp_model(hidden_layers=[256, 128, 64], dropout_rate=0.3) + history_reg = model_reg.fit( + x_train, y_train, + epochs=EPOCHS, + batch_size=BATCH_SIZE, + validation_split=0.1, + verbose=1 + ) + + # 4. Save Model Artifact + results_model_dir = os.path.join("results", "models") + ensure_dir(results_model_dir) + model_reg_path = os.path.join(results_model_dir, "model_c_regularized.keras") + model_reg.save(model_reg_path) + print(f"\n[INFO] Model teregularisasi disimpan di: {model_reg_path}") + + # 5. Plot Comparison Curves + results_fig_dir = os.path.join("results", "figures") + ensure_dir(results_fig_dir) + fig_path = os.path.join(results_fig_dir, "loss_regularization.png") + + plt.figure(figsize=(14, 5)) + + # Subplot 1: Baseline + plt.subplot(1, 2, 1) + plt.plot(history_base.history['loss'], label='Training Loss', color='blue') + plt.plot(history_base.history['val_loss'], label='Validation Loss', color='orange', linestyle='--') + plt.title('Model C Without Regularization') + plt.xlabel('Epoch') + plt.ylabel('Loss') + plt.legend() + plt.grid(True, alpha=0.3) + + # Subplot 2: Regularized + plt.subplot(1, 2, 2) + plt.plot(history_reg.history['loss'], label='Training Loss', color='blue') + plt.plot(history_reg.history['val_loss'], label='Validation Loss', color='green', linestyle='--') + plt.title('Model C With BatchNorm + Dropout(0.3)') + plt.xlabel('Epoch') + plt.ylabel('Loss') + plt.legend() + plt.grid(True, alpha=0.3) + + plt.tight_layout() + plt.savefig(fig_path, dpi=130) + print(f"[INFO] Grafik perbandingan loss disimpan di: {fig_path}") + + +if __name__ == "__main__": + main() + diff --git a/experiments/03_model_selection.py b/experiments/03_model_selection.py new file mode 100644 index 0000000..8c91bbd --- /dev/null +++ b/experiments/03_model_selection.py @@ -0,0 +1,67 @@ +""" +Tugas 3: Contoh Implementasi Berbagai Arsitektur Model Sesuai Karakteristik Data +""" + +import tensorflow as tf +from tensorflow import keras +from tensorflow.keras.layers import Conv2D, Dense, Embedding, Flatten, LSTM, MaxPooling2D +from tensorflow.keras.models import Sequential +from xgboost import XGBClassifier + + +def build_models(): + print("=" * 60) + print("TUGAS 3: CONTOH ARSITEKTUR MODEL SELECTION") + print("=" * 60) + + # (a) Prediksi Stok Barang dari Deret Waktu (LSTM) + # Input shape: (samples, time_steps=12, features=1) + model_a = Sequential([ + LSTM(32, input_shape=(12, 1)), + Dense(1) + ], name="LSTM_Stock_Forecasting") + model_a.compile(optimizer='adam', loss='mse') + print("\n[Case A] Model LSTM untuk Prediksi Stok Barang (Time Series):") + model_a.summary() + + # (b) Klasifikasi Foto Produk Rusak vs Normal (CNN) + # Input shape contoh citra RGB 128x128 + model_b = Sequential([ + Conv2D(32, (3, 3), activation='relu', input_shape=(128, 128, 3)), + MaxPooling2D((2, 2)), + Flatten(), + Dense(64, activation='relu'), + Dense(1, activation='sigmoid') # binary: rusak vs normal + ], name="CNN_Defect_Classification") + model_b.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) + print("\n[Case B] Model CNN untuk Klasifikasi Foto Produk (Computer Vision):") + model_b.summary() + + # (c) Analisis Sentimen Ulasan Play Store (LSTM + Embedding) + vocab_size = 5000 + max_length = 100 + model_c = Sequential([ + Embedding(input_dim=vocab_size, output_dim=64, input_length=max_length), + LSTM(64), + Dense(32, activation='relu'), + Dense(1, activation='sigmoid') # binary: positif vs negatif + ], name="LSTM_Sentiment_Analysis") + model_c.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) + print("\n[Case C] Model LSTM + Embedding untuk Analisis Sentimen (NLP):") + model_c.summary() + + # (d) Prediksi Churn Pelanggan Tabular (ML Klasik - XGBoost) + # X_train memiliki dimensi (n_samples, 15) + model_d = XGBClassifier( + n_estimators=100, + max_depth=4, + learning_rate=0.1, + random_state=42 + ) + print("\n[Case D] Model XGBoost untuk Prediksi Churn (Tabular 15 fitur):") + print(model_d) + + +if __name__ == "__main__": + build_models() + diff --git a/experiments/04_cnn_mnist.py b/experiments/04_cnn_mnist.py new file mode 100644 index 0000000..019ce12 --- /dev/null +++ b/experiments/04_cnn_mnist.py @@ -0,0 +1,148 @@ +""" +Tugas No. 4 - Implementasi CNN sederhana untuk MNIST +dan perbandingannya dengan MLP dari Tugas No. 1. +""" + +import os +import sys +import time + +# Sembunyikan log informasi TensorFlow +os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2" + +import matplotlib +matplotlib.use("Agg") # simpan plot sebagai file +import matplotlib.pyplot as plt +import numpy as np +import tensorflow as tf + +# Tambahkan root directory ke path agar dapat import dari src +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) + +from src.data_loader import load_mnist_for_cnn +from src.models import create_cnn_mnist_model +from src.utils import EpochTimerCallback, ensure_dir + + +def main(): + # Konfigurasi + SEED = 42 + EPOCHS = 10 + BATCH_SIZE = 128 + VAL_SPLIT = 0.1 + + tf.random.set_seed(SEED) + np.random.seed(SEED) + + # Hasil MLP terbaik dari Tugas No. 1 (Model C: 256-128-64) + MLP_ACCURACY = 0.9764 + MLP_PARAMS = 242_762 + MLP_EPOCH_TIME = 2.50 + + # 1. Load dan preprocessing data + print("Memuat dataset MNIST untuk CNN...") + (x_train, y_train), (x_test, y_test) = load_mnist_for_cnn() + + print(f"Data training : {x_train.shape[0]:,} gambar") + print(f"Data testing : {x_test.shape[0]:,} gambar") + print(f"Ukuran gambar : {x_train.shape[1]} x {x_train.shape[2]} piksel (channel={x_train.shape[3]})\n") + + # 2. Bangun model CNN + model = create_cnn_mnist_model() + model.summary() + + # 3. Training dengan pencatatan waktu per epoch + timer_cb = EpochTimerCallback() + + print("\nMemulai training CNN...") + print("Perkiraan waktu: 15-20 detik per epoch di CPU (total sekitar 3 menit).\n") + + history = model.fit( + x_train, + y_train, + validation_split=VAL_SPLIT, + epochs=EPOCHS, + batch_size=BATCH_SIZE, + verbose=2, + callbacks=[timer_cb], + ) + + # 4. Evaluasi + test_loss, test_acc = model.evaluate(x_test, y_test, verbose=0) + n_params = model.count_params() + avg_epoch_time = float(np.mean(timer_cb.epoch_times)) if timer_cb.epoch_times else 0.0 + + predictions = np.argmax(model.predict(x_test, verbose=0), axis=1) + n_wrong = int(np.sum(predictions != y_test)) + + # 5. Perbandingan CNN vs MLP + error_mlp = (1 - MLP_ACCURACY) * 100 + error_cnn = (1 - test_acc) * 100 + gain_point = (test_acc - MLP_ACCURACY) * 100 + error_reduction = (1 - error_cnn / error_mlp) * 100 + + print("\n" + "=" * 62) + print("HASIL EKSPERIMEN CNN") + print("=" * 62) + print(f"Test accuracy : {test_acc * 100:.2f}%") + print(f"Test loss : {test_loss:.4f}") + print(f"Jumlah parameter : {n_params:,}") + print(f"Waktu training/epoch : {avg_epoch_time:.2f} detik") + print(f"Salah klasifikasi : {n_wrong} dari {len(y_test):,} gambar") + + print("\n" + "=" * 62) + print("PERBANDINGAN CNN vs MLP") + print("=" * 62) + print(f"{'Metrik':<24}{'MLP':>14}{'CNN':>14}") + print("-" * 62) + print(f"{'Test accuracy':<24}{MLP_ACCURACY * 100:>13.2f}%{test_acc * 100:>13.2f}%") + print(f"{'Error rate':<24}{error_mlp:>13.2f}%{error_cnn:>13.2f}%") + print(f"{'Jumlah parameter':<24}{MLP_PARAMS:>14,}{n_params:>14,}") + print(f"{'Waktu/epoch (detik)':<24}{MLP_EPOCH_TIME:>14.2f}{avg_epoch_time:>14.2f}") + print("-" * 62) + print(f"Improvement akurasi : +{gain_point:.2f} poin persentase") + print(f"Pengurangan error rate : {error_reduction:.1f}% (relatif)") + print(f"Selisih parameter : {n_params - MLP_PARAMS:+,}") + print("=" * 62) + + # 6. Simpan grafik ke folder results/figures + results_fig_dir = os.path.join("results", "figures") + ensure_dir(results_fig_dir) + fig_path = os.path.join(results_fig_dir, "hasil_cnn.png") + + fig, axes = plt.subplots(1, 2, figsize=(12, 4.5)) + epochs_range = range(1, EPOCHS + 1) + axes[0].plot(epochs_range, history.history["accuracy"], label="Train accuracy") + axes[0].plot(epochs_range, history.history["val_accuracy"], label="Validation accuracy") + axes[0].set_title("Learning Curve CNN") + axes[0].set_xlabel("Epoch") + axes[0].set_ylabel("Accuracy") + axes[0].legend() + axes[0].grid(alpha=0.3) + + axes[1].bar( + ["MLP terbaik", "CNN"], + [MLP_ACCURACY * 100, test_acc * 100], + color=["#55A868", "#C44E52"], + ) + axes[1].set_ylim(96, 100) + axes[1].set_ylabel("Test Accuracy (%)") + axes[1].set_title("Perbandingan MLP vs CNN") + for i, value in enumerate([MLP_ACCURACY * 100, test_acc * 100]): + axes[1].text(i, value + 0.05, f"{value:.2f}%", ha="center") + + plt.tight_layout() + plt.savefig(fig_path, dpi=130) + print(f"\n[INFO] Grafik disimpan di: {fig_path}") + + # 7. Simpan model terlatih ke folder results/models + results_model_dir = os.path.join("results", "models") + ensure_dir(results_model_dir) + model_path = os.path.join(results_model_dir, "model_cnn_mnist.keras") + model.save(model_path) + print(f"[INFO] Model disimpan di: {model_path}") + + +if __name__ == "__main__": + main() + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..a8b4eed --- /dev/null +++ b/requirements.txt @@ -0,0 +1,13 @@ +# Core Deep Learning & Machine Learning Frameworks +tensorflow>=2.16.0 +keras>=3.0.0 +xgboost>=2.0.0 +scikit-learn>=1.3.0 + +# Scientific Computing & Data Manipulation +numpy>=1.24.0 +pandas>=2.0.0 + +# Data Visualization +matplotlib>=3.7.0 +seaborn>=0.12.0 diff --git a/task4-cnn/hasil_cnn.png b/results/figures/hasil_cnn.png similarity index 100% rename from task4-cnn/hasil_cnn.png rename to results/figures/hasil_cnn.png diff --git a/task-2-Regulation/image.png b/results/figures/loss_regularization.png similarity index 100% rename from task-2-Regulation/image.png rename to results/figures/loss_regularization.png diff --git a/task-2-Regulation/model_c_regularized.keras b/results/models/model_c_regularized.keras similarity index 100% rename from task-2-Regulation/model_c_regularized.keras rename to results/models/model_c_regularized.keras diff --git a/task4-cnn/model_cnn_mnist.keras b/results/models/model_cnn_mnist.keras similarity index 100% rename from task4-cnn/model_cnn_mnist.keras rename to results/models/model_cnn_mnist.keras diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..47023e3 --- /dev/null +++ b/src/__init__.py @@ -0,0 +1,4 @@ +""" +Helper utilities and modules for Deep Learning experiments. +""" + diff --git a/src/data_loader.py b/src/data_loader.py new file mode 100644 index 0000000..bf731ea --- /dev/null +++ b/src/data_loader.py @@ -0,0 +1,46 @@ +import numpy as np +from tensorflow import keras +from typing import Tuple + + +def load_mnist_for_mlp() -> Tuple[Tuple[np.ndarray, np.ndarray], Tuple[np.ndarray, np.ndarray]]: + """ + Memuat dataset MNIST dan melakukan normalisasi serta perataan (flatten) + menjadi 784 fitur untuk arsitektur MLP. + + Returns: + (x_train, y_train), (x_test, y_test) + """ + (x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data() + + # Normalisasi nilai pixel dari 0-255 menjadi 0.0-1.0 + x_train = x_train.astype("float32") / 255.0 + x_test = x_test.astype("float32") / 255.0 + + # Flatten 28x28 menjadi 784 + x_train = x_train.reshape(-1, 784) + x_test = x_test.reshape(-1, 784) + + return (x_train, y_train), (x_test, y_test) + + +def load_mnist_for_cnn() -> Tuple[Tuple[np.ndarray, np.ndarray], Tuple[np.ndarray, np.ndarray]]: + """ + Memuat dataset MNIST dan melakukan normalisasi serta penambahan dimensi channel + (28, 28, 1) untuk arsitektur CNN. + + Returns: + (x_train, y_train), (x_test, y_test) + """ + (x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data() + + # Normalisasi nilai pixel dari 0-255 menjadi 0.0-1.0 + x_train = x_train.astype("float32") / 255.0 + x_test = x_test.astype("float32") / 255.0 + + # Reshape ke format (N, 28, 28, 1) + x_train = x_train.reshape(-1, 28, 28, 1) + x_test = x_test.reshape(-1, 28, 28, 1) + + return (x_train, y_train), (x_test, y_test) + diff --git a/src/models.py b/src/models.py new file mode 100644 index 0000000..f62df20 --- /dev/null +++ b/src/models.py @@ -0,0 +1,82 @@ +from typing import List +from tensorflow import keras +from tensorflow.keras import layers + + +def create_mlp_model(hidden_layers: List[int], input_dim: int = 784, num_classes: int = 10) -> keras.Model: + """ + Membangun model MLP sederhana sesuai daftar neuron per hidden layer. + """ + model = keras.Sequential(name="mlp_model") + model.add(layers.Input(shape=(input_dim,))) + + for neurons in hidden_layers: + model.add(layers.Dense(neurons, activation="relu")) + + model.add(layers.Dense(num_classes, activation="softmax")) + + model.compile( + optimizer="adam", + loss="sparse_categorical_crossentropy", + metrics=["accuracy"] + ) + return model + + +def create_regularized_mlp_model( + hidden_layers: List[int] = [256, 128, 64], + dropout_rate: float = 0.3, + input_dim: int = 784, + num_classes: int = 10 +) -> keras.Model: + """ + Membangun model MLP dengan Batch Normalization dan Dropout. + """ + model = keras.Sequential(name="mlp_regularized") + model.add(layers.Input(shape=(input_dim,))) + + for neurons in hidden_layers: + model.add(layers.Dense(neurons)) + model.add(layers.BatchNormalization()) + model.add(layers.Activation("relu")) + model.add(layers.Dropout(dropout_rate)) + + model.add(layers.Dense(num_classes, activation="softmax")) + + model.compile( + optimizer="adam", + loss="sparse_categorical_crossentropy", + metrics=["accuracy"] + ) + return model + + +def create_cnn_mnist_model(input_shape: tuple = (28, 28, 1), num_classes: int = 10) -> keras.Model: + """ + Membangun model Convolutional Neural Network (CNN) untuk MNIST. + """ + model = keras.Sequential( + name="cnn_mnist", + layers=[ + layers.Input(shape=input_shape), + # Block 1 + layers.Conv2D(32, (3, 3), activation="relu"), + layers.MaxPooling2D((2, 2)), + # Block 2 + layers.Conv2D(64, (3, 3), activation="relu"), + layers.MaxPooling2D((2, 2)), + # Classifier + layers.Flatten(), + layers.Dense(64, activation="relu"), + layers.Dropout(0.3), + layers.Dense(num_classes, activation="softmax"), + ] + ) + + model.compile( + optimizer="adam", + loss="sparse_categorical_crossentropy", + metrics=["accuracy"] + ) + return model + diff --git a/src/utils.py b/src/utils.py new file mode 100644 index 0000000..49130f2 --- /dev/null +++ b/src/utils.py @@ -0,0 +1,65 @@ +import os +import time +from typing import Dict, List +import matplotlib.pyplot as plt +from tensorflow import keras + + +class EpochTimerCallback(keras.callbacks.Callback): + """ + Keras callback untuk mencatat durasi waktu setiap epoch. + """ + def __init__(self): + super().__init__() + self.epoch_times: List[float] = [] + self._start: float = 0.0 + + def on_epoch_begin(self, epoch, logs=None): + self._start = time.time() + + def on_epoch_end(self, epoch, logs=None): + self.epoch_times.append(time.time() - self._start) + + +def ensure_dir(dir_path: str): + """Membuat direktori jika belum ada.""" + os.makedirs(dir_path, exist_ok=True) + + +def plot_training_history( + history, + title: str = "Training History", + save_path: str = None +): + """ + Membuat plot loss dan akurasi dari training history Keras. + """ + fig, axes = plt.subplots(1, 2, figsize=(12, 4.5)) + + # Loss plot + axes[0].plot(history.history.get("loss", []), label="Train Loss") + if "val_loss" in history.history: + axes[0].plot(history.history["val_loss"], label="Val Loss", linestyle="--") + axes[0].set_title(f"{title} - Loss") + axes[0].set_xlabel("Epoch") + axes[0].set_ylabel("Loss") + axes[0].legend() + axes[0].grid(True, alpha=0.3) + + # Accuracy plot + axes[1].plot(history.history.get("accuracy", []), label="Train Accuracy") + if "val_accuracy" in history.history: + axes[1].plot(history.history["val_accuracy"], label="Val Accuracy", linestyle="--") + axes[1].set_title(f"{title} - Accuracy") + axes[1].set_xlabel("Epoch") + axes[1].set_ylabel("Accuracy") + axes[1].legend() + axes[1].grid(True, alpha=0.3) + + plt.tight_layout() + if save_path: + ensure_dir(os.path.dirname(save_path)) + plt.savefig(save_path, dpi=130) + print(f"[INFO] Plot disimpan di: {save_path}") + plt.close() + diff --git a/task-2-Regulation/model_c_regularization.py b/task-2-Regulation/model_c_regularization.py deleted file mode 100644 index f5afa69..0000000 --- a/task-2-Regulation/model_c_regularization.py +++ /dev/null @@ -1,123 +0,0 @@ -import tensorflow as tf -from tensorflow import keras -from tensorflow.keras import layers -import matplotlib.pyplot as plt - -# 1. LOAD & PREPROCESS MNIST DATASET -(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data() - -x_train = x_train.astype("float32") / 255.0 -x_test = x_test.astype("float32") / 255.0 -x_train = x_train.reshape(-1, 784) -x_test = x_test.reshape(-1, 784) - -# Model C Architecture from Task 1 -BEST_ARCHITECTURE = [256, 128, 64] -EPOCHS = 20 # 20 epochs gives enough room to observe overfitting -BATCH_SIZE = 128 - - -# ============================================================ -# MODEL 1: WITHOUT REGULARIZATION (Baseline Model C from Task 1) -# ============================================================ -model_base = keras.Sequential([ - layers.Input(shape=(784,)), - layers.Dense(256, activation="relu"), - layers.Dense(128, activation="relu"), - layers.Dense(64, activation="relu"), - layers.Dense(10, activation="softmax") -]) - -model_base.compile( - optimizer="adam", - loss="sparse_categorical_crossentropy", - metrics=["accuracy"] -) - -print("=" * 60) -print("TRAINING BASELINE MODEL (WITHOUT REGULARIZATION)") -print("=" * 60) - -history_base = model_base.fit( - x_train, y_train, - epochs=EPOCHS, - batch_size=BATCH_SIZE, - validation_split=0.1, - verbose=1 -) - - -# ============================================================ -# MODEL 2: WITH REGULARIZATION (Batch Normalization + Dropout 0.3) -# ============================================================ -model_reg = keras.Sequential([ - layers.Input(shape=(784,)), - - layers.Dense(256), - layers.BatchNormalization(), - layers.Activation("relu"), - layers.Dropout(0.3), - - layers.Dense(128), - layers.BatchNormalization(), - layers.Activation("relu"), - layers.Dropout(0.3), - - layers.Dense(64), - layers.BatchNormalization(), - layers.Activation("relu"), - layers.Dropout(0.3), - - layers.Dense(10, activation="softmax") -]) - -model_reg.compile( - optimizer="adam", - loss="sparse_categorical_crossentropy", - metrics=["accuracy"] -) - -print("\n" + "=" * 60) -print("TRAINING REGULARIZED MODEL (WITH BATCHNORM + DROPOUT)") -print("=" * 60) - -history_reg = model_reg.fit( - x_train, y_train, - epochs=EPOCHS, - batch_size=BATCH_SIZE, - validation_split=0.1, - verbose=1 -) - -# Optional: Save the trained regularized model to disk -model_reg.save("model_c_regularized.keras") -print("\n[INFO] Regularized model saved as 'model_c_regularized.keras' in your project directory.") - - -# ============================================================ -# PLOTTING LOSS CURVES FOR COMPARISON -# ============================================================ -plt.figure(figsize=(14, 5)) - -# Plot 1: Baseline (Without Regularization) -plt.subplot(1, 2, 1) -plt.plot(history_base.history['loss'], label='Training Loss', color='blue') -plt.plot(history_base.history['val_loss'], label='Validation Loss', color='orange', linestyle='--') -plt.title('Model C Without Regularization') -plt.xlabel('Epoch') -plt.ylabel('Loss') -plt.legend() -plt.grid(True) - -# Plot 2: Regularized (With BatchNorm + Dropout) -plt.subplot(1, 2, 2) -plt.plot(history_reg.history['loss'], label='Training Loss', color='blue') -plt.plot(history_reg.history['val_loss'], label='Validation Loss', color='green', linestyle='--') -plt.title('Model C With BatchNorm + Dropout(0.3)') -plt.xlabel('Epoch') -plt.ylabel('Loss') -plt.legend() -plt.grid(True) - -plt.tight_layout() -plt.show() \ No newline at end of file diff --git a/task1-models/codingan.py b/task1-models/codingan.py deleted file mode 100644 index caa0982..0000000 --- a/task1-models/codingan.py +++ /dev/null @@ -1,224 +0,0 @@ -import tensorflow as tf -from tensorflow import keras -from tensorflow.keras import layers -import time - - -# ============================================================ -# 1. LOAD DATASET MNIST -# ============================================================ - -print("=" * 60) -print("MEMUAT DATASET MNIST") -print("=" * 60) - -(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data() - -print(f"Data training : {x_train.shape}") -print(f"Data testing : {x_test.shape}") - - -# ============================================================ -# 2. PREPROCESSING -# ============================================================ - -# Normalisasi nilai pixel dari 0-255 menjadi 0-1 -x_train = x_train.astype("float32") / 255.0 -x_test = x_test.astype("float32") / 255.0 - -# Mengubah gambar 28x28 menjadi 784 fitur -x_train = x_train.reshape(-1, 784) -x_test = x_test.reshape(-1, 784) - -print(f"Training setelah preprocessing: {x_train.shape}") -print(f"Testing setelah preprocessing : {x_test.shape}") - - -# ============================================================ -# 3. FUNGSI MEMBUAT MODEL -# ============================================================ - -def create_model(hidden_layers): - - model = keras.Sequential() - - # Input layer - model.add(layers.Input(shape=(784,))) - - # Hidden layers - for neurons in hidden_layers: - model.add( - layers.Dense( - neurons, - activation="relu" - ) - ) - - # Output layer - model.add( - layers.Dense( - 10, - activation="softmax" - ) - ) - - model.compile( - optimizer="adam", - loss="sparse_categorical_crossentropy", - metrics=["accuracy"] - ) - - return model - - -# ============================================================ -# 4. KONFIGURASI 3 MODEL -# ============================================================ - -models_config = { - "Model A - 1 Hidden Layer": [64], - "Model B - 2 Hidden Layer": [128, 64], - "Model C - 3 Hidden Layer": [256, 128, 64] -} - - -# ============================================================ -# 5. TRAINING DAN EVALUASI -# ============================================================ - -results = [] - -EPOCHS = 10 -BATCH_SIZE = 128 - -for model_name, architecture in models_config.items(): - - print("\n") - print("=" * 60) - print(model_name) - print("=" * 60) - - # Membuat model - model = create_model(architecture) - - # Menampilkan arsitektur - model.summary() - - # Training - print("\nMemulai training...") - - start_time = time.time() - - history = model.fit( - x_train, - y_train, - epochs=EPOCHS, - batch_size=BATCH_SIZE, - validation_split=0.1, - verbose=1 - ) - - end_time = time.time() - - # Total waktu training - total_time = end_time - start_time - - # Rata-rata waktu per epoch - average_time = total_time / EPOCHS - - # Evaluasi menggunakan test data - test_loss, test_accuracy = model.evaluate( - x_test, - y_test, - verbose=0 - ) - - # Jumlah parameter - total_parameters = model.count_params() - - # Menyimpan hasil - results.append({ - "model": model_name, - "parameters": total_parameters, - "accuracy": test_accuracy * 100, - "time_per_epoch": average_time - }) - - print("\nHasil:") - print(f"Test Accuracy : {test_accuracy * 100:.2f}%") - print(f"Jumlah Parameter : {total_parameters:,}") - print(f"Waktu/Epoch : {average_time:.2f} detik") - - -# ============================================================ -# 6. HASIL PERBANDINGAN -# ============================================================ - -print("\n\n") -print("=" * 80) -print("HASIL PERBANDINGAN 3 MODEL MLP") -print("=" * 80) - -print( - f"{'Model':<30}" - f"{'Parameter':>15}" - f"{'Accuracy':>15}" - f"{'Time/Epoch':>15}" -) - -print("-" * 80) - -for result in results: - - print( - f"{result['model']:<30}" - f"{result['parameters']:>15,}" - f"{result['accuracy']:>14.2f}%" - f"{result['time_per_epoch']:>14.2f}s" - ) - - -# ============================================================ -# 7. MENENTUKAN MODEL DENGAN ACCURACY TERTINGGI -# ============================================================ - -best_model = max( - results, - key=lambda x: x["accuracy"] -) - -print("\n") -print("=" * 60) -print("MODEL DENGAN TEST ACCURACY TERTINGGI") -print("=" * 60) - -print(f"Model : {best_model['model']}") -print(f"Test Accuracy : {best_model['accuracy']:.2f}%") -print(f"Jumlah Parameter : {best_model['parameters']:,}") -print(f"Waktu Training/Epoch: {best_model['time_per_epoch']:.2f} detik") - - -# ============================================================ -# 8. KESIMPULAN SINGKAT -# ============================================================ - -print("\n") -print("=" * 60) -print("KESIMPULAN") -print("=" * 60) - -print( - "Model yang lebih dalam memiliki jumlah parameter " - "yang lebih banyak dan umumnya membutuhkan waktu " - "training yang lebih besar." -) - -print( - "Namun, model yang lebih dalam tidak selalu menghasilkan " - "peningkatan test accuracy yang signifikan." -) - -print( - "Pemilihan arsitektur sebaiknya mempertimbangkan " - "accuracy, jumlah parameter, dan waktu training." -) \ No newline at end of file diff --git a/task3-model-selection/model_selection.md b/task3-model-selection/model_selection.md deleted file mode 100644 index cac6d5b..0000000 --- a/task3-model-selection/model_selection.md +++ /dev/null @@ -1,23 +0,0 @@ -(a) Prediksi stok barang dari 12 bulan historis penjualan - -Arsitektur: LSTM (atau ML Klasik seperti XGBoost / SARIMA sebagai alternatif kuat). - -Justifikasi: Data penjualan historis merupakan deret waktu (time-series) yang memiliki dependensi temporal, tren, dan pola musiman antar-bulan. LSTM dirancang khusus untuk memproses data sekuensial dengan mempertahankan informasi masa lalu melalui mekanisme cell state dan gates, sehingga mampu menangkap dinamika tren penjualan tanpa kehilangan memori jangka panjang. - -(b) Klasifikasi foto produk rusak vs normal di lini produksi - -Arsitektur: CNN (Convolutional Neural Network). - -Justifikasi: Data citra memerlukan ekstraksi pola visual lokal seperti goresan, retakan, atau perbedaan warna yang terikat pada korelasi spasial antarpiksel. Operasi konvolusi pada CNN mampu mengekstraksi hierarki fitur visual (dari garis tepi hingga tekstur utuh) serta memiliki sifat translation invariance, sehingga cacat produk tetap terdeteksi meskipun posisinya bergeser. - -(c) Analisis sentimen review Google Play Store - -Arsitektur: LSTM (atau variannya seperti Bi-LSTM / model berbasis Transformer). - -Justifikasi: Ulasan teks adalah data sekuensial linguistik di mana arti suatu kalimat sangat bergantung pada urutan dan konteks kata di sekitarnya. LSTM secara efektif menangani panjang kalimat yang bervariasi dan mampu mempertahankan konteks makna dari awal hingga akhir ulasan untuk menentukan polaritas sentimen positif atau negatif secara akurat. - -(d) Prediksi churn pelanggan dari 15 kolom tabular - -Arsitektur: ML Klasik (seperti XGBoost, LightGBM, atau Random Forest). - -Justifikasi: Pada data tabular berdimensi kecil (15 fitur), model gradient boosted decision trees secara konsisten mengungguli deep learning dalam hal performa generalisasi, kecepatan latih, dan interpretasi fitur (feature importance). Jaringan saraf seperti ANN cenderung membutuhkan volume sampel yang jauh lebih besar dan rentan overfitting pada batas keputusan data tabular yang tidak terstruktur secara spasial. \ No newline at end of file diff --git a/task3-model-selection/model_selection_examples.py b/task3-model-selection/model_selection_examples.py deleted file mode 100644 index 2ddf858..0000000 --- a/task3-model-selection/model_selection_examples.py +++ /dev/null @@ -1,47 +0,0 @@ -import numpy as np -import tensorflow as tf -from tensorflow import keras -from keras.layers import Conv2D, Dense, Embedding, Flatten, LSTM, MaxPooling2D -from keras.models import Sequential -from xgboost import XGBClassifier - -# (a) Prediksi Stok Barang (LSTM) -# Input shape: (samples, time_steps=12, features=1) -model_a = Sequential([ - LSTM(32, input_shape=(12, 1)), - Dense(1) -]) -model_a.compile(optimizer='adam', loss='mse') - -# (b) Klasifikasi Foto Produk Rusak vs Normal (CNN) -# Input shape contoh citra RGB 128x128 -model_b = Sequential([ - Conv2D(32, (3, 3), activation='relu', input_shape=(128, 128, 3)), - MaxPooling2D((2, 2)), - Flatten(), - Dense(64, activation='relu'), - Dense(1, activation='sigmoid') # binary: rusak vs normal -]) -model_b.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) - -# (c) Analisis Sentimen Ulasan Play Store (LSTM + Embedding) -vocab_size = 5000 -max_length = 100 - -model_c = Sequential([ - Embedding(input_dim=vocab_size, output_dim=64, input_length=max_length), - LSTM(64), - Dense(32, activation='relu'), - Dense(1, activation='sigmoid') # binary: positif vs negatif -]) -model_c.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) - -# (d) Prediksi Churn Pelanggan Tabular (ML Klasik - XGBoost) -# X_train memiliki dimensi (n_samples, 15) -model_d = XGBClassifier( - n_estimators=100, - max_depth=4, - learning_rate=0.1, - random_state=42 -) -# model_d.fit(X_train, y_train) \ No newline at end of file diff --git a/task4-cnn/README.md.md b/task4-cnn/README.md.md deleted file mode 100644 index cf53f55..0000000 --- a/task4-cnn/README.md.md +++ /dev/null @@ -1,333 +0,0 @@ -# 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\\.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) -``` diff --git a/task4-cnn/requirements.txt b/task4-cnn/requirements.txt deleted file mode 100644 index c675797..0000000 --- a/task4-cnn/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -tensorflow>=2.16 -numpy -matplotlib diff --git a/task4-cnn/task4_cnn.py b/task4-cnn/task4_cnn.py deleted file mode 100644 index bf1d359..0000000 --- a/task4-cnn/task4_cnn.py +++ /dev/null @@ -1,184 +0,0 @@ -""" -Tugas No. 4 - Implementasi CNN sederhana untuk MNIST -dan perbandingannya dengan MLP dari Tugas No. 1. - -Cara menjalankan di VS Code: - 1. Aktifkan virtual environment - 2. pip install tensorflow numpy matplotlib - 3. Klik tombol Run, atau jalankan: python task4_cnn.py - -Dataset akan diunduh otomatis saat pertama kali dijalankan -dan disimpan di ~/.keras/datasets/ -""" - -import os - -# Sembunyikan log informasi TensorFlow (harus sebelum import tensorflow) -os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2" - -import time - -import matplotlib -matplotlib.use("Agg") # simpan plot sebagai file, tidak membuka jendela -import matplotlib.pyplot as plt -import numpy as np -import tensorflow as tf -import keras -from keras import layers - -#Konfigurasi -SEED = 42 -EPOCHS = 10 -BATCH_SIZE = 128 -VAL_SPLIT = 0.1 - -tf.random.set_seed(SEED) -np.random.seed(SEED) - -# Hasil MLP terbaik dari Tugas No. 1 (Model C: 256-128-64). -# Ganti angka di bawah ini dengan hasil eksperimen Anda sendiri. -MLP_ACCURACY = 0.9764 -MLP_PARAMS = 242_762 -MLP_EPOCH_TIME = 2.50 - -#1. Load dan preprocessing data -print("Memuat dataset MNIST...") -(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data() - -print(f"Data training : {x_train.shape[0]:,} gambar") -print(f"Data testing : {x_test.shape[0]:,} gambar") -print(f"Ukuran gambar : {x_train.shape[1]} x {x_train.shape[2]} piksel\n") - -# ormalisasi nilai piksel dari 0-255 menjadi 0-1 -x_train = x_train.astype("float32") / 255.0 -x_test = x_test.astype("float32") / 255.0 - -#CNN membutuhkan dimensi channel: (N, 28, 28) -> (N, 28, 28, 1) -#Berbeda dengan MLP yang meratakan gambar menjadi (N, 784) -x_train = x_train.reshape(-1, 28, 28, 1) -x_test = x_test.reshape(-1, 28, 28, 1) - -#2. Bangun model CNN - -model = keras.Sequential( - name="cnn_mnist", - layers=[ - layers.Input(shape=(28, 28, 1)), - - # Blok konvolusi 1: deteksi fitur sederhana (tepi, garis) - layers.Conv2D(32, (3, 3), activation="relu"), - layers.MaxPooling2D((2, 2)), - - # Blok konvolusi 2: gabungkan menjadi fitur lebih kompleks - layers.Conv2D(64, (3, 3), activation="relu"), - layers.MaxPooling2D((2, 2)), - - # Klasifikasi - 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"], -) - -model.summary() - -# 3. Training dengan pencatatan waktu per epoch -epoch_times = [] - -class TimeCallback(keras.callbacks.Callback): - """Mencatat durasi setiap epoch.""" - - def on_epoch_begin(self, epoch, logs=None): - self._start = time.time() - - def on_epoch_end(self, epoch, logs=None): - epoch_times.append(time.time() - self._start) - - -print("\nMemulai training CNN...") -print("Perkiraan waktu: 15-20 detik per epoch di CPU (total sekitar 3 menit).\n") - -history = model.fit( - x_train, - y_train, - validation_split=VAL_SPLIT, - epochs=EPOCHS, - batch_size=BATCH_SIZE, - verbose=2, - callbacks=[TimeCallback()], -) -# 4. Evaluasi -test_loss, test_acc = model.evaluate(x_test, y_test, verbose=0) -n_params = model.count_params() -avg_epoch_time = float(np.mean(epoch_times)) - -predictions = np.argmax(model.predict(x_test, verbose=0), axis=1) -n_wrong = int(np.sum(predictions != y_test)) - -# 5. Perbandingan CNN vs MLP -error_mlp = (1 - MLP_ACCURACY) * 100 -error_cnn = (1 - test_acc) * 100 -gain_point = (test_acc - MLP_ACCURACY) * 100 -error_reduction = (1 - error_cnn / error_mlp) * 100 - -print("\n" + "=" * 62) -print("HASIL EKSPERIMEN CNN") -print("=" * 62) -print(f"Test accuracy : {test_acc * 100:.2f}%") -print(f"Test loss : {test_loss:.4f}") -print(f"Jumlah parameter : {n_params:,}") -print(f"Waktu training/epoch : {avg_epoch_time:.2f} detik") -print(f"Salah klasifikasi : {n_wrong} dari {len(y_test):,} gambar") - -print("\n" + "=" * 62) -print("PERBANDINGAN CNN vs MLP") -print("=" * 62) -print(f"{'Metrik':<24}{'MLP':>14}{'CNN':>14}") -print("-" * 62) -print(f"{'Test accuracy':<24}{MLP_ACCURACY * 100:>13.2f}%{test_acc * 100:>13.2f}%") -print(f"{'Error rate':<24}{error_mlp:>13.2f}%{error_cnn:>13.2f}%") -print(f"{'Jumlah parameter':<24}{MLP_PARAMS:>14,}{n_params:>14,}") -print(f"{'Waktu/epoch (detik)':<24}{MLP_EPOCH_TIME:>14.2f}{avg_epoch_time:>14.2f}") -print("-" * 62) -print(f"Improvement akurasi : +{gain_point:.2f} poin persentase") -print(f"Pengurangan error rate : {error_reduction:.1f}% (relatif)") -print(f"Selisih parameter : {n_params - MLP_PARAMS:+,}") -print("=" * 62) - -# 6. Simpan grafik -fig, axes = plt.subplots(1, 2, figsize=(12, 4.5)) - -epochs_range = range(1, EPOCHS + 1) -axes[0].plot(epochs_range, history.history["accuracy"], label="Train accuracy") -axes[0].plot(epochs_range, history.history["val_accuracy"], label="Validation accuracy") -axes[0].set_title("Learning Curve CNN") -axes[0].set_xlabel("Epoch") -axes[0].set_ylabel("Accuracy") -axes[0].legend() -axes[0].grid(alpha=0.3) - -axes[1].bar( - ["MLP terbaik", "CNN"], - [MLP_ACCURACY * 100, test_acc * 100], - color=["#55A868", "#C44E52"], -) -axes[1].set_ylim(96, 100) -axes[1].set_ylabel("Test Accuracy (%)") -axes[1].set_title("Perbandingan MLP vs CNN") -for i, value in enumerate([MLP_ACCURACY * 100, test_acc * 100]): - axes[1].text(i, value + 0.05, f"{value:.2f}%", ha="center") - -plt.tight_layout() -plt.savefig("hasil_cnn.png", dpi=130) -print("\nGrafik disimpan sebagai: hasil_cnn.png") - -# Simpan model terlatih agar tidak perlu training ulang -model.save("model_cnn_mnist.keras") -print("Model disimpan sebagai: model_cnn_mnist.keras")