ml/ library Learn by doing
SUPERVISED LEARNING · PYTHON / JAVASCRIPT

Decision Tree

เปลี่ยนข้อมูลให้เป็นชุดคำถาม

LEARNING LEVEL1
พื้นฐานควรรู้มาก่อน · เงื่อนไขแบบ if–else
ลองใน Playground

01 Overall Concept

OVERALL CONCEPT

ไอเดียหลัก — Decision Tree เรียนรู้ด้วยคำถามแบบ “ใช่หรือไม่” ทีละข้อ เช่น ผลไม้นี้สีแดงไหม หรือมีน้ำหนักเกินเท่านี้ไหม ทุกคำตอบพาเราเดินไปคนละกิ่ง จนถึงปลายทางที่บอกคำทำนาย

ลองนึกภาพว่า — เหมือนเล่นเกมทายสัตว์ เราเริ่มด้วยคำถามว่า “อยู่ในน้ำไหม” แล้วถามต่อว่า “มีครีบไหม” คำถามที่ดีจะช่วยตัดตัวเลือกออกได้มากและพาไปถึงคำตอบเร็ว

ตัวอย่างการนำไปใช้ — จำแนกชนิดพืช คัดแยกคำร้องของลูกค้า ประเมินว่าลูกค้าจะกลับมาซื้อหรือไม่ และงานที่ต้องอธิบายเหตุผลเป็นกฎง่าย ๆ

02 อธิบายภาษาคนเข้าใจง่ายๆ

เล่าแบบไม่ใช้ศัพท์ยาก

Decision Tree คิดเหมือนคนตัดสินใจตาม Flowchart

สมมติเราจะอนุมัติสินเชื่อ

มันอาจสร้างต้นไม้แบบนี้

รายได้ > 50,000 ไหม?

ถ้าไม่ → ดูหนี้ ถ้าใช่ → ดูประวัติชำระเงิน

แล้วถามต่อไปเรื่อยๆ

เคยผิดนัดไหม? มีงานประจำไหม? หนี้เกิน 40% ของรายได้ไหม?

สุดท้ายไปถึงใบไม้ เช่น

อนุมัติ ไม่อนุมัติ

ข้อดีมากๆ คือมนุษย์เข้าใจง่าย เราสามารถเปิดดูเหตุผลได้แทบเหมือนอ่าน Flowchart

ปัญหาคือ Decision Tree ตัวเดียว “ใจร้อน” พอสมควร

ถ้าข้อมูลเปลี่ยนเล็กน้อย ต้นไม้อาจสร้างโครงสร้างต่างไปมาก และถ้าปล่อยให้แตกกิ่งเยอะเกินไปก็ Overfit ได้ง่าย

นี่เป็นเหตุผลที่ภายหลังเกิดเทคนิคอย่าง Random Forest ขึ้นมา

ภาพจำ: เกม 20 Questions — ถามทีละข้อจนรู้ว่าคำตอบคืออะไร

03 How it works

