ml/ library Learn by doing
ALGORITHM 19 · PYTHON / JAVASCRIPT

Quantile Regression

ทำนายขอบล่าง กลาง หรือขอบบน

LEARNING LEVEL2
ต่อยอดโดยตรงควรรู้มาก่อน · Linear Regression และ loss function
ลองใน Playground

01Overall Concept

OVERALL CONCEPT

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

ลองนึกภาพว่า — ถ้าถามว่าไปโรงเรียนใช้เวลาเฉลี่ยกี่นาที เราอาจได้ 20 นาที แต่ถ้าต้องไม่สาย เราอยากรู้เวลาที่ 90% ของวันไปถึงก่อน เช่น 35 นาที Quantile ช่วยตอบคำถามแบบหลัง

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

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

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

Regression ปกติชอบถามว่า

“ค่าเฉลี่ยน่าจะเท่าไร?”

แต่โลกจริงบางครั้งค่าเฉลี่ยไม่ใช่สิ่งที่เราอยากรู้

สมมติเราทำบริษัทขนส่ง และต้องทำนายเวลาส่งสินค้า

Regression ปกติอาจบอกว่า

ส่งเฉลี่ย 2.3 วัน

แต่ฝ่ายบริการลูกค้าอาจไม่ได้สนใจค่าเฉลี่ย เขาอยากรู้ว่า

“ถ้าจะรับประกันว่า 90% ของพัสดุถึงภายในกี่วัน?”

นี่คือสิ่งที่ Quantile Regression ทำได้

เราอาจถามมันว่า

50th percentile = ประมาณ 2 วัน 90th percentile = ประมาณ 4 วัน 95th percentile = ประมาณ 5 วัน

ทีนี้เราสามารถเอาไปใช้กำหนด SLA ได้ดีกว่าค่าเฉลี่ย

อีกตัวอย่างคือเงินเดือน แทนที่จะถามว่า “คนตำแหน่งนี้ได้เงินเดือนเฉลี่ยเท่าไร” เราอาจถามว่า

คนกลุ่มเงินเดือนต่ำ 25% เป็นแบบไหน คนกลางๆ เป็นแบบไหน คนระดับบน 10% เป็นแบบไหน

จึงเหมาะมากเวลาการกระจายข้อมูลไม่สมมาตร หรือเราสนใจ “กลุ่มบน/กลุ่มล่าง” มากกว่าค่ากลาง

ภาพจำ: ไม่ถามแค่ “คนกลางห้องอยู่ไหน” แต่ถามได้ว่า “หัวแถว ท้ายแถว และคนบนสุดอยู่ตรงไหน”

03How it works

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

  1. ตั้งคำถามบริษัทขนส่งให้ตรง

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

  2. กำหนดว่าต้องการเผื่อให้กี่เปอร์เซ็นต์

    เลือก quantile=0.9 ถ้าอยากประมาณขอบเวลาสำหรับ 90% ของงานที่มีลักษณะใกล้กัน หรือ 0.5 ถ้าอยากได้ค่ามัธยฐาน ค่า 0.9 ไม่ใช่การสั่งว่าทุกกลุ่มต้องได้ตามสัญญา 90% แน่นอน แต่เป็นเป้าหมายที่โมเดลพยายามเรียนรู้จากข้อมูล

  3. คิดค่าความพลาดสองฝั่งไม่เท่ากัน

    สมมติส่งจริง 5 วัน แต่ทาย 3 วัน เราประเมินต่ำไป 2 วัน เมื่อ quantile=0.9 ค่าความเสียหายแบบ pinball คือ 0.9 × 2 = 1.8 ถ้าส่งจริง 3 วันแต่ทาย 5 วัน จะคิดเพียง 0.1 × 2 = 0.2 โมเดลจึงมีแรงผลักให้เผื่อเวลาด้านบนมากขึ้น แทนการกดทั้งสองฝั่งให้เข้าใกล้ค่าเฉลี่ย

  4. ฝึกเส้นกลางกับเส้นเผื่อแยกกัน

    ใช้ QuantileRegressor(quantile=0.9, alpha=0.01, solver='highs') ภายใน Pipeline ที่ปรับสเกล แล้ว fit(X_train, y_train) ค่า alpha คุมค่าปรับน้ำหนัก ไม่ใช่ระดับเปอร์เซ็นต์ ถ้าอยากเห็น 50% และ 90% ต้องฝึกสองโมเดลด้วย quantile ต่างกัน แล้ว predict ด้วยข้อมูลชุดเดียวกัน

  5. ตรวจว่าที่เผื่อไว้ช่วยจริงไหม

    ใช้ mean_pinball_loss(y_test, pred, alpha=0.9) โดย alpha ของฟังก์ชันวัดผลนี้หมายถึง quantile คนละความหมายกับ alpha ในโมเดล นอกจากนี้นับสัดส่วน y_test ≤ pred ว่าใกล้ 90% หรือไม่ และดูแยกตามเส้นทาง ถ้าโมเดลหลาย quantile ให้เส้นข้ามกัน ต้องตรวจเพิ่มก่อนนำไปตั้ง SLA เพราะการฝึกแยกไม่ได้บังคับลำดับเส้น

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

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

