ฟังก์ชันต้นทุนและกำลังสองน้อยที่สุด
ผู้เรียนจะคำนวณค่าคลาดเคลื่อนกำลังสองเฉลี่ย แสดงภาพพื้นผิวต้นทุน และเข้าใจว่าเหตุใดการลดค่าคลาดเคลื่อนจึงนำไปสู่พารามิเตอร์ที่เหมาะสมที่สุด
ฟังก์ชันต้นทุนและกำลังสองน้อยที่สุด เป็นบทเรียน Machine Learning Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Machine Learning Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Machine Learning Academy มีบทเรียนทั้งหมด 4 บทเรียน
อะไรทำให้เส้นตรง “ดีที่สุด”
เมื่อมีแผนภาพกระจายของจุดข้อมูล เส้นตรงจำนวนอนันต์อาจลากผ่านหรืออยู่ใกล้ข้อมูลเหล่านั้นได้ คำถามคือ เส้นตรงใด ดีที่สุด เราจำเป็นต้องมีนิยามทางคณิตศาสตร์อย่างเป็นทางการของคำว่า “ดีที่สุด” ซึ่งสามารถหาค่าที่เหมาะสมได้ด้วยอัลกอริทึม
คำตอบคือ ฟังก์ชันต้นทุน (เรียกอีกอย่างว่าฟังก์ชันสูญเสียหรือฟังก์ชันวัตถุประสงค์) ซึ่งเป็นตัวเลขเดียวที่วัดว่าค่าทำนายของแบบจำลองผิดพลาดมากเพียงใดเมื่อพิจารณาตัวอย่างฝึกสอนทั้งหมด เส้นตรงที่ดีที่สุดคือเส้นที่ทำให้ฟังก์ชันต้นทุนมีค่าต่ำสุด วิธีนี้เปลี่ยนการฝึกแบบจำลองให้เป็นปัญหาการหาค่าที่เหมาะสมทางคณิตศาสตร์
ค่าเฉลี่ยความคลาดเคลื่อนกำลังสอง: ฟังก์ชันต้นทุนมาตรฐาน
ฟังก์ชันต้นทุนที่ใช้กันมากที่สุดสำหรับการถดถอยคือ Mean Squared Error (MSE) สำหรับตัวอย่างฝึกสอนแต่ละรายการ คุณจะคำนวณค่าคงเหลือ (ค่าจริงลบด้วยค่าทำนาย) ยกกำลังสอง แล้วหาค่าเฉลี่ยจากตัวอย่างทั้งหมด:
MSE = (1/n) × Σ(yᵢ - ŷᵢ)²
การยกกำลังสองมีผลสำคัญสองประการ คือทำให้ข้อผิดพลาดทั้งหมดเป็นบวก (ดังนั้นข้อผิดพลาดบวกและลบจะไม่หักล้างกัน) และลงโทษข้อผิดพลาดขนาดใหญ่มากกว่าข้อผิดพลาดขนาดเล็ก (ค่าคงเหลือ 10 จะมีส่วนต่อค่าต้นทุนเป็น 100 ไม่ใช่ 10) ดังนั้น MSE จึงผลักดันให้แบบจำลองหลีกเลี่ยงความผิดพลาดขนาดใหญ่
import numpy as np
y_actual = np.array([250000, 300000, 350000, 200000, 400000])
y_pred = np.array([240000, 320000, 330000, 210000, 380000])
# Compute MSE manually
residuals = y_actual - y_pred
squared_residuals = residuals ** 2
mse = squared_residuals.mean()
print('Residuals:', residuals)
print('Squared residuals:', squared_residuals)
print(f'MSE: {mse:,.0f}')
print(f'RMSE (interpretable): ${np.sqrt(mse):,.0f}')เหตุใดจึงต้องยกกำลังสองข้อผิดพลาด
คุณอาจสงสัยว่า เหตุใดจึงไม่หาค่าเฉลี่ยของค่าสัมบูรณ์ของค่าคงเหลือ (MAE) แทนการยกกำลังสอง ทั้งสองอย่างเป็นฟังก์ชันต้นทุนที่ใช้ได้ แต่ MSE มีข้อได้เปรียบทางคณิตศาสตร์ดังนี้:
- MSE หาอนุพันธ์ได้ทุกจุด ซึ่งจำเป็นสำหรับการหาค่าที่เหมาะสมด้วยเกรเดียนต์
- ข้อผิดพลาดที่ยกกำลังสองทำให้พื้นผิวของ MSE เป็น ชามที่เรียบ และมีค่าต่ำสุดทั่วโลกเพียงจุดเดียว ต่างจากฟังก์ชันต้นทุนบางชนิดที่มีค่าต่ำสุดเฉพาะที่หลายจุด
- MSE มีคำตอบพีชคณิตในรูปปิด หมายความว่าเราสามารถคำนวณพารามิเตอร์ที่เหมาะสมที่สุดได้โดยตรงโดยไม่ต้องค้นหาแบบวนซ้ำ
Mean Absolute Error (MAE) ทนต่อค่าผิดปกติได้ดีกว่าและมักเป็นที่ต้องการในการใช้งานจริง แต่ MSE เป็นจุดเริ่มต้นสำหรับทำความเข้าใจการถดถอยแบบกำลังสองน้อยที่สุด
import numpy as np
from sklearn.metrics import mean_squared_error, mean_absolute_error
y_actual = np.array([1.0, 2.0, 3.0, 4.0, 100.0]) # note the outlier
y_pred = np.array([1.1, 2.0, 3.1, 4.0, 4.0]) # miss the outlier
mse = mean_squared_error(y_actual, y_pred)
mae = mean_absolute_error(y_actual, y_pred)
print(f'MSE: {mse:.2f} -> heavily penalises the outlier (100 vs 4)')
print(f'MAE: {mae:.2f} -> less sensitive to the outlier')
# MSE amplifies the big miss much more than MAEพื้นผิวต้นทุน: การแสดงภาพการหาค่าที่เหมาะสม
ลองจินตนาการถึงปริภูมิ 2 มิติที่แกนหนึ่งคือความชัน m และอีกแกนคือจุดตัดแกน b สำหรับชุดค่าผสม (m, b) แต่ละชุด เราสามารถคำนวณ MSE บนข้อมูลฝึกสอนได้ ผลลัพธ์คือ พื้นผิวต้นทุน — พื้นผิว 3 มิติรูปชามที่ก้นชามคือค่า (m, b) ที่เหมาะสมที่สุด ซึ่งทำให้ MSE มีค่าต่ำสุด
สำหรับการถดถอยเชิงเส้นที่ใช้ MSE พื้นผิวนี้เป็นพาราโบลอยด์นูนที่สมบูรณ์แบบ — มีค่าต่ำสุดเพียงจุดเดียว จึงรับประกันได้ว่าการหาค่าที่เหมาะสมจะค้นพบพารามิเตอร์ที่ดีที่สุดในระดับสากลเสมอ นี่คือข้อได้เปรียบทางทฤษฎีที่สำคัญเมื่อเทียบกับแบบจำลองที่ซับซ้อนกว่าและมีพื้นผิวการสูญเสียที่ไม่นูน
import numpy as np
import matplotlib.pyplot as plt
# Simple 1-feature dataset
np.random.seed(42)
x = np.array([1, 2, 3, 4, 5], dtype=float)
y = np.array([2.1, 4.0, 5.9, 8.1, 10.0])
# Compute MSE for a grid of (slope, intercept) values
slopes = np.linspace(0, 4, 50)
intercepts = np.linspace(-3, 3, 50)
MSE = np.zeros((50, 50))
for i, m in enumerate(slopes):
for j, b in enumerate(intercepts):
y_pred = m * x + b
MSE[j, i] = ((y - y_pred) ** 2).mean()
# Minimum MSE occurs at the true parameters (~m=2, b=0)
print('Minimum MSE:', MSE.min().round(3))
print('At grid position:', np.unravel_index(MSE.argmin(), MSE.shape))คำตอบแบบกำลังสองน้อยที่สุดธรรมดา
Ordinary Least Squares (OLS) คือคำตอบทางคณิตศาสตร์ในรูปปิดที่ค้นหาความชันและจุดตัดแกนซึ่งทำให้ MSE มีค่าต่ำสุดได้ในการคำนวณเพียงครั้งเดียว — ไม่จำเป็นต้องวนซ้ำ สำหรับการถดถอยเชิงเส้นแบบง่าย (มีหนึ่งคุณลักษณะ) สูตรคือ:
m = Σ(xᵢ - x̄)(yᵢ - ȳ) / Σ(xᵢ - x̄)²
b = ȳ - m × x̄
สูตรเหล่านี้ใช้เพียงค่าเฉลี่ย ผลรวม และผลคูณของข้อมูลฝึกสอน Scikit-learn's LinearRegression ใช้รูปเมทริกซ์ทั่วไปของคำตอบนี้ ซึ่งรองรับคุณลักษณะจำนวนเท่าใดก็ได้
import numpy as np
x = np.array([1, 2, 3, 4, 5], dtype=float)
y = np.array([2.1, 4.0, 5.9, 8.1, 10.0])
# OLS closed-form solution
x_mean, y_mean = x.mean(), y.mean()
numerator = ((x - x_mean) * (y - y_mean)).sum()
denominator = ((x - x_mean) ** 2).sum()
m = numerator / denominator
b = y_mean - m * x_mean
print(f'Optimal slope (m): {m:.4f}') # ~2.0
print(f'Optimal intercept (b): {b:.4f}') # ~0.0
print(f'MSE at optimal params: {((y - (m*x+b))**2).mean():.4f}')สมการปกติสำหรับคุณลักษณะหลายรายการ
เมื่อมีคุณลักษณะหลายรายการ OLS จะขยายเป็นสมการปกติโดยใช้พีชคณิตเมทริกซ์:
w = (XᵀX)⁻¹ Xᵀy
ในที่นี้ X คือเมทริกซ์คุณลักษณะ (มีคอลัมน์ของ ones สำหรับไบแอส) y คือเวกเตอร์เป้าหมาย และ w คือเวกเตอร์ของน้ำหนักที่เหมาะสมที่สุด นี่คือสิ่งที่ scikit-learn คำนวณภายในเมื่อคุณเรียกใช้ LinearRegression().fit()
สมการปกติทำงานได้รวดเร็วกับชุดข้อมูลขนาดเล็ก (มีคุณลักษณะสูงสุดประมาณ 10,000 รายการ) แต่จะช้ากับชุดข้อมูลขนาดใหญ่มาก เนื่องจากการคำนวณเมทริกซ์ผกผันเป็นการดำเนินการระดับ O(n³) สำหรับชุดข้อมูลขนาดมหึมา มักเลือกใช้การไล่ระดับลง
import numpy as np
# Multiple features: X has columns [1, sqft, bedrooms]
X_raw = np.array([[1000, 3], [1500, 4], [800, 2], [2000, 5]], dtype=float)
X = np.column_stack([np.ones(4), X_raw]) # add bias column
y = np.array([200000, 300000, 160000, 380000], dtype=float)
# Normal Equation: w = (X^T X)^{-1} X^T y
w = np.linalg.inv(X.T @ X) @ X.T @ y
print(f'Bias (intercept): {w[0]:,.0f}')
print(f'Sqft coefficient: {w[1]:.2f}')
print(f'Bedrooms coef: {w[2]:,.0f}')
# Verify: prediction for a 1200 sqft, 3 bed house
pred = w[0] + w[1]*1200 + w[2]*3
print(f'Prediction: ${pred:,.0f}')การไล่ระดับลง: ตัวหาค่าที่เหมาะสมอีกวิธีหนึ่ง
สำหรับชุดข้อมูลขนาดใหญ่มากหรือแบบจำลองที่มีพารามิเตอร์หลายล้านรายการ (เช่น โครงข่ายประสาทเทียม) สมการปกติจะช้าเกินไป การไล่ระดับลงเป็นวิธีวนซ้ำทางเลือก เริ่มจากจุดสุ่มบนพื้นผิวต้นทุน คำนวณเกรเดียนต์ (ความชันของพื้นผิวต้นทุน) แล้วก้าวเล็ก ๆ ไปในทิศทางลง ทำซ้ำจนไปถึงก้นชาม
อัตราการเรียนรู้เป็นตัวควบคุมขนาดก้าว หากใหญ่เกินไปจะก้าวเลยค่าต่ำสุด หากเล็กเกินไปการลู่เข้าจะช้าอย่างมาก การไล่ระดับลงเป็นรากฐานของการฝึกการเรียนรู้เชิงลึก และเป็นอัลกอริทึมที่คุณจะใช้โดยปริยายทุกครั้งที่ฝึกโครงข่ายประสาทเทียม
import numpy as np
# Gradient descent for linear regression
x = np.array([1, 2, 3, 4, 5], dtype=float)
y = np.array([2.1, 4.0, 5.9, 8.1, 10.0])
m, b = 0.0, 0.0 # start at zero
lr = 0.02 # learning rate
for epoch in range(500):
y_pred = m * x + b
residuals = y_pred - y
# Gradients of MSE w.r.t. m and b
grad_m = (2/len(x)) * (residuals * x).sum()
grad_b = (2/len(x)) * residuals.sum()
m -= lr * grad_m
b -= lr * grad_b
print(f'Learned slope: {m:.4f}') # ~2.0
print(f'Learned intercept: {b:.4f}') # ~0.0R-Squared: ความสอดคล้องของแบบจำลอง
R² (R-squared) หรือที่เรียกว่าค่าสัมประสิทธิ์การกำหนด วัดว่าส่วนใดของความแปรปรวนใน y ที่แบบจำลองอธิบายได้ ค่านี้อยู่ระหว่าง 0 ถึง 1 (หรืออาจติดลบได้หากแบบจำลองแย่มาก):
- R² = 1.0 — ค่าทำนายสมบูรณ์แบบ เส้นตรงอธิบายความแปรปรวนทั้งหมด
- R² = 0.0 — แบบจำลองทำได้ไม่ดีกว่าการทำนายค่าเฉลี่ยของ y เสมอ
- R² = 0.8 — แบบจำลองอธิบายความแปรปรวนใน y ได้ 80%
R² เป็นตัวชี้วัดหลักสำหรับประเมินแบบจำลองการถดถอย เพราะต่างจาก MSE ตรงที่ไม่ขึ้นกับสเกลและตีความได้เสมอในรูปสัดส่วน
import numpy as np
from sklearn.metrics import r2_score
y_actual = np.array([200, 250, 300, 350, 400], dtype=float)
y_pred_good = np.array([195, 255, 305, 345, 402], dtype=float) # tight fit
y_pred_bad = np.array([300, 300, 300, 300, 300], dtype=float) # always predict mean
print(f'Good model R2: {r2_score(y_actual, y_pred_good):.3f}') # close to 1.0
print(f'Baseline R2: {r2_score(y_actual, y_pred_bad):.3f}') # close to 0.0
# Manual calculation
ss_res = ((y_actual - y_pred_good)**2).sum()
ss_tot = ((y_actual - y_actual.mean())**2).sum()
print(f'Manual R2: {1 - ss_res/ss_tot:.3f}')การประเมินต้นทุนด้วย scikit-learn
Scikit-learn มีตัวชี้วัดมาตรฐานสำหรับการถดถอยทั้งหมดอยู่ใน sklearn.metrics คุณนำเข้าเครื่องมือเหล่านี้ในรูปฟังก์ชันที่รับอาร์เรย์สองชุด — ค่าจริงและค่าทำนาย — แล้วคืนคะแนนแบบสเกลาร์
โปรดคำนวณตัวชี้วัดบนชุดทดสอบเสมอ ไม่ใช่ชุดฝึกสอน MSE ของชุดฝึกสอนบอกว่าแบบจำลองสอดคล้องกับข้อมูลที่ใช้ฝึกได้ดีเพียงใด ซึ่งย่อมต่ำกว่า MSE ของชุดทดสอบเสมอ MSE ของชุดทดสอบคือค่าประมาณประสิทธิภาพในการนำไปใช้กับข้อมูลใหม่ที่ตรงไปตรงมา
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
import numpy as np
np.random.seed(42)
X = np.random.randn(200, 1)
y = 3 * X.ravel() + 2 + np.random.randn(200) * 0.5
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
model = LinearRegression().fit(X_train, y_train)
y_pred = model.predict(X_test)
print(f'Test MSE: {mean_squared_error(y_test, y_pred):.4f}')
print(f'Test RMSE: {mean_squared_error(y_test, y_pred, squared=False):.4f}')
print(f'Test MAE: {mean_absolute_error(y_test, y_pred):.4f}')
print(f'Test R2: {r2_score(y_test, y_pred):.4f}')เมื่อ MSE ไม่ใช่การสูญเสียที่เหมาะสม
MSE เป็นค่าเริ่มต้นสำหรับการถดถอย แต่ไม่ใช่ตัวเลือกที่ดีที่สุดเสมอไป:
- หากเป้าหมายของคุณมีค่าผิดปกติ MSE จะขยายผลกระทบของค่าเหล่านั้นอย่างมาก ให้ใช้การสูญเสียแบบ HuberหรือMAEเพื่อความทนทาน
- หากคุณให้ความสำคัญกับข้อผิดพลาดสัมพัทธ์มากกว่าข้อผิดพลาดสัมบูรณ์ (เช่น การทำนายยอดขายของสินค้าราคา $100 และ $1,000,000) ให้ใช้MSLE (Mean Squared Log Error)
- สำหรับการพยากรณ์อนุกรมเวลา ตัวชี้วัดเฉพาะด้านอย่างMAPE (Mean Absolute Percentage Error)มักตีความได้ง่ายกว่า
ฟังก์ชันการสูญเสียเป็นการตัดสินใจด้านการออกแบบที่เข้ารหัสว่าข้อผิดพลาดประเภทใดสำคัญที่สุดสำหรับปัญหาเฉพาะของคุณ
ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจแนวคิดการเรียนรู้ของเครื่องด้วย Python จากบทเรียนนี้
ทบทวนบทเรียน
ในบทเรียนนี้ คุณได้เรียนรู้ว่า MSE วัดข้อผิดพลาดรวมของการทำนายโดยหาค่าเฉลี่ยของค่าคงเหลือที่ยกกำลังสองจากตัวอย่างฝึกสอนทั้งหมด, คำตอบ OLS ค้นหาความชันและจุดตัดแกนที่เหมาะสมที่สุดได้อย่างแม่นยำในการคำนวณครั้งเดียวโดยใช้สมการปกติ และ R-squared วัดสัดส่วนของความแปรปรวนที่แบบจำลองอธิบายได้และไม่ขึ้นกับสเกล ต่อไปเราจะใช้ LinearRegression ของ scikit-learn เพื่อฝึกแบบจำลองจริง ตรวจสอบสัมประสิทธิ์ของแบบจำลอง และประเมินแบบจำลองบนชุดทดสอบที่กันไว้ต่างหาก
เรียนรู้ Python ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 30
- บทเรียน
- 120
คำถามที่พบบ่อย
บทเรียน “ฟังก์ชันต้นทุนและกำลังสองน้อยที่สุด” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “ฟังก์ชันต้นทุนและกำลังสองน้อยที่สุด” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Machine Learning Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Machine Learning Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “ฟังก์ชันต้นทุนและกำลังสองน้อยที่สุด”
ผู้เรียนจะคำนวณค่าคลาดเคลื่อนกำลังสองเฉลี่ย แสดงภาพพื้นผิวต้นทุน และเข้าใจว่าเหตุใดการลดค่าคลาดเคลื่อนจึงนำไปสู่พารามิเตอร์ที่เหมาะสมที่สุด คุณปฏิบัติ Machine Learning Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Machine Learning Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Machine Learning Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “ฟังก์ชันต้นทุนและกำลังสองน้อยที่สุด” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Machine Learning Academy นี้ได้ไหม
ได้ บทเรียน Machine Learning Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- สมการเส้นตรง: ความชัน จุดตัด และการพยากรณ์
- ฟังก์ชันต้นทุนและกำลังสองน้อยที่สุด
- การฝึกการถดถอยเชิงเส้นด้วย scikit-learn
- การถดถอยเชิงเส้นพหุคูณและความสำคัญของคุณลักษณะ