01Overall 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
ค่อยๆ ทำไปด้วยกัน ตั้งแต่ข้อมูลแถวแรกจนถึงการตรวจคำตอบ
เริ่มจากเรื่องอายุกับรายได้
เตรียม X เป็นอายุหนึ่งคอลัมน์ และ y เป็นรายได้ต่อเดือน แถวหนึ่งแทนคนหนึ่งคน เช่น X = [[25], [40], [60]] ข้อมูลจริงต้องมีคนหลากหลายกว่านี้มาก แบ่งชุดฝึกและชุดทดสอบก่อน และอย่าให้ข้อมูลซ้ำของคนเดียวกันอยู่ทั้งสองฝั่ง
ทำให้ไม้บรรทัดงอได้ด้วยการเพิ่มคอลัมน์
เมื่อเลือก degree=2 เราไม่ได้สั่งให้คอมพิวเตอร์วาดเส้นด้วยมือ แต่ให้ PolynomialFeatures สร้างอายุและอายุ² เช่น 25 กลายเป็น [25, 625] จากนั้น Linear Regression หาน้ำหนักของสองคอลัมน์ ได้สูตรรายได้ = b + w₁ × อายุ + w₂ × อายุ² ถ้า w₂ ติดลบ เส้นมีโอกาสโค้งคว่ำเหมือนรายได้ที่เพิ่มแล้วลด
ประกอบขั้นตอนให้ข้อมูลใหม่ผ่านทางเดิม
ใช้ make_pipeline(PolynomialFeatures(degree=2, include_bias=False), StandardScaler(), LinearRegression()) แล้ว fit ด้วย X_train, y_train ตัว scaler ช่วยจัดสเกลคอลัมน์ที่ยกกำลังให้คำนวณสะดวกขึ้น Pipeline จำวิธีแปลงไว้ให้ เมื่อ predict([[45]]) จึงไม่ต้องยกกำลังหรือปรับสเกลเองอีก
ปรับความโค้งทีละระดับ
ลอง degree=1, 2 และ 3 ก่อน ค่าใหญ่ทำให้ตามรายละเอียดได้มาก แต่เพิ่มจำนวนคอลัมน์เร็วมากเมื่อมีหลาย feature ใช้ include_bias=False เพราะ LinearRegression มี intercept อยู่แล้ว ส่วน interaction_only=True จะเก็บเฉพาะผลคูณข้ามตัวแปร จึงไม่เหมาะถ้าตั้งใจสร้างอายุ² จากอายุคอลัมน์เดียว
เลือกเส้นที่ทายคนใหม่ได้ดี
ใช้ cross-validation ภายในชุดฝึกเพื่อเลือก degree แล้วตรวจ RMSE บนชุดทดสอบครั้งสุดท้าย วาดเส้นทับข้อมูลฝึกและทดสอบ ถ้าค่า error ตอนฝึกลดลงแต่ตอนทดสอบเพิ่ม แสดงว่าเส้นเริ่มจำข้อมูลเก่า ลองลด degree และอย่าเชื่อเส้นที่ลากเลยช่วงอายุที่เคยฝึกโดยไม่ตรวจสอบ
ข้อมูล พารามิเตอร์ และภาพรวมการคำนวณ
degreeinclude_biasinteraction_onlyข้อมูลที่รับเข้ามา
รับ X และ y แบบ Linear Regression แต่ X ต้องเป็นตัวเลข เพราะโมเดลจะนำตัวเลขไปยกกำลังเพื่อสร้าง feature ใหม่
X = อายุของแต่ละคน · y = รายได้ต่อเดือนพารามิเตอร์ที่ใช้
- degree
- กำลังสูงสุดและระดับความคดของเส้น
- include_bias
- เพิ่มคอลัมน์ค่าคงที่ 1 ในชุด feature หรือไม่
- interaction_only
- สร้างเฉพาะการคูณข้าม feature โดยไม่สร้างกำลังซ้ำ
ผลลัพธ์ที่ได้
ได้เส้นโค้งและค่าทำนายตัวเลข โดยโมเดลภายในยังเก็บน้ำหนักหนึ่งค่าต่อ feature ที่สร้างขึ้น
degree=2 → รายได้ = b + w₁ × อายุ + w₂ × อายุ²คำนวณทีละขั้น
- 01
แปลงแต่ละแถวจาก x เป็นชุดตัวเลข x, x², … จนถึง degree ที่กำหนด
- 02
นำ feature ที่ขยายแล้วเข้า Linear Regression เพื่อหาน้ำหนักของแต่ละกำลัง
- 03
รวมค่าทั้งหมดเป็น ŷ = b + w₁x + w₂x² + … แล้วใช้สมการเดียวกันกับข้อมูลใหม่
ควรรู้อีกนิด — degree สูงเกินไปทำให้เส้นแกว่งและจำ noise ได้ง่าย ควรดูผลบน validation set และปรับสเกล feature
04Make it yours
# ติดตั้ง: 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 แล้วสังเกตรูปแบบคำทำนายและตัวชี้วัดที่คำนวณใหม่ทันที
Playground เป็น implementation เพื่อการเรียนรู้ที่คำนวณในเบราว์เซอร์ ส่วนโค้ด Python ใช้ scikit-learn จึงอาจให้ค่าต่างกันเล็กน้อยจากรายละเอียดการ optimize และค่าเริ่มต้นของไลบรารี ผลนี้ไม่ใช่ benchmark บนข้อมูลจริง