ค่อยๆ ทำไปด้วยกัน ตั้งแต่ข้อมูลแถวแรกจนถึงการตรวจคำตอบ

  1. เตรียมแฟ้มสินเชื่อที่มีคำตอบเก่า

    หนึ่งแถวแทนหนึ่งใบสมัคร X มีรายได้ สัดส่วนหนี้ และประวัติที่ทราบตอนสมัคร ส่วน y เป็นคำตอบเป้าหมาย เช่นผลชำระคืนจริงที่กำหนดช่วงเวลาชัดเจน หากใช้ผลอนุมัติเก่าเป็น y โมเดลจะเรียนแบบการอนุมัติเก่า ไม่ใช่ความเสี่ยงผิดนัดโดยตรง แบ่ง test ก่อนและแปลงหมวดหมู่เป็นตัวเลขให้เหมาะสม

  2. ต้นไม้คิดคำถามแรกเอง

    ตอน fit มันลอง feature กับ threshold หลายแบบ เช่นรายได้ ≤ 50,000 แล้วดูว่าซ้ายกับขวาแยกคลาสได้ดีขึ้นแค่ไหน สำหรับ classification วัดด้วย Gini หรือ entropy ซึ่งสะท้อนความปะปนของคลาส คำถามที่ลดความปะปนรวมโดยถ่วงจำนวนคนแต่ละฝั่งได้ดีที่สุดจะถูกเลือก

  3. ถามต่อจนถึงป้ายคำตอบ

    ต้นไม้ทำขั้นตอนเดิมกับข้อมูลในแต่ละกิ่ง ถ้าฝั่งหนึ่งยังปนหลายคลาสก็ถามเพิ่ม เมื่อถึงเงื่อนไขหยุดจะเก็บสัดส่วนคลาสไว้ที่ใบ เช่นใบหนึ่งมี 8 คนเป็นคลาส A และ 2 คนเป็น B จะทาย A พร้อมสัดส่วน 0.8 ถ้าเป็น DecisionTreeRegressor เปลี่ยนเป็นลดความผิดพลาดของตัวเลขและใช้ค่าเฉลี่ยที่ใบแทน

  4. ตั้งรั้วไม่ให้แตกกิ่งไม่จบ

    เริ่ม DecisionTreeClassifier(max_depth=3, min_samples_leaf=5, random_state=42) แล้ว fit(X_train, y_train) max_depth จำกัดจำนวนชั้นคำถาม min_samples_leaf บังคับให้แต่ละใบมีข้อมูลอย่างน้อยกี่แถว และ criterion เลือกวิธีวัดความปะปน เริ่มจากต้นเล็กจะอ่านกฎและเห็นข้อผิดพลาดง่ายกว่า

  5. เดินตามต้นไม้และตรวจสิ่งที่พลาด

    predict(X_test) จะพาแต่ละแถวเดินตามคำถามจนถึงใบ ใช้ plot_tree(model, feature_names=...) เพื่อเปิดดูโครงสร้าง แล้วดู confusion matrix ว่าพลาดคลาสใด ลองเพิ่ม max_depth ทีละระดับใน validation ถ้า train ดีขึ้นแต่ test ไม่ดีขึ้นให้หยุด การนำไปใช้ตัดสินสินเชื่อจริงยังต้องตรวจคุณภาพข้อมูลและกฎงาน เพราะโมเดลอาจจำความลำเอียงจากคำตอบเก่า

เปิดตัวอย่างโค้ดเพื่อลองทำตาม →ตัวอย่างตัวเลขในเรื่องใช้ช่วยอธิบาย ส่วนโค้ดและ Playground ใช้ชุดข้อมูลสาธิตของแต่ละหน้าอ่านเอกสารอ้างอิงของเทคนิคนี้ ↗

ข้อมูล พารามิเตอร์ และภาพรวมการคำนวณ

DATA INX · featuresy · targetX = [รายได้, สัดส่วนหนี้, ประวัติ] · y = คลาสเป้าหมาย
CALCULATEDecision Tree
max_depthmin_samples_leafcriterion
RESULT0.800.150.05class / probabilityตัวอย่างใบ: A 8 คน, B 2 คน → ทาย A และสัดส่วน 0.8
เส้นทางของข้อมูล: จากค่าที่รับเข้า ผ่านการคำนวณด้วยพารามิเตอร์ ไปเป็นผลลัพธ์
INPUT

ข้อมูลที่รับเข้ามา

รับ X เป็นตารางที่แต่ละคอลัมน์คือคุณลักษณะ และ y เป็นคลาสหรือค่าต่อเนื่อง ตัวเลขและหมวดหมู่ที่เข้ารหัสแล้วใช้เป็นเงื่อนไขแตกกิ่งได้

X = [รายได้, สัดส่วนหนี้, ประวัติ] · y = คลาสเป้าหมาย
PARAMETERS

พารามิเตอร์ที่ใช้

max_depth
จำนวนชั้นคำถามสูงสุดของต้นไม้
min_samples_leaf
จำนวนตัวอย่างขั้นต่ำที่ปลายกิ่งต้องมี
criterion
Classifier ใช้ gini หรือ entropy; squared_error เป็นของ Regressor
OUTPUT

ผลลัพธ์ที่ได้