DATA INX · featuresy · targetX = [ระยะทาง, น้ำหนักพัสดุ, จราจร] · y = เวลาส่งจริง
CALCULATEQuantile Regression
quantilealphasolver
RESULTnumeric predictionquantile=0.9 → ประมาณเวลาขอบบน แล้วตรวจ coverage บน test
เส้นทางของข้อมูล: จากค่าที่รับเข้า ผ่านการคำนวณด้วยพารามิเตอร์ ไปเป็นผลลัพธ์
INPUT

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

รับ X เป็นตารางตัวเลขและ y เป็นค่าต่อเนื่องเหมือน regression ทั่วไป แต่ผู้ใช้เลือกตำแหน่งของการกระจายที่ต้องการทำนาย

X = [ระยะทาง, น้ำหนักพัสดุ, จราจร] · y = เวลาส่งจริง
PARAMETERS

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

quantile
ตำแหน่งที่ต้องการ เช่น 0.5 ค่ากลาง หรือ 0.9 ขอบสูง
alpha
แรง regularization ที่ช่วยคุมขนาดน้ำหนัก
solver
วิธี optimization ที่ใช้ลด pinball loss
OUTPUT

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

ได้ค่าทำนายของ quantile ที่เลือกหนึ่งค่าต่อแถว สามารถฝึกหลายโมเดลเพื่อสร้างช่วงล่าง–กลาง–บน

quantile=0.9 → ประมาณเวลาขอบบน แล้วตรวจ coverage บน test
CALCULATION

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

  1. 01

    สร้างคำทำนายเชิงเส้น ŷ จาก X แล้วหาความต่างระหว่าง y กับ ŷ

  2. 02

    ใช้ pinball loss ซึ่งลงโทษการพลาดด้านบนและด้านล่างไม่เท่ากันตาม quantile

  3. 03

    ปรับน้ำหนักจน loss ต่ำที่สุด ทำให้สัดส่วนข้อมูลใต้เส้นใกล้ quantile ที่เลือก

ควรรู้อีกนิด — quantile สุดขอบต้องใช้ข้อมูลมาก และเส้นหลาย quantile อาจตัดกันหาก fit แยกกัน

04Make it yours

Python · scikit-learn
# ติดตั้ง: pip install numpy scikit-learn matplotlibfrom sklearn.linear_model import QuantileRegressorfrom sklearn.metrics import mean_squared_error import numpy as npfrom sklearn.model_selection import train_test_split rng = np.random.default_rng(42)X = np.linspace(-1, 1, 60).reshape(-1, 1)y = 0.1 + 0.55*X[:, 0] + 0.55*np.sin(3.4*X[:, 0])y += rng.normal(0, 0.14, len(y))X_train, X_test, y_train, y_test = train_test_split(    X, y, test_size=0.2, random_state=42) model = QuantileRegressor(quantile=0.50)model.fit(X_train, y_train)pred = model.predict(X_test)print("RMSE:", mean_squared_error(y_test, pred) ** 0.5)

โค้ดเปลี่ยนตามค่าที่เลือกใน Playground · แต่ละภาษาใช้ข้อมูลตัวอย่างตามที่ระบุในโค้ด

05Learn by playing

ปรับ quantile แล้วสังเกตรูปแบบคำทำนายและตัวชี้วัดที่คำนวณใหม่ทันที

Sample dataset / Curved signal● คำนวณใหม่เมื่อปรับค่า
0.5 คือค่ามัธยฐาน · 0.9 คือขอบบน
ข้อมูลฝึกและผลการทำนายFeature xค่าจริง • / ค่าทำนาย —
RMSE0.338
สัดส่วนจุดใต้เส้น48%
พารามิเตอร์ที่ลอง0.50

Playground เป็น implementation เพื่อการเรียนรู้ที่คำนวณในเบราว์เซอร์ ส่วนโค้ด Python ใช้ scikit-learn จึงอาจให้ค่าต่างกันเล็กน้อยจากรายละเอียดการ optimize และค่าเริ่มต้นของไลบรารี ผลนี้ไม่ใช่ benchmark บนข้อมูลจริง