Decision tree, dalam bahasa Indonesia disebut pohon keputusan, memisahkan ruang fitur dengan pertanyaan bertingkat yang berbentuk sederhana, misalnya apakah suatu fitur berada di bawah nilai tertentu. Model ini termasuk yang paling mudah dibaca karena keputusan akhirnya dapat ditelusuri dari akar hingga daun. Topik ini membahas kriteria pemisahan gini dan entropy, kontrol kedalaman dengan parameter max_depth, serta cara membaca struktur pohon dan kepentingan fiturnya. Semua contoh dijalankan pada dataset iris dan data sintetis make_moons bawaan scikit-learn.
Pertanyaan bertingkat dan kriteria gini#
Pohon keputusan membangun dirinya secara berulang. Pada setiap simpul, algoritma memeriksa seluruh kombinasi fitur dan ambang yang mungkin, lalu memilih pertanyaan yang paling berhasil memisahkan sampel menurut kelasnya. Data kemudian terbagi menjadi dua anak simpul, dan proses yang sama diulang pada setiap anak sampai kondisi berhenti tercapai, misalnya kedalaman maksimum terlampaui atau simpulnya sudah berisi satu kelas saja. Hasil akhirnya berupa pohon yang setiap jalur dari akar ke daunnya merupakan rangkaian pertanyaan dengan satu jawaban kelas di ujungnya.
Keberhasilan pemisahan diukur dengan ukuran ketidakmurnian (impurity), yaitu angka yang menyatakan seberapa bercampurnya kelas dalam satu simpul. Ukuran yang paling umum adalah indeks gini:
dengan menyatakan proporsi sampel kelas k pada simpul tersebut dan K adalah jumlah kelas. Simpul yang berisi satu kelas tunggal memiliki gini nol, sedangkan simpul dengan kelas tercampur rata memiliki gini mendekati nilai terbesarnya. Alternatif lain adalah entropy, yaitu ukuran ketidakmurnian yang dihitung dari logaritma proporsi kelas dan dipilih melalui parameter criterion="entropy". Pada praktiknya keduanya sering menghasilkan pohon yang mirip, sehingga gini dengan nilai bawaannya menjadi pilihan yang wajar.
Kedalaman pohon dan overfitting#
Parameter max_depth membatasi panjang rantai pertanyaan, sehingga menjadi saklar utama antara model yang terlalu sederhana dan model yang menghafal data. Pohon tanpa batas kedalaman akan terus memecah data sampai setiap daunnya murni, termasuk memisahkan titik-titik kebisingan (noise) yang sebenarnya tidak dapat diprediksi. Program berikut membandingkan kedua keadaan itu pada data make_moons, yaitu dua kelompok berbentuk bulan sabit yang saling bertumpang tindih.
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
X, y = make_moons(n_samples=400, noise=0.3, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.25, stratify=y, random_state=42
)
for kedalaman, label in [(None, "tak dibatasi"), (3, "max_depth=3")]:
pohon = DecisionTreeClassifier(max_depth=kedalaman, random_state=42)
pohon.fit(X_train, y_train)
print(f"Pohon {label:>13}: train={pohon.score(X_train, y_train):.3f}, "
f"test={pohon.score(X_test, y_test):.3f}, "
f"daun={pohon.get_n_leaves()}")Pohon tak dibatasi: train=1.000, test=0.870, daun=39
Pohon max_depth=3: train=0.877, test=0.930, daun=7Perbandingan ini memperlihatkan pola overfitting dalam bentuk yang paling murni. Pohon tak dibatasi mencapai akurasi train 1.000 dengan 39 daun, yang berarti setiap sampel data latih diklasifikasikan sempurna, tetapi akurasi testnya hanya 0.870. Pohon berkedalaman tiga hanya mencapai 0.877 pada data latih, jauh dari sempurna, namun akurasi testnya justru lebih tinggi di angka 0.930. Selisih train dan test pada pohon tak dibatasi mencapai 0.130, sedangkan pohon dangkal hanya 0.053, karena pohon dangkal tidak sempat menyesuaikan kebisingan data latih. Menahan kompleksitas model dapat menaikkan skor pada data baru, dan pada pohon keputusan, kedalaman adalah kendali yang paling murah untuk itu.
Membaca struktur pohon#
Keterinterpretasian pohon dapat dilihat langsung dari strukturnya. Pada dataset iris, pohon berkedalaman dua yang hanya menggunakan panjang dan lebar kelopak sudah mampu mengklasifikasikan hampir seluruh sampel. Diagram berikut menggambarkan struktur pohon tersebut, kemudian teks yang setara dihasilkan kembali oleh export_text sehingga keduanya dapat dibandingkan secara langsung. Format teks semacam itu aman dibaca kapan saja tanpa perangkat gambar, sehingga cocok untuk catatan eksperimen dan tinjauan kode.
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier, export_text
iris = load_iris()
# pohon kecil: dua fitur dan kedalaman dua agar strukturnya mudah dibaca
X = iris.data[:, [2, 3]] # panjang kelopak dan lebar kelopak
y = iris.target
pohon = DecisionTreeClassifier(max_depth=2, random_state=42)
pohon.fit(X, y)
print(export_text(pohon, feature_names=["panjang kelopak", "lebar kelopak"]))
print("Akurasi data latih:", round(pohon.score(X, y), 3))|--- panjang kelopak <= 2.45
| |--- class: 0
|--- panjang kelopak > 2.45
| |--- lebar kelopak <= 1.75
| | |--- class: 1
| |--- lebar kelopak > 1.75
| | |--- class: 2
Akurasi data latih: 0.96Teks keluaran sama persis dengan diagramnya. Pertanyaan pertama, panjang kelopak di bawah 2.45, memisahkan seluruh kelas setosa dari dua kelas lainnya tanpa kesalahan. Sampel yang lolos ke cabang kanan lalu diuji dengan lebar kelopak di bawah 1.75 untuk memisahkan versicolor dan virginica. Dua pertanyaan saja sudah menghasilkan akurasi data latih 0.96, yang menunjukkan sifat khas pohon keputusan, yaitu aturan yang pendek dan dapat dipertanggungjawabkan. Kualitas ini menjadikan pohon keputusan pilihan utama ketika model perlu dijelaskan kepada pihak yang bukan pemodel data.
Kepentingan fitur#
Selain membaca strukturnya, kontribusi setiap fitur dapat dirangkum menjadi satu angka melalui atribut feature_importances_. Angka tersebut dihitung dari total penurunan ketidakmurnian yang disumbang setiap fitur pada seluruh pemisahan, kemudian dinormalkan sehingga jumlahnya satu. Nilainya berguna untuk membandingkan fitur pada satu model, tetapi bukan ukuran sebab akibat, karena fitur yang berkorelasi dengan fitur penting lain dapat memperoleh porsi yang kecil.
import numpy as np
from sklearn.datasets import make_moons
from sklearn.tree import DecisionTreeClassifier
X, y = make_moons(n_samples=400, noise=0.3, random_state=42)
pohon = DecisionTreeClassifier(max_depth=3, random_state=42)
pohon.fit(X, y)
importance = pohon.feature_importances_
for nama, nilai in zip(["fitur 1", "fitur 2"], importance):
print(f"{nama}: {nilai:.3f}")fitur 1: 0.381
fitur 2: 0.619Kedua fitur make_moons sama-sama dibutuhkan, tetapi porsi kepentingannya tidak sama, yaitu 0.619 berbanding 0.381. Pohon menemukan bahwa sebagian besar pemisahan yang paling efektif terjadi pada fitur kedua, sehingga fitur itu menyerap porsi penurunan gini yang lebih besar. Angka ini konsisten dengan struktur pohon yang dibaca pada bagian “Membaca struktur pohon”, yang menempatkan fitur yang paling informatif di akar. Pada data dengan banyak fitur, rangkuman ini menjadi titik awal yang murah sebelum pemeriksaan fitur yang lebih menyeluruh dilakukan, dan nilainya akan berbeda antarmodel karena setiap model membagi kontribusinya dengan caranya sendiri.
Kesalahan umum#
Kesalahan pertama adalah melatih pohon tanpa batas kedalaman pada data berukuran kecil hingga menengah. Pohon yang bebas akan menghafal kebisingan data latih hingga akurasi train sempurna, sementara akurasi testnya menurun, sebagaimana terukur pada contoh make_moons di atas. Penyembuhannya murah, yaitu menetapkan max_depth atau parameter pengendali kompleksitas lainnya seperti min_samples_leaf.
Kesalahan kedua adalah menyertakan StandardScaler pada pipeline pohon karena terbawa kebiasaan dari model lain. Pohon hanya membandingkan satu fitur dengan satu ambang, sehingga penyetaraan skala tidak mengubah pohonnya sama sekali dan hanya menambah satu langkah praproses yang tidak berguna. Pembahasan lengkapnya ada pada topik Mengapa Scaling Diperlukan.
Kesalahan ketiga adalah membaca feature_importances_ sebagai bukti hubungan sebab akibat. Nilainya mewakili kontribusi pada satu model tertentu, dan fitur yang saling berkorelasi dapat saling membagi porsi secara tidak proporsional. Kesimpulan tentang fitur perlu diperkuat dengan pemeriksaan lain sebelum dilaporkan, misalnya dengan mengulang pelatihan pada subset fitur yang berbeda untuk menguji kestabilannya.
Ringkasan#
- Pohon keputusan memecah data berulang dengan pertanyaan satu fitur dan satu ambang, dipilih menurut penurunan ketidakmurnian gini atau entropy.
max_depthmengendalikan kompleksitas pohon, dan pada make_moons pohon berkedalaman tiga mengalahkan pohon tak dibatasi pada data uji dengan skor 0.930 berbanding 0.870.- Struktur pohon dapat dibaca langsung melalui
export_text, sehingga setiap prediksi dapat dijelaskan sebagai rangkaian pertanyaan. feature_importances_merangkum kontribusi fitur menjadi angka berjumlah satu, tetapi bukan ukuran sebab akibat.
Referensi#
- 1.10. Decision Trees — scikit-learn documentation — Bagian user guide yang mengulas kriteria gini, entropy, dan pengendalian kompleksitas pohon.
- sklearn.tree.DecisionTreeClassifier — scikit-learn documentation
— Rujukan parameter
max_depth,criterion, serta atributfeature_importances_. - sklearn.datasets.make_moons — scikit-learn documentation — Dataset sintetis dua bulan sabit yang digunakan pada demonstrasi overfitting.
- sklearn.datasets.load_iris — scikit-learn documentation — Dataset iris yang digunakan pada demonstrasi struktur pohon.