ได้โครงสร้างต้นไม้ กฎ if–else และคำทำนายหนึ่งค่าต่อแถว พร้อม probability จากสัดส่วนที่ใบ

ตัวอย่างใบ: A 8 คน, B 2 คน → ทาย A และสัดส่วน 0.8
CALCULATION

คำนวณทีละขั้น

  1. 01

    ลองทุก feature และ threshold ที่เป็นไปได้เพื่อแบ่งข้อมูลออกเป็นซ้ายกับขวา

  2. 02

    เลือกคำถามที่ลด impurity แบบถ่วงจำนวนตัวอย่างของแต่ละฝั่งได้ดีที่สุด

  3. 03

    ทำซ้ำในแต่ละกิ่งจนชนเงื่อนไขหยุด แล้วเก็บคลาสเสียงข้างมากหรือค่าเฉลี่ยไว้ที่ใบ

ควรรู้อีกนิด —

04 Make it yours

Python · scikit-learn
# ติดตั้ง: pip install numpy pandas scikit-learn matplotlibimport numpy as npimport pandas as pdimport matplotlib.pyplot as pltfrom sklearn.tree import DecisionTreeClassifier, plot_treefrom sklearn.metrics import accuracy_score # ดาวน์โหลด sample.csv จาก Playground ไว้ข้างไฟล์นี้df = pd.read_csv("sample.csv")X, y = df[["x", "y"]], df["label"]is_test = np.arange(len(df)) % 5 == 0  # test 20%, ชุดเดียวกับเว็บ model = DecisionTreeClassifier(    max_depth=3,         # ความลึกมากขึ้น = กฎที่ละเอียดขึ้น    min_samples_leaf=3,  # จำนวนตัวอย่างขั้นต่ำในแต่ละใบ    criterion="gini",    random_state=42,)model.fit(X[~is_test], y[~is_test])pred = model.predict(X[is_test])print("Test accuracy:", accuracy_score(y[is_test], pred))plt.figure(figsize=(16, 8))plot_tree(model, feature_names=["x", "y"],          class_names=["Class 1", "Class 2", "Class 3"],          filled=True, rounded=True, fontsize=10)plt.tight_layout()plt.show()

โค้ดอัปเดตตามพารามิเตอร์ใน Playground ด้านล่าง · เปลี่ยนไฟล์และคอลัมน์เพื่อใช้ข้อมูลของคุณ

05 Learn by playing

ลองปรับความลึก แล้วดูจำนวนกิ่ง เงื่อนไข และคำตอบที่ใบ เปลี่ยนตัวอย่างเพื่อเดินตามเส้นทางการตัดสินใจจริง

Sample dataset / Three groups● คำนวณใหม่เมื่อปรับค่า
ความลึกสูงสุดของต้นไม้ (1–6)
ตัวอย่างขั้นต่ำในใบ ปรับเพิ่มเพื่อให้กฎเรียบง่ายขึ้น
ต้นไม้ที่เรียนรู้จากข้อมูลฝึก

อ่านจากบนลงล่าง: ทดสอบเงื่อนไข → เลือกกิ่ง → คำตอบที่ใบ

