Belajar AI #23: Proyek Kecil — Klasifikasi dengan Python dari Nol sampai Akurasi

Teori sudah berhimpun di 22 episode pertama. Sekarang saatnya bukti: satu proyek kecil, dari nol sampai model menghasilkan angka akurasi. Saya pilih dataset iris — klasik, kecil, dan bisa dijalankan di laptop apa pun tanpa GPU. Tujuannya bukan angka akurasi setinggi mungkin, tapi membiasakan otot alur kerja ML: load data, split, train, evaluasi. Kalau Anda belum pernah menyelesaikan satu siklus penuh, episode ini teman yang pas.

Rencana Proyek

  • Dataset iris: 150 sampel bunga, 4 fitur (panjang/lebar sepal & petal), 3 kelas.
  • Model: RandomForestClassifier — kuat, minim tuning, cocok untuk baseline.
  • Metrik: accuracy plus classification report per kelas.
  • Semua dalam satu file Python yang bisa dijalankan ulang kapan saja.

Mengenal Dataset Iris

Sebelum menulis kode satu baris pun, penting untuk memahami data yang akan kita gunakan. Dataset iris adalah salah satu dataset paling ikonik di dunia machine learning. Dataset ini pertama kali diperkenalkan oleh ahli biologi dan statistikawan Inggris, Ronald A. Fisher, dalam makalahnya tahun 1936 berjudul “The Use of Multiple Measurements in Taxonomic Problems.” Fisher mengumpulkan pengukuran tiga spesies bunga iris yang tumbuh di wilayah Gaspé Peninsula, Kanada: Iris setosa, Iris versicolor, dan Iris virginica.

Setiap sampel terdiri dari empat fitur numerik: panjang dan lebar sepal, serta panjang dan lebar petal. Dari 150 sampel, masing-masing spesies memiliki 50 sampel. Yang menarik, Iris setosa sangat mudah dibedakan dari dua spesies lainnya — garis pemisahnya hampir linear. Sementara Iris versicolor dan Iris virginica memiliki sedikit tumpang tindih, menjadikannya tantangan klasifikasi yang realistis untuk dataset berukuran kecil.

Kenapa dataset ini menjadi favorit komunitas ML? Alasannya sederhana: ukurannya kecil sehingga proses training cepat, strukturnya bersih tanpa missing values, dan distribusinya cukup seimbang. Sebagai “Hello World” machine learning, dataset iris sudah terbukti oleh jutaan praktisi selama hampir satu dekade. Memahami dataset ini berarti memahami pola pikir dasar klasifikasi.

Kode Lengkap

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report

# 1. Load data
iris = load_iris()
X, y = iris.data, iris.target

# 2. Train/test split
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

# 3. Train
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)

# 4. Evaluasi
y_pred = model.predict(X_test)
print("Akurasi:", accuracy_score(y_test, y_pred))
print(classification_report(y_test, y_pred, target_names=iris.target_names))

importance = dict(zip(iris.feature_names, model.feature_importances_.round(3)))
print("Feature importance:", importance)

Jalankan dengan python klasifikasi_iris.py. Di mesin saya hasilnya akurasi tinggi di kisaran 90%+ — wajar untuk dataset semudah iris; jangan jadikan ini tolok ukur kesulitan ML.

Memecah Kode Baris per Baris

Bagi yang baru pertama kali membaca kode Python untuk ML, mari kita bedah setiap bagian agar tidak ada yang terasa seperti “kotak hitam.”

Impor library. Empat baris pertama mengimpor alat yang kita butuhkan. load_iris() menyediakan dataset siap pakai. train_test_split membagi data. RandomForestClassifier adalah model kita. Dan dari sklearn.metrics kita ambil fungsi untuk mengukur seberapa baik model bekerja. Anggap seperti menyiapkan perkakas sebelum mulai kerja: palu, meteran, obeng, dan bor — masing-masing punya peran spesifik.

Load data. load_iris() mengembalikan objek Bunch (semacam dictionary) yang berisi data (numpy array 150×4) dan target (array 150 berisi angka 0, 1, 2 untuk masing-masing spesies). Kita memisahkan keduanya ke X (fitur) dan y (label). Pemisahan ini konsisten di seluruh framework ML: X selalu fitur, y selalu target.

