364 lines
12 KiB
Markdown
364 lines
12 KiB
Markdown
# Corn Leaf Disease Classification
|
||
|
||
Pipeline lengkap untuk klasifikasi penyakit daun jagung menggunakan **EfficientNetV2B0**, mulai dari persiapan dataset, pelatihan di Google Colab, hingga ekspor model ke format **TFLite** dan **TensorFlow.js** untuk kebutuhan produksi.
|
||
|
||
---
|
||
|
||
## Daftar Isi
|
||
|
||
1. [Kelas yang Diklasifikasikan](#1-kelas-yang-diklasifikasikan)
|
||
2. [Struktur Proyek](#2-struktur-proyek)
|
||
3. [Prasyarat & Instalasi](#3-prasyarat--instalasi)
|
||
4. [Sumber Dataset](#4-sumber-dataset)
|
||
5. [Tahap 1 — Preprocessing Lokal](#5-tahap-1--preprocessing-lokal)
|
||
6. [Tahap 2 — Upload ke Google Drive & Training di Colab](#6-tahap-2--upload-ke-google-drive--training-di-colab)
|
||
7. [Tahap 3 — Download Model dari Colab](#7-tahap-3--download-model-dari-colab)
|
||
8. [Tahap 4 — Ekspor Model untuk Produksi](#8-tahap-4--ekspor-model-untuk-produksi)
|
||
9. [Output Akhir](#9-output-akhir)
|
||
10. [Troubleshooting](#10-troubleshooting)
|
||
|
||
---
|
||
|
||
## 1. Kelas yang Diklasifikasikan
|
||
|
||
Model dilatih untuk mengenali **4 kelas** kondisi daun jagung:
|
||
|
||
| Label (Bahasa Indonesia) | Deskripsi |
|
||
|---|---|
|
||
| **Bercak Daun** | *Gray Leaf Spot* — bercak abu-abu memanjang pada daun |
|
||
| **Hawar Daun** | *Northern/Southern Leaf Blight* — hawar coklat berbentuk panjang |
|
||
| **Karat Daun** | *Common Rust* — bintik coklat kemerahan berbentuk pustula |
|
||
| **Daun Sehat** | Daun jagung tanpa gejala penyakit |
|
||
|
||
---
|
||
|
||
## 2. Struktur Proyek
|
||
|
||
```
|
||
.
|
||
├── dataset_1.zip # File ZIP dataset 1 (dari Kaggle)
|
||
├── dataset_2.zip # File ZIP dataset 2 (dari Kaggle)
|
||
├── dataset_3.zip # File ZIP dataset 3 (dari SciDB)
|
||
│
|
||
├── preprocessing.py # Skrip persiapan & penggabungan dataset
|
||
├── notebook.ipynb # Notebook pelatihan (dijalankan di Google Colab)
|
||
├── save_model.py # Skrip ekspor model ke TFLite & TensorFlow.js
|
||
│
|
||
├── best_model/
|
||
│ └── best_model.keras # Model hasil training terbaik (diunduh dari Colab)
|
||
│
|
||
├── model/ # Output ekspor (dibuat otomatis)
|
||
│ ├── saved_model/ # Format SavedModel TensorFlow
|
||
│ ├── tfjs_model/ # Format TensorFlow.js
|
||
│ └── model.tflite # Format TFLite untuk Mobile
|
||
│
|
||
├── requirements.txt # Daftar dependensi Python
|
||
└── README.md
|
||
```
|
||
|
||
---
|
||
|
||
## 3. Prasyarat & Instalasi
|
||
|
||
### Kebutuhan Sistem
|
||
- Python **3.9 – 3.11**
|
||
- Akun **Google** (untuk Google Drive & Google Colab)
|
||
- Akun **Kaggle** (untuk mengunduh dataset)
|
||
- Koneksi internet
|
||
|
||
### Instalasi Dependensi
|
||
|
||
Disarankan menggunakan virtual environment:
|
||
|
||
```bash
|
||
# Buat environment baru (opsional tapi dianjurkan)
|
||
python -m venv venv
|
||
source venv/bin/activate # Linux / macOS
|
||
# venv\Scripts\activate # Windows
|
||
|
||
# Instal semua dependensi
|
||
pip install -r requirements.txt
|
||
```
|
||
|
||
---
|
||
|
||
## 4. Sumber Dataset
|
||
|
||
Proyek ini menggabungkan **3 dataset** dari sumber berbeda untuk menghasilkan data yang lebih beragam dan representatif.
|
||
|
||
### Dataset 1 — Kaggle (Corn Leaf Disease - Indonesia)
|
||
> 🔗 https://www.kaggle.com/datasets/ndisan/corn-leaf-disease
|
||
|
||
Berisi gambar penyakit daun jagung dengan label dalam Bahasa Indonesia. Dataset ini memiliki **4 folder**, namun label **"Karat Daun" tidak digunakan** karena gambar di dalamnya tidak merepresentasikan penyakit karat yang sebenarnya.
|
||
|
||
| Folder di Dataset 1 | Tindakan |
|
||
|---|---|
|
||
| `Bercak Daun/` | Digunakan |
|
||
| `Hawar Daun/` | Digunakan |
|
||
| `Daun Sehat/` | Digunakan (sebagai tambahan) |
|
||
| `Karat Daun/` | **Dibuang** — data tidak representatif |
|
||
|
||
### Dataset 2 — Kaggle (Corn or Maize Leaf Disease)
|
||
> 🔗 https://www.kaggle.com/datasets/smaranjitghose/corn-or-maize-leaf-disease-dataset
|
||
|
||
Digunakan untuk **menggantikan** data Karat Daun dari Dataset 1 dan menambah variasi gambar Daun Sehat.
|
||
|
||
| Folder di Dataset 2 | Dipetakan ke Label |
|
||
|---|---|
|
||
| `Common_Rust/` | **Karat Daun** |
|
||
| `Healthy/` | **Daun Sehat** (tambahan) |
|
||
| `Blight/` | Tidak diproses |
|
||
| `Gray_Leaf_Spot/` | Tidak diproses |
|
||
|
||
### Dataset 3 — SciDB (China Agricultural Dataset)
|
||
> 🔗 https://www.scidb.cn/en/detail?dataSetId=19536c73f6d74946a212719a94f53ab3
|
||
|
||
Dataset dengan label berbahasa Mandarin. Digunakan untuk **menambah variasi data** pada tiga kelas utama. Pemetaan label dilakukan menggunakan file `desc.json` yang disertakan dalam dataset.
|
||
|
||
| Label Mandarin | Dipetakan ke Label |
|
||
|---|---|
|
||
| `大斑病` (Hawar Besar) | **Hawar Daun** |
|
||
| `小斑病` (Hawar Kecil) | **Hawar Daun** |
|
||
| `褐斑病` (Bercak Coklat) | **Bercak Daun** |
|
||
| `弯孢霉叶斑病` (Bercak Curvularia) | **Bercak Daun** |
|
||
| `圆斑病` (Bercak Bulat) | **Bercak Daun** |
|
||
| `灰斑病` (Bercak Abu-abu) | **Bercak Daun** |
|
||
| `南方锈病` (Karat Selatan) | **Karat Daun** |
|
||
| `普通锈病` (Karat Biasa) | **Karat Daun** |
|
||
|
||
---
|
||
|
||
## 5. Tahap 1 — Preprocessing Lokal
|
||
|
||
Skrip `preprocessing.py` menjalankan **5 tahap** secara berurutan untuk menyiapkan dataset akhir yang siap diunggah ke Google Drive.
|
||
|
||
### Persiapan
|
||
|
||
Unduh ketiga dataset dari sumber di atas, lalu letakkan file ZIP-nya di direktori yang sama dengan `preprocessing.py`:
|
||
|
||
```
|
||
.
|
||
├── preprocessing.py
|
||
├── dataset_1.zip
|
||
├── dataset_2.zip
|
||
└── dataset_3.zip
|
||
```
|
||
|
||
### Menjalankan Preprocessing
|
||
|
||
```bash
|
||
python preprocessing.py
|
||
```
|
||
|
||
### Alur Kerja Otomatis
|
||
|
||
#### Tahap 1 — Ekstraksi ZIP
|
||
Mengekstrak ketiga file `.zip` menjadi folder masing-masing (`dataset_1/`, `dataset_2/`, `dataset_3/`).
|
||
|
||
#### Tahap 2 — Menggabungkan Dataset 1 & 2
|
||
- Menyalin folder `Bercak Daun`, `Hawar Daun`, dan `Daun Sehat` dari Dataset 1 ke folder `dataset/`.
|
||
- **Folder `Karat Daun` dari Dataset 1 dilewati** karena gambarnya tidak representatif.
|
||
- Mengambil gambar `Common_Rust` dari Dataset 2 → disimpan ke `dataset/Karat Daun/`.
|
||
- Mengambil gambar `Healthy` dari Dataset 2 → digabung ke `dataset/Daun Sehat/`.
|
||
|
||
#### Tahap 3 — Menggabungkan Dataset 3
|
||
- Membaca file `desc.json` dari Dataset 3 yang berisi pasangan nama gambar dan labelnya.
|
||
- Memetakan label Mandarin ke label target (lihat tabel di atas).
|
||
- Menyalin gambar yang relevan ke folder `dataset/` yang sesuai.
|
||
|
||
#### Tahap 4 — Pembersihan Data (Cleaning)
|
||
Menghapus file gambar spesifik yang bermasalah (rusak, duplikat, atau tidak relevan):
|
||
- `CBS28.jpg`
|
||
- `Corn_Common_Rust (1275).jpg`
|
||
- `Corn_Common_Rust (1289).jpg`
|
||
- `Corn_Common_Rust (1295).jpg`
|
||
- `Corn_Gray_Spot (1).jpg`
|
||
|
||
#### Tahap 5 — Kompresi ke ZIP
|
||
Mengemas seluruh folder `dataset/` menjadi `dataset.zip` yang siap diunggah ke Google Drive.
|
||
|
||
### Hasil Akhir Preprocessing
|
||
|
||
```
|
||
dataset/
|
||
├── Bercak Daun/ ← DS1 + DS3
|
||
├── Hawar Daun/ ← DS1 + DS3
|
||
├── Karat Daun/ ← DS2 (Common Rust) + DS3
|
||
└── Daun Sehat/ ← DS1 + DS2 (Healthy)
|
||
|
||
dataset.zip ← File siap upload ke Google Drive
|
||
```
|
||
|
||
---
|
||
|
||
## 6. Tahap 2 — Upload ke Google Drive & Training di Colab
|
||
|
||
### Langkah 1: Upload `dataset.zip` ke Google Drive
|
||
|
||
1. Buka [Google Drive](https://drive.google.com) di browser.
|
||
2. Upload file `dataset.zip` ke lokasi yang mudah diingat, misalnya:
|
||
```
|
||
My Drive/corn_disease/dataset.zip
|
||
```
|
||
|
||
### Langkah 2: Buka Notebook di Google Colab
|
||
|
||
1. Upload `notebook.ipynb` ke Google Drive, atau buka langsung dari Colab:
|
||
- Klik kanan file `notebook.ipynb` di Google Drive → **"Open with"** → **Google Colaboratory**.
|
||
2. Aktifkan GPU: **Runtime** → **Change runtime type** → pilih **T4 GPU**.
|
||
|
||
### Langkah 3: Mount Google Drive di Colab
|
||
|
||
Di sel pertama notebook, jalankan:
|
||
|
||
```python
|
||
from google.colab import drive
|
||
drive.mount('/content/drive')
|
||
```
|
||
|
||
Ikuti instruksi autentikasi yang muncul.
|
||
|
||
### Langkah 4: Ekstrak Dataset di Colab
|
||
|
||
```python
|
||
import zipfile
|
||
|
||
zip_path = '/content/drive/MyDrive/corn_disease/dataset.zip'
|
||
extract_path = '/content/dataset'
|
||
|
||
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
|
||
zip_ref.extractall(extract_path)
|
||
|
||
print("Dataset berhasil diekstrak!")
|
||
```
|
||
|
||
### Langkah 5: Jalankan Training
|
||
|
||
Jalankan seluruh sel di `notebook.ipynb` secara berurutan. Notebook akan melatih model `EfficientNetV2B0` dan menyimpan model terbaik secara otomatis ke:
|
||
|
||
```
|
||
/content/drive/MyDrive/corn_disease/best_model.keras
|
||
```
|
||
|
||
> **Tips:** Aktifkan **"Run all"** dan pantau grafik loss/accuracy. Proses training bisa memakan waktu 30–90 menit tergantung ukuran dataset dan kuota GPU Colab.
|
||
|
||
---
|
||
|
||
## 7. Tahap 3 — Download Model dari Colab
|
||
|
||
Setelah training selesai, unduh `best_model.keras` dari Google Drive ke komputer lokal.
|
||
|
||
### Opsi A: Unduh via Google Drive (Direkomendasikan)
|
||
|
||
1. Buka Google Drive → navigasi ke folder `corn_disease/`.
|
||
2. Klik kanan `best_model.keras` → **Download**.
|
||
3. Letakkan file yang diunduh ke folder `best_model/` di proyek lokal:
|
||
```
|
||
best_model/best_model.keras
|
||
```
|
||
|
||
### Opsi B: Unduh Langsung dari Colab
|
||
|
||
Tambahkan sel berikut di akhir notebook, lalu jalankan:
|
||
|
||
```python
|
||
from google.colab import files
|
||
files.download('/content/drive/MyDrive/corn_disease/best_model.keras')
|
||
```
|
||
|
||
---
|
||
|
||
## 8. Tahap 4 — Ekspor Model untuk Produksi
|
||
|
||
Setelah `best_model/best_model.keras` tersedia di lokal, jalankan skrip ekspor.
|
||
|
||
### Persiapan Struktur Folder
|
||
|
||
Pastikan struktur direktori sudah benar:
|
||
|
||
```
|
||
.
|
||
├── best_model/
|
||
│ └── best_model.keras ← File hasil unduhan dari Colab
|
||
└── save_model.py
|
||
```
|
||
|
||
### Langkah 1: Ekspor ke SavedModel & TFLite
|
||
|
||
```bash
|
||
python save_model.py
|
||
```
|
||
|
||
Skrip ini akan:
|
||
1. Memuat model dari `best_model/best_model.keras`.
|
||
2. Membangun ulang arsitektur **tanpa layer augmentasi** (wajib untuk kompatibilitas TFJS).
|
||
3. Menyalin semua bobot terlatih ke arsitektur baru.
|
||
4. Mengekspor ke `model/saved_model/` (format SavedModel).
|
||
5. Mengonversi ke `model/model.tflite` (format TFLite untuk Android/iOS).
|
||
|
||
### Langkah 2: Konversi ke TensorFlow.js (untuk Web/Browser)
|
||
|
||
Konversi TFJS **harus dilakukan via CLI**, bukan dari dalam Python, untuk menghindari konflik library Protobuf.
|
||
|
||
```bash
|
||
# Langkah 2a: Atur variabel lingkungan
|
||
export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python
|
||
|
||
# Langkah 2b: Konversi
|
||
tensorflowjs_converter \
|
||
--input_format=tf_saved_model \
|
||
--output_format=tfjs_graph_model \
|
||
--signature_name=serving_default \
|
||
--saved_model_tags=serve \
|
||
model/saved_model \
|
||
model/tfjs_model
|
||
```
|
||
|
||
---
|
||
|
||
## 9. Output Akhir
|
||
|
||
Setelah seluruh pipeline selesai dijalankan, berikut file output yang tersedia:
|
||
|
||
| File / Direktori | Format | Kegunaan |
|
||
|---|---|---|
|
||
| `dataset/` | Folder gambar terstruktur | Dataset akhir hasil preprocessing |
|
||
| `dataset.zip` | ZIP | Dataset untuk diupload ke Google Drive / Colab |
|
||
| `best_model/best_model.keras` | Keras | Model terlatih lengkap (dengan optimizer) |
|
||
| `model/saved_model/` | SavedModel (PB) | Inferensi server-side & jembatan konversi TFJS |
|
||
| `model/model.tflite` | TFLite | Inferensi di perangkat **Android / iOS** |
|
||
| `model/tfjs_model/` | TensorFlow.js | Inferensi di **browser / Node.js** |
|
||
|
||
---
|
||
|
||
## 10. Troubleshooting
|
||
|
||
### `FileNotFoundError: dataset_1.zip tidak ditemukan`
|
||
**Solusi:** Pastikan ketiga file ZIP sudah diunduh dan diletakkan di direktori yang sama dengan `preprocessing.py`.
|
||
|
||
---
|
||
|
||
### `FileNotFoundError: Model file not found at best_model/best_model.keras`
|
||
**Solusi:** Unduh `best_model.keras` dari Google Drive/Colab dan letakkan di folder `best_model/`. Pastikan nama filenya tepat.
|
||
|
||
---
|
||
|
||
### `ValueError: incompatible with expected resource` (saat konversi TFJS)
|
||
**Penyebab:** Layer augmentasi data Keras (`random_flip`, dll.) bersifat *stateful* dinamis dan tidak bisa dibekukan oleh konverter TFJS.
|
||
|
||
**Solusi:** Sudah ditangani otomatis oleh fungsi `build_clean_model()` dalam `save_model.py`, yang membangun ulang arsitektur tanpa layer augmentasi sebelum proses ekspor.
|
||
|
||
---
|
||
|
||
### `VersionError: Detected incompatible Protobuf Gencode/Runtime versions`
|
||
**Penyebab:** Konflik antara library C++ Protobuf yang dibawa oleh `tensorflow_decision_forests` dengan *runtime* Python di lingkungan virtual lokal.
|
||
|
||
**Solusi:** Pastikan konversi TFJS dijalankan via **CLI langsung** (bukan `subprocess` dari Python) dengan variabel lingkungan berikut:
|
||
```bash
|
||
export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python
|
||
```
|
||
|
||
---
|
||
|
||
### Sesi Colab terputus saat training
|
||
**Solusi:** Gunakan callback `ModelCheckpoint` di notebook untuk menyimpan checkpoint secara berkala ke Google Drive, sehingga training bisa dilanjutkan dari checkpoint terakhir tanpa mengulang dari awal. |