ต้นไม้ตัดสินใจที่คำนวณจากพารามิเตอร์ปัจจุบันใช่ไม่ใช่ใช่ไม่ใช่ใช่ไม่ใช่ใช่ไม่ใช่ใช่ไม่ใช่ใช่ไม่ใช่คำตอบ: คลาส 1ข้อมูลฝึก 36 ตัวอย่างคลาส 1 / 2 / 3: 36 / 0 / 0ใช้คลาสที่มีจำนวนมากที่สุดคำตอบ: คลาส 1ข้อมูลฝึก 3 ตัวอย่างคลาส 1 / 2 / 3: 2 / 1 / 0ใช้คลาสที่มีจำนวนมากที่สุดx ≤ 45.66 ?ข้อมูลฝึก 39 ตัวอย่างคลาส 1 / 2 / 3: 38 / 1 / 0เลือกกิ่งตามเงื่อนไขคำตอบ: คลาส 2ข้อมูลฝึก 36 ตัวอย่างคลาส 1 / 2 / 3: 0 / 36 / 0ใช้คลาสที่มีจำนวนมากที่สุดx ≤ 50.37 ?ข้อมูลฝึก 75 ตัวอย่างคลาส 1 / 2 / 3: 38 / 37 / 0เลือกกิ่งตามเงื่อนไขคำตอบ: คลาส 3ข้อมูลฝึก 5 ตัวอย่างคลาส 1 / 2 / 3: 1 / 0 / 4ใช้คลาสที่มีจำนวนมากที่สุดคำตอบ: คลาส 2ข้อมูลฝึก 3 ตัวอย่างคลาส 1 / 2 / 3: 0 / 3 / 0ใช้คลาสที่มีจำนวนมากที่สุดx ≤ 65.52 ?ข้อมูลฝึก 8 ตัวอย่างคลาส 1 / 2 / 3: 1 / 3 / 4เลือกกิ่งตามเงื่อนไขคำตอบ: คลาส 3ข้อมูลฝึก 3 ตัวอย่างคลาส 1 / 2 / 3: 1 / 0 / 2ใช้คลาสที่มีจำนวนมากที่สุดคำตอบ: คลาส 3ข้อมูลฝึก 34 ตัวอย่างคลาส 1 / 2 / 3: 0 / 0 / 34ใช้คลาสที่มีจำนวนมากที่สุดx ≤ 25.10 ?ข้อมูลฝึก 37 ตัวอย่างคลาส 1 / 2 / 3: 1 / 0 / 36เลือกกิ่งตามเงื่อนไขy ≤ 57.27 ?ข้อมูลฝึก 45 ตัวอย่างคลาส 1 / 2 / 3: 2 / 3 / 40เลือกกิ่งตามเงื่อนไขy ≤ 50.12 ?ข้อมูลฝึก 120 ตัวอย่างคลาส 1 / 2 / 3: 40 / 40 / 40เลือกกิ่งตามเงื่อนไข

เลื่อนซ้าย–ขวาเพื่อดูทุกกิ่ง · กรอบและเส้นสีเขียวแสดงเส้นทางของตัวอย่างด้านล่าง · ค่าในภาพปัดเป็นทศนิยม 2 ตำแหน่ง

ลองเดินตามต้นไม้
1 / 30

ตัวอย่างจากชุดทดสอบที่โมเดลไม่เคยใช้ฝึก

Feature x
9.28
Feature y
6.10
คำตอบจริง
คลาส 1
โมเดลทำนาย
คลาส 1
  1. y = 6.10 ≤ 50.12 → ใช่
  2. x = 9.28 ≤ 50.37 → ใช่
  3. x = 9.28 ≤ 45.66 → ใช่
  4. ถึงใบ → คลาส 1
Test accuracy96.7%
จำนวนโหนด13
Train / Test120 / 30
ดูกฎที่ต้นไม้เรียนรู้y ≤ 50.1 ├ yes: x ≤ 50.4 ├ yes: x ≤ 45.7 ├ yes: กลุ่ม 1 (36 ตัวอย่าง) └ no: กลุ่ม 1 (3 ตัวอย่าง) └ no: กลุ่ม 2 (36 ตัวอย่าง) └ no: y ≤ 57.3 ├ yes: x ≤ 65.5 ├ yes: กลุ่ม 3 (5 ตัวอย่าง) └ no: กลุ่ม 2 (3 ตัวอย่าง) └ no: x ≤ 25.1 ├ yes: กลุ่ม 3 (3 ตัวอย่าง) └ no: กลุ่ม 3 (34 ตัวอย่าง)

ข้อมูลสังเคราะห์ 150 จุด มี 2 features และ 3 กลุ่ม ใช้ seed 42 เพื่อให้ทดลองซ้ำได้ แยกทุกจุดลำดับที่ 5 เป็น test set คงที่ 30 จุด; Playground ใช้ CART/Gini แบบย่อ ผลอาจต่างจาก scikit-learn เมื่อมีจุดแบ่งที่คะแนนเท่ากัน ผลนี้ใช้เพื่อเรียนรู้ ไม่ใช่ benchmark บนข้อมูลจริง