Train/test split. Baris ini membagi data menjadi 80% latih dan 20% uji. Parameter random_state=42 menjamin hasil yang sama setiap kali dijalankan — bayangkan sebagai nomor benih acak yang tetap. stratify=y memastikan proporsi ketiga spesies sama di set latih maupun uji. Tanpa stratifikasi, bisa saja satu spesies tidak muncul sama sekali di data uji, yang akan membuat evaluasi menyesatkan.

Training model. RandomForestClassifier(n_estimators=100) membuat hutan dengan 100 pohon keputusan. model.fit(X_train, y_train) meminta model belajar pola dari data latih. Di sinilah “magis” terjadi — model menemukan kombinasi fitur yang membedakan satu spesies dari lainnya. Proses ini biasanya selesai dalam hitungan milidetik untuk dataset iris.

Evaluasi. model.predict(X_test) menghasilkan prediksi untuk data yang belum pernah dilihat model. accuracy_score menghitung persentase prediksi yang benar. classification_report memberikan rincian precision, recall, dan f1-score per kelas — penting untuk mengetahui apakah model adil terhadap semua kelas atau hanya jago di satu kelas saja.

Feature importance. Dua baris terakhir menampilkan seberapa besar kontribusi tiap fitur terhadap keputusan model. Untuk iris, petal length dan petal width biasanya mendominasi — sesuai intuisi botani bahwa ukuran petal paling membedakan spesies.

Apa yang Terjadi di Balik Layar: RandomForest

RandomForest terasa seperti “one-click magic” — cukup panggil fit(), lalu dapatkan hasil. Tapi di balik kemudahan itu ada mekanisme yang cerdas. RandomForest adalah jenis ensemble learning, yaitu teknik yang menggabungkan banyak model sederhana untuk menghasilkan satu model yang lebih kuat.

Bayangkan sebuah ruangan berisi 100 pakar botani. Setiap pakar diberi subset acak dari data latih dan subset acak dari empat fitur yang tersedia. Setiap pakar kemudian membuat “pohon keputusan” — serangkaian pertanyaan ya/tidak yang membagi data menjadi kelompok-kelompok murni. Misalnya: “Apah panjang petal lebih dari 2.5 cm?” → kalau ya, arahkan ke satu cabang; kalau tidak, ke cabang lain.

Saat model harus memprediksi spesies bunga baru, semua 100 pakar memberikan suara masing-masing. Spesies yang mendapat suara terbanyak itulah yang dipilih. Inilah mengapa disebut “random” — karena ada unsur keacakan di dua tempat: (1) subset data latih untuk tiap pohon (bagging) dan (2) subset fitur yang dipertimbangkan di setiap percabangan. Keacakan ini justru mengurangi risiko overfitting karena tidak ada satu pohon yang melihat seluruh data atau seluruh fitur.

Konsep ini mirip dengan polling demokrasi: satu orang bisa salah, tapi jika seratus orang dengan latar belakang berbeda memberikan jawaban, mayoritasnya cenderung benar. Dalam istilah statistik, ini menurunkan variance tanpa menambah bias secara signifikan — keseimbangan inilah yang menjadikan RandomForest sangat populer untuk baseline awal.

Kenapa Tiap Langkah Penting

  • random_state tetap: supaya hasil reproducible — versi “seed” dunia ML.
  • stratify=y: proporsi kelas di train dan test tetap seimbang.
  • test_size=0.2: 80/20 adalah titik awal umum untuk dataset kecil.
  • Evaluasi di test set terpisah: menilai model dari data latihnya sendiri itu seperti ujian dengan kunci jawaban di tangan.

Eksperimen Lanjutan

Setelah baseline jalan, coba variasikan untuk merasakan pengaruh tiap keputusan. Berikut beberapa percobaan yang saya rekomendasikan beserta kode singkatnya.

Mengganti Model

RandomForest bukan satu-satunya pilihan. Scikit-learn menyediakan banyak algoritma klasifikasi yang bisa di-swap dengan hanya mengganti satu baris impor dan satu baris inisialisasi. Berikut tiga alternatif yang layak dicoba beserta karakteristik masing-masing:

SVM (Support Vector Machine) — mencari hyperplane terbaik yang memisahkan kelas dengan margin terbesar. SVM sangat efektif pada dataset berdimensi tinggi, tapi membutuhkan scaling fitur terlebih dahulu karena sensitif terhadap rentang nilai. Gunakan from sklearn.svm import SVC lalu SVC(kernel='rbf', gamma='scale').

KNN (K-Nearest Neighbors) — tidak benar-benar “melatih” model; ia menyimpan seluruh data latih dan saat prediksi, mencari K tetangga terdekat lalu mengambil suara mayoritas. Sederhana tapi bisa lambat pada dataset besar. Gunakan from sklearn.neighbors import KNeighborsClassifier lalu KNeighborsClassifier(n_neighbors=5). Perhatikan bagaimana akurasi berubah saat K diubah antara 1, 3, 5, 7, dan 10.

Neural Network (MLPClassifier) — jaringan saraf tiruan sederhana dengan satu atau dua hidden layer. Untuk dataset kecil seperti iris, ini seringkali overkill, tapi berguna untuk latihan memahami konsep hidden layer dan neuron. Gunakan from sklearn.neural_network import MLPClassifier lalu MLPClassifier(hidden_layer_sizes=(10, 5), max_iter=500, random_state=42).

Tuning Hyperparameter

Selain mengganti model, bereksperimen dengan hyperparameter mengajarkan kita tentang sensitivitas model terhadap konfigurasi. Untuk RandomForest, coba variasikan: n_estimators (jumlah pohon: 10, 50, 100, 200, 500), max_depth (kedalaman pohon: None, 3, 5, 10), dan max_features (‘sqrt’, ‘log2’, atauNone). Perhatikan pola: jumlah pohon meningkatkan stabilitas tapi dengan diminishing returns, sementara membatasi kedalaman pohon dapat mencegah overfitting pada dataset kecil.

Menggunakan Cross-Validation

Satu split train/test bisa saja beruntung atau sial — hasilnya berbeda-beda tergantung data mana yang masuk ke test set. Cross-validation menyelesaikan masalah ini dengan membagi data menjadi K lipatan (fold), lalu melatih dan mengevaluasi K kali sehingga setiap data menjadi test set tepat sekali. Gunakan:

from sklearn.model_selection import cross_val_score
scores = cross_val_score(model, X, y, cv=5)
print("Akurasi per fold:", scores)
print("Rata-rata:", scores.mean(), "±", scores.std())

Selisih antara fold tertinggi dan terendah menunjukkan stabilitas model. Jika selisihnya besar, model mungkin sensitif terhadap komposisi data tertentu.

Visualisasi: Confusion Matrix

Angka akurasi keseluruhan sering menutupi masalah pada kelas tertentu. Confusion matrix menunjukkan secara detail berapa banyak prediksi yang benar dan salah untuk tiap pasangan kelas aktual vs prediksi. Berikut contoh output yang mungkin dihasilkan:

Prediksi ↓ / Aktual →setosaversicolorvirginica
setosa1000
versicolor091
virginica0010

Dari tabel di atas terlihat bahwa Iris setosa dan Iris virginica diprediksi dengan sempurna. Namun ada satu sampel versicolor yang salah diklasifikasikan sebagai virginica — ini wajar karena kedua spesies tersebut memang memiliki fitur yang agak tumpang tindih. Untuk membuat confusion matrix sendiri, jalankan kode berikut:

from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
import matplotlib.pyplot as plt

cm = confusion_matrix(y_test, y_pred)
disp = ConfusionMatrixDisplay(cm, display_labels=iris.target_names)
disp.plot(cmap=plt.cm.Blues)
plt.title("Confusion Matrix — Klasifikasi Iris")
plt.tight_layout()
plt.savefig("confusion_matrix_iris.png", dpi=150)
plt.show()

Visualisasi ini memudahkan identifikasi pola kesalahan secara langsung. Warna yang lebih gelap di diagonal menunjukkan prediksi yang benar, sementara kotak non-diagonal menunjukkan kesalahan klasifikasi.

Kesalahan Umum yang Saya Temui

