Untuk pemasangan y = A + B log x , cukup pas y terhadap (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
Untuk pemasangan y = Ae Bx , ambil logaritma dari kedua sisi beri log y = log A + Bx . Jadi pas (log y ) terhadap x .
Perhatikan bahwa pemasangan (log y ) seolah-olah linier akan menekankan nilai-nilai kecil y , menyebabkan penyimpangan besar untuk y besar . Ini karena polyfit
(regresi linier) bekerja dengan meminimalkan ∑ i (Δ Y ) 2 = ∑ i ( Y i - Ŷ i ) 2 . Ketika Y i = log y i , residu Δ Y i = Δ (log y i ) ≈ Δ y i / | y i |. Bahkan jikapolyfit
membuat keputusan yang sangat buruk untuk y besar , "divide-by- | y |" Faktor akan mengimbanginya, menyebabkan polyfit
nilai-nilai kecil nikmat.
Ini dapat dikurangi dengan memberikan setiap entri "bobot" sebanding dengan y . polyfit
mendukung weighted-least-square melalui w
argumen kata kunci.
>>> 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)
Perhatikan bahwa Excel, LibreOffice, dan sebagian besar kalkulator ilmiah biasanya menggunakan rumus tanpa bobot (bias) untuk garis regresi / tren eksponensial. Jika Anda ingin hasil Anda kompatibel dengan platform ini, jangan masukkan bobot meskipun itu memberikan hasil yang lebih baik.
Sekarang, jika Anda bisa menggunakan Scipy, Anda bisa menggunakan scipy.optimize.curve_fit
model apa saja tanpa transformasi.
Untuk y = log A + B x hasilnya sama dengan metode transformasi:
>>> 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)
Namun untuk y = Ae Bx , kita bisa mendapatkan kecocokan yang lebih baik karena ia menghitung Δ (log y ) secara langsung. Tetapi kita perlu memberikan perkiraan inisialisasi sehingga curve_fit
dapat mencapai minimum lokal yang diinginkan.
>>> 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.
y
kecil akan secara artifisial kelebihan berat badan. Lebih baik untuk mendefinisikan fungsi (linier, bukan transformasi log) dan menggunakan kurva bugar atau minimizer.Anda juga dapat muat satu set data untuk apa pun yang berfungsi Anda suka menggunakan
curve_fit
dariscipy.optimize
. Misalnya jika Anda ingin menyesuaikan fungsi eksponensial (dari dokumentasi ):Dan jika Anda ingin merencanakan, Anda bisa melakukan:
(Catatan:
*
di depanpopt
ketika Anda merencanakan akan memperluas syarat-syarat ke dalama
,b
danc
yangfunc
. Mengharapkan)sumber
a
,b
danc
?Saya mengalami beberapa masalah dengan ini jadi biarkan saya menjadi sangat eksplisit sehingga noobs seperti saya bisa mengerti.
Katakanlah kita memiliki file data atau sesuatu seperti itu
hasilnya adalah: a = 0.849195983017, b = -1.18101681765, c = 2.24061176543, d = 0.816643894816
sumber
y = [np.exp(i) for i in x]
sangat lambat; salah satu alasan numpy dibuat agar kamu bisa menulisy=np.exp(x)
. Juga, dengan penggantian itu, Anda dapat menyingkirkan bagian kekuatan brutal Anda. Di ipython, ada%timeit
keajaiban yangIn [27]: %timeit ylist=[exp(i) for i in x] 10000 loops, best of 3: 172 us per loop In [28]: %timeit yarr=exp(x) 100000 loops, best of 3: 2.85 us per loop
x = np.array(x, dtype=float)
harus memungkinkan Anda untuk menyingkirkan pemahaman daftar lambat.Yah saya kira Anda selalu dapat menggunakan:
Sedikit memodifikasi jawaban IanVS :
Ini menghasilkan grafik berikut:
sumber
Berikut adalah opsi linierisasi pada data sederhana yang menggunakan alat dari scikit belajar .
Diberikan
Kode
Sesuai dengan data eksponensial
Sesuaikan data log
Detail
Langkah Umum
x
,y
atau keduanya)np.exp()
) dan pas dengan data asliDengan asumsi data kami mengikuti tren eksponensial, persamaan umum + mungkin:
Kita dapat meratakan persamaan kedua (misalnya y = intersep + kemiringan * x) dengan mengambil log :
Diberikan persamaan linear + dan parameter regresi, kita dapat menghitung:
A
via intercept (ln(A)
)B
via slope (B
)Ringkasan Teknik Linearisasi
+ Catatan: fungsi eksponensial linier bekerja paling baik saat noise kecil dan C = 0. Gunakan dengan hati-hati.
++ Catatan: sementara mengubah data x membantu linierisasi data eksponensial , mengubah data y membantu linierisasi data log .
sumber
Kami menunjukkan fitur
lmfit
sambil menyelesaikan kedua masalah.Diberikan
Kode
Pendekatan 1 -
lmfit
ModelSesuai dengan data eksponensial
Pendekatan 2 - Model Kustom
Sesuaikan data log
Detail
Anda dapat menentukan parameter yang disimpulkan dari objek regressor. Contoh:
Catatan:
ExponentialModel()
berikut ini adalah fungsi peluruhan , yang menerima dua parameter, salah satunya negatif.Lihat juga
ExponentialGaussianModel()
, yang menerima lebih banyak parameter .Instal perpustakaan melalui
> pip install lmfit
.sumber
Wolfram memiliki solusi bentuk tertutup untuk memasang eksponensial . Mereka juga memiliki solusi serupa untuk menyesuaikan hukum logaritmik dan kekuasaan .
Saya menemukan ini bekerja lebih baik daripada curve_fit scipy's. Berikut ini sebuah contoh:
sumber