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

Polynomial Regression

ให้เส้นโค้งตามแพตเทิร์นของข้อมูล

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

01Overall Concept

OVERALL CONCEPT

ไอเดียหลัก — Polynomial Regression ใช้เมื่อเรื่องที่เราศึกษาไม่ได้เปลี่ยนเป็นเส้นตรง แต่อาจโค้งขึ้นหรือโค้งลง โมเดลเพิ่มมุมมองใหม่อย่าง x² และ x³ ให้ข้อมูลเดิม จึงสร้างเส้นโค้งที่ตามรูปแบบได้ดีกว่าไม้บรรทัดเส้นเดียว

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

ตัวอย่างการนำไปใช้ — ดูการเติบโตของต้นไม้ตามเวลา ประมาณการใช้ไฟตามอุณหภูมิ หรืออธิบายระยะทางของลูกบอลที่เคลื่อนเป็นเส้นโค้ง

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

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

Polynomial Regression เกิดขึ้นเพราะโลกจริงไม่ได้เป็นเส้นตรงเสมอไป

สมมติเราดูความสัมพันธ์ระหว่าง อายุคนกับรายได้ ตอนเด็กๆ รายได้เกือบเป็นศูนย์ พอเริ่มทำงานรายได้เพิ่มขึ้นเรื่อยๆ ช่วงกลางอาชีพอาจสูงที่สุด แล้วช่วงเกษียณอาจลดลง

ถ้าใช้ Linear Regression เราอาจลากเส้นตรงจากอายุ 20 ไป 70 ซึ่งไม่ค่อยสมเหตุสมผล

Polynomial Regression จึงบอกว่า

“ไม่จำเป็นต้องเป็นเส้นตรงก็ได้ ให้เส้นมันโค้งได้”

มันอาจสร้างเส้นเป็นรูปตัว U, คว่ำ U หรือโค้งหลายจังหวะ เพื่อให้เข้ากับข้อมูลมากขึ้น

ตัวอย่างอีกแบบคือความสัมพันธ์ระหว่าง ความเร็วรถกับการกินน้ำมัน การเพิ่มจาก 30 → 40 กม./ชม. อาจมีผลไม่เท่ากับเพิ่มจาก 120 → 130 กม./ชม. เพราะพฤติกรรมมันไม่ได้เปลี่ยนแบบเส้นตรง

ข้อดีคือจับ pattern ที่ซับซ้อนกว่า Linear Regression ได้ แต่ปัญหาคือถ้าเราอนุญาตให้มันโค้งเยอะเกินไป มันอาจกลายเป็นเส้นที่คดไปคดมาตามข้อมูลเก่าอย่างสวยงาม แต่พอเจอข้อมูลใหม่กลับทำนายไม่ดี

นี่คือสิ่งที่เรียกว่า Overfitting

ภาพจำ: Linear Regression ใช้ไม้บรรทัด ส่วน Polynomial Regression ใช้ไม้ดัดที่งอได้

