ฉันเห็นรายการนี้ที่นี่และไม่อยากจะเชื่อว่ามีวิธีมากมายในการแก้ปัญหากำลังสองน้อยที่สุด "การสมปกติ" ในวิกิพีเดียดูเหมือนจะเป็นทางข้างหน้าค่อนข้างตรง: α
ดังนั้นทำไมไม่ใช้เพียงแค่พวกเขา? ฉันสันนิษฐานว่าจะต้องมีปัญหาการคำนวณหรือความแม่นยำเนื่องจากในลิงค์แรกเหนือ Mark L. Stone กล่าวว่า SVD หรือ QR เป็นวิธีที่ได้รับความนิยมในซอฟต์แวร์ทางสถิติและสมการปกติคือ "TERRIBLE จากความน่าเชื่อถือและความแม่นยำเชิงตัวเลข" อย่างไรก็ตามในรหัสต่อไปนี้สมการปกติทำให้ฉันมีความแม่นยำถึง ~ 12 ตำแหน่งทศนิยมเมื่อเทียบกับสามฟังก์ชั่นหลามยอดนิยม: numpy polyfit ; SciPy ของlinregress ; และ scikit การเรียนรู้ของการถดถอยเชิงเส้น
สิ่งที่น่าสนใจกว่าคือวิธีสมการปกตินั้นเร็วที่สุดเมื่อ n = 100000000 เวลาในการคำนวณสำหรับฉันคือ: 2.5 วินาทีสำหรับ linregress; 12.9s สำหรับ polyfit 4.2 วินาทีสำหรับ LinearRegression; และ 1.8s สำหรับสมการปกติ
รหัส:
import numpy as np
from sklearn.linear_model import LinearRegression
from scipy.stats import linregress
import timeit
b0 = 0
b1 = 1
n = 100000000
x = np.linspace(-5, 5, n)
np.random.seed(42)
e = np.random.randn(n)
y = b0 + b1*x + e
# scipy
start = timeit.default_timer()
print(str.format('{0:.30f}', linregress(x, y)[0]))
stop = timeit.default_timer()
print(stop - start)
# numpy
start = timeit.default_timer()
print(str.format('{0:.30f}', np.polyfit(x, y, 1)[0]))
stop = timeit.default_timer()
print(stop - start)
# sklearn
clf = LinearRegression()
start = timeit.default_timer()
clf.fit(x.reshape(-1, 1), y.reshape(-1, 1))
stop = timeit.default_timer()
print(str.format('{0:.30f}', clf.coef_[0, 0]))
print(stop - start)
# normal equation
start = timeit.default_timer()
slope = np.sum((x-x.mean())*(y-y.mean()))/np.sum((x-x.mean())**2)
stop = timeit.default_timer()
print(str.format('{0:.30f}', slope))
print(stop - start)