Để khớp y = A + B log x , chỉ cần khớp y với (log x ).
>>> x = numpy.array([1, 7, 20, 50, 79])
>>> y = numpy.array([10, 19, 30, 35, 51])
>>> numpy.polyfit(numpy.log(x), y, 1)
array([ 8.46295607, 6.61867463])
# y ≈ 8.46 log(x) + 6.62
Để phù hợp với y = Ae Bx , lấy logarit của cả hai bên đưa ra log y = log A + Bx . Vì vậy, phù hợp (log y ) so với x .
Lưu ý rằng khớp (log y ) như thể nó là tuyến tính sẽ nhấn mạnh các giá trị nhỏ của y , gây ra độ lệch lớn cho y lớn . Điều này là do polyfit
(hồi quy tuyến tính) hoạt động bằng cách giảm thiểu Σ i (Δ Y ) 2 = Σ i ( Y i - y i ) 2 . Khi Y i = log y i , phần dư Y i = Δ (log y i ) Δ y i / | y i |. Vì vậy, ngay cả khipolyfit
đưa ra một quyết định rất tồi tệ cho y lớn , "chia cho | | y |" yếu tố sẽ bù đắp cho nó, gây ra polyfit
những giá trị nhỏ.
Điều này có thể được giảm bớt bằng cách cho mỗi mục nhập "trọng lượng" tỷ lệ với y . polyfit
hỗ trợ bình phương có trọng số nhỏ nhất thông qua w
đối số từ khóa.
>>> x = numpy.array([10, 19, 30, 35, 51])
>>> y = numpy.array([1, 7, 20, 50, 79])
>>> numpy.polyfit(x, numpy.log(y), 1)
array([ 0.10502711, -0.40116352])
# y ≈ exp(-0.401) * exp(0.105 * x) = 0.670 * exp(0.105 * x)
# (^ biased towards small values)
>>> numpy.polyfit(x, numpy.log(y), 1, w=numpy.sqrt(y))
array([ 0.06009446, 1.41648096])
# y ≈ exp(1.42) * exp(0.0601 * x) = 4.12 * exp(0.0601 * x)
# (^ not so biased)
Lưu ý rằng Excel, LibreScript và hầu hết các máy tính khoa học thường sử dụng công thức không trọng số (thiên vị) cho các đường hồi quy / xu hướng theo cấp số nhân. Nếu bạn muốn kết quả của mình tương thích với các nền tảng này, không bao gồm các trọng số ngay cả khi nó cung cấp kết quả tốt hơn.
Bây giờ, nếu bạn có thể sử dụng scipy, bạn có thể sử dụng scipy.optimize.curve_fit
để phù hợp với bất kỳ mô hình nào mà không cần chuyển đổi.
Với y = A + B log x kết quả giống như phương thức biến đổi:
>>> x = numpy.array([1, 7, 20, 50, 79])
>>> y = numpy.array([10, 19, 30, 35, 51])
>>> scipy.optimize.curve_fit(lambda t,a,b: a+b*numpy.log(t), x, y)
(array([ 6.61867467, 8.46295606]),
array([[ 28.15948002, -7.89609542],
[ -7.89609542, 2.9857172 ]]))
# y ≈ 6.62 + 8.46 log(x)
Tuy nhiên, đối với y = Ae Bx , chúng ta có thể có sự phù hợp tốt hơn vì nó tính (log y ) trực tiếp. Nhưng chúng tôi cần cung cấp một dự đoán khởi tạo để curve_fit
có thể đạt đến mức tối thiểu cục bộ mong muốn.
>>> x = numpy.array([10, 19, 30, 35, 51])
>>> y = numpy.array([1, 7, 20, 50, 79])
>>> scipy.optimize.curve_fit(lambda t,a,b: a*numpy.exp(b*t), x, y)
(array([ 5.60728326e-21, 9.99993501e-01]),
array([[ 4.14809412e-27, -1.45078961e-08],
[ -1.45078961e-08, 5.07411462e+10]]))
# oops, definitely wrong.
>>> scipy.optimize.curve_fit(lambda t,a,b: a*numpy.exp(b*t), x, y, p0=(4, 0.1))
(array([ 4.88003249, 0.05531256]),
array([[ 1.01261314e+01, -4.31940132e-02],
[ -4.31940132e-02, 1.91188656e-04]]))
# y ≈ 4.88 exp(0.0553 x). much better.