03How it works

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

  1. เริ่มจากเรื่องอายุกับรายได้

    เตรียม X เป็นอายุหนึ่งคอลัมน์ และ y เป็นรายได้ต่อเดือน แถวหนึ่งแทนคนหนึ่งคน เช่น X = [[25], [40], [60]] ข้อมูลจริงต้องมีคนหลากหลายกว่านี้มาก แบ่งชุดฝึกและชุดทดสอบก่อน และอย่าให้ข้อมูลซ้ำของคนเดียวกันอยู่ทั้งสองฝั่ง

  2. ทำให้ไม้บรรทัดงอได้ด้วยการเพิ่มคอลัมน์

    เมื่อเลือก degree=2 เราไม่ได้สั่งให้คอมพิวเตอร์วาดเส้นด้วยมือ แต่ให้ PolynomialFeatures สร้างอายุและอายุ² เช่น 25 กลายเป็น [25, 625] จากนั้น Linear Regression หาน้ำหนักของสองคอลัมน์ ได้สูตรรายได้ = b + w₁ × อายุ + w₂ × อายุ² ถ้า w₂ ติดลบ เส้นมีโอกาสโค้งคว่ำเหมือนรายได้ที่เพิ่มแล้วลด

  3. ประกอบขั้นตอนให้ข้อมูลใหม่ผ่านทางเดิม

    ใช้ make_pipeline(PolynomialFeatures(degree=2, include_bias=False), StandardScaler(), LinearRegression()) แล้ว fit ด้วย X_train, y_train ตัว scaler ช่วยจัดสเกลคอลัมน์ที่ยกกำลังให้คำนวณสะดวกขึ้น Pipeline จำวิธีแปลงไว้ให้ เมื่อ predict([[45]]) จึงไม่ต้องยกกำลังหรือปรับสเกลเองอีก

  4. ปรับความโค้งทีละระดับ

    ลอง degree=1, 2 และ 3 ก่อน ค่าใหญ่ทำให้ตามรายละเอียดได้มาก แต่เพิ่มจำนวนคอลัมน์เร็วมากเมื่อมีหลาย feature ใช้ include_bias=False เพราะ LinearRegression มี intercept อยู่แล้ว ส่วน interaction_only=True จะเก็บเฉพาะผลคูณข้ามตัวแปร จึงไม่เหมาะถ้าตั้งใจสร้างอายุ² จากอายุคอลัมน์เดียว

  5. เลือกเส้นที่ทายคนใหม่ได้ดี

    ใช้ cross-validation ภายในชุดฝึกเพื่อเลือก degree แล้วตรวจ RMSE บนชุดทดสอบครั้งสุดท้าย วาดเส้นทับข้อมูลฝึกและทดสอบ ถ้าค่า error ตอนฝึกลดลงแต่ตอนทดสอบเพิ่ม แสดงว่าเส้นเริ่มจำข้อมูลเก่า ลองลด degree และอย่าเชื่อเส้นที่ลากเลยช่วงอายุที่เคยฝึกโดยไม่ตรวจสอบ

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

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

DATA INX · featuresy · targetX = อายุของแต่ละคน · y = รายได้ต่อเดือน
CALCULATEPolynomial Regression
degreeinclude_biasinteraction_only
RESULTnumeric predictiondegree=2 → รายได้ = b + w₁ × อายุ + w₂ × อายุ²
เส้นทางของข้อมูล: จากค่าที่รับเข้า ผ่านการคำนวณด้วยพารามิเตอร์ ไปเป็นผลลัพธ์
INPUT

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

รับ X และ y แบบ Linear Regression แต่ X ต้องเป็นตัวเลข เพราะโมเดลจะนำตัวเลขไปยกกำลังเพื่อสร้าง feature ใหม่

X = อายุของแต่ละคน · y = รายได้ต่อเดือน
PARAMETERS

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

degree
กำลังสูงสุดและระดับความคดของเส้น
include_bias
เพิ่มคอลัมน์ค่าคงที่ 1 ในชุด feature หรือไม่
interaction_only
สร้างเฉพาะการคูณข้าม feature โดยไม่สร้างกำลังซ้ำ
OUTPUT

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

ได้เส้นโค้งและค่าทำนายตัวเลข โดยโมเดลภายในยังเก็บน้ำหนักหนึ่งค่าต่อ feature ที่สร้างขึ้น

degree=2 → รายได้ = b + w₁ × อายุ + w₂ × อายุ²
CALCULATION

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

  1. 01

    แปลงแต่ละแถวจาก x เป็นชุดตัวเลข x, x², … จนถึง degree ที่กำหนด

  2. 02

    นำ feature ที่ขยายแล้วเข้า Linear Regression เพื่อหาน้ำหนักของแต่ละกำลัง

  3. 03

    รวมค่าทั้งหมดเป็น ŷ = b + w₁x + w₂x² + … แล้วใช้สมการเดียวกันกับข้อมูลใหม่

ควรรู้อีกนิด — degree สูงเกินไปทำให้เส้นแกว่งและจำ noise ได้ง่าย ควรดูผลบน validation set และปรับสเกล feature

04Make it yours

Python · scikit-learn
# ติดตั้ง: pip install numpy scikit-learn matplotlibfrom sklearn.pipeline import make_pipelinefrom sklearn.preprocessing import PolynomialFeaturesfrom sklearn.linear_model import LinearRegressionfrom 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 = make_pipeline(PolynomialFeatures(degree=3), LinearRegression())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

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

Sample dataset / Curved signal● คำนวณใหม่เมื่อปรับค่า
ดีกรีสูงขึ้นทำให้เส้นยืดหยุ่นและเสี่ยง overfit มากขึ้น
ข้อมูลฝึกและผลการทำนายFeature xค่าจริง • / ค่าทำนาย —
RMSE0.105
จำนวน coefficient4
พารามิเตอร์ที่ลอง3

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