Saat pertama kali menjalankan proyek ini, saya menghadapi beberapa jebakan yang ternyata cukup umum di kalangan pemula:

Mengevaluasi model di data training. Kesalahan paling klasik — saya awalnya hanya mencetak akurasi dari model.score(X_train, y_train) dan terkejut karena nilainya selalu 100%. Ternyata itu wajar karena model sudah “melihat” data tersebut. Pelajaran: selalu pisahkan data uji.

Melupakan scaling. Saat saya mencoba SVM, akurasi menurun drastis. Ternyata fitur iris memiliki rentang nilai yang berbeda-beda (sepal length ~4-7 cm, petal width ~0.1-2.5 cm). SVM sangat sensitif terhadap skala fitur. Solusinya: tambahkan StandardScaler sebelum training. RandomForest tidak membutuhkan scaling karena membagi data berdasarkan threshold, bukan jarak.

Tidak menetapkan random_state. Tanpa random_state, setiap kali menjalankan ulang saya mendapat akurasi berbeda. Ini membingungkan saat mencoba debugging. Menetapkan seed membuat eksperimen lebih terkendali.

Catatan Pribadi: Kesan Pertama Model Berhasil

Ada momen unik yang tidak akan pernah saya lupa: pertama kali menjalankan kode klasifikasi iris dan melihat angka akurasi muncul di terminal. Setelah baca puluhan halaman teori tentang overfitting, train/test split, dan random forest, tiba-tiba saya punya model yang benar-benar bekerja — dalam satu file Python, dijalankan dalam hitungan detik.

Perasaannya campur aduk: lega karena ternyata tidak sesulit yang dibayangkan, sekaligus penasaran — “bagaimana kalau datasetnya lebih besar? Bagaimana kalau fiturnya bukan angka tapi teks atau gambar?” Proyek kecil ini jadi semacam pintu masuk yang memberikan kepercayaan diri: saya bisa membuat model ML yang berfungsi. Dari titik itu, perjalanan belajar jadi lebih menyenangkan karena ada fondasi pengalaman langsung.

Yang Saya Pelajari dari Proyek Ini

Meskipun dataset iris terlihat sederhana, proyek ini mengajarkan beberapa pelajaran fundamental yang berlaku di proyek ML skala mana pun:

Alur kerja ML itu standar. Load, split, train, evaluasi — pola ini berulang di setiap proyek klasifikasi. Bedanya hanya pada kompleksitas data dan modelnya. Menghafal alur ini sekarang berarti menghemat waktu di masa depan.

Baseline sebelum optimasi. RandomForest memberikan hasil yang sudah cukup baik tanpa tuning apa pun. Langkah pertama harus selalu membangun baseline yang solid, baru kemudian berusaha memperbaikinya. Berlomba membuat model sempurna tanpa baseline hanya akan menghasilkan kebingungan karena tidak ada titik perbandingan.

Metrik lebih dari sekadar akurasi. Akurasi keseluruhan bisa menipu, terutama saat kelas tidak seimbang. Classification report dan confusion matrix memberikan gambaran yang jauh lebih lengkap tentang kekuatan dan kelemahan model. Sebagai contoh, sebuah model yang selalu memprediksi kelas mayoritas bisa saja menghasilkan akurasi 90%, tapi sama sekali tidak berguna.

Reproducibility itu penting. random_state bukan sekadar parameter teknis — ini cerminan etika sains: hasil harus bisa direplikasi oleh orang lain. Di dunia machine learning profesional, ketiadaan reproducibility berarti ketiadaan kepercayaan dari tim dan pemangku kepentingan.

Kecil bukan berarti tidak penting. Dataset iris hanya 150 baris dan empat fitur, tapi pelajaran yang didapat dari menyelesaikan satu siklus penuh bernilai lebih dari sekadar membaca seratus halaman teori tanpa praktik. Mulai dari yang kecil, selesaikan, lalu tingkatkan kompleksitasnya secara bertahap.

Dari sini naik kelasnya tinggal ganti dataset — misalnya data tabular sendiri dari pekerjaan sehari-hari — dan alurnya persis sama.

Sumber

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *

Situs ini menggunakan Akismet untuk mengurangi spam. Pelajari bagaimana data komentar Anda diproses