Bagaimana cara menghitung turunan suatu fungsi, misalnya
y = x 2 +1
menggunakan numpy
?
Katakanlah, saya ingin nilai turunannya pada x = 5 ...
Bagaimana cara menghitung turunan suatu fungsi, misalnya
y = x 2 +1
menggunakan numpy
?
Katakanlah, saya ingin nilai turunannya pada x = 5 ...
Jawaban:
Anda memiliki empat opsi
Perbedaan terbatas tidak memerlukan alat eksternal tetapi rentan terhadap kesalahan numerik dan, jika Anda berada dalam situasi multivarian, dapat memakan waktu cukup lama.
Diferensiasi simbolik ideal jika masalah Anda cukup sederhana. Metode simbolis semakin kuat belakangan ini. SymPy adalah proyek luar biasa untuk ini yang terintegrasi dengan baik dengan NumPy. Lihat fungsi autowrap atau lambdify atau lihat posting blog Jensen tentang pertanyaan serupa .
Turunan otomatis sangat keren, tidak rentan terhadap kesalahan numerik, tetapi memerlukan beberapa pustaka tambahan (untuk ini google, ada beberapa opsi bagus). Ini adalah pilihan yang paling kuat tetapi juga yang paling canggih / sulit untuk diatur. Jika Anda baik-baik saja membatasi diri Anda pada numpy
sintaks, maka Theano mungkin pilihan yang baik.
Berikut ini contoh penggunaan SymPy
In [1]: from sympy import *
In [2]: import numpy as np
In [3]: x = Symbol('x')
In [4]: y = x**2 + 1
In [5]: yprime = y.diff(x)
In [6]: yprime
Out[6]: 2⋅x
In [7]: f = lambdify(x, yprime, 'numpy')
In [8]: f(np.ones(5))
Out[8]: [ 2. 2. 2. 2. 2.]
mpmath
(tidak yakin apa yang mereka lakukan).
Cara paling mudah yang dapat saya pikirkan adalah menggunakan fungsi gradien numpy :
x = numpy.linspace(0,10,1000)
dx = x[1]-x[0]
y = x**2 + 1
dydx = numpy.gradient(y, dx)
Dengan cara ini, dydx akan dihitung menggunakan perbedaan pusat dan akan memiliki panjang yang sama dengan y, tidak seperti numpy.diff, yang menggunakan perbedaan maju dan akan mengembalikan vektor ukuran (n-1).
dx
ke numpy.gradient
alih-alih x
? (ii) Bisakah kita juga melakukan baris terakhir dari Anda sebagai berikut: dydx = numpy.gradient(y, numpy.gradient(x))
?
NumPy tidak menyediakan fungsionalitas umum untuk menghitung turunan. Ia dapat menangani kasus khusus polinomial sederhana namun:
>>> p = numpy.poly1d([1, 0, 1])
>>> print p
2
1 x + 1
>>> q = p.deriv()
>>> print q
2 x
>>> q(5)
10
Jika Anda ingin menghitung turunan secara numerik, Anda dapat menggunakan kuosien perbedaan pusat untuk sebagian besar aplikasi. Untuk turunan dalam satu titik, rumusnya akan seperti ini
x = 5.0
eps = numpy.sqrt(numpy.finfo(float).eps) * (1.0 + x)
print (p(x + eps) - p(x - eps)) / (2.0 * eps * x)
jika Anda memiliki larik x
absis dengan larik y
nilai fungsi yang sesuai , Anda dapat menghitung perkiraan turunan dengan
numpy.diff(y) / numpy.diff(x)
1 * x**2 + 1
. Mereka meletakkan 2
di baris di atas karena eksponennya. Lihatlah dari kejauhan.
Dengan asumsi Anda ingin menggunakan numpy
, Anda dapat menghitung turunan suatu fungsi secara numerik pada titik mana pun menggunakan definisi Ketelitian :
def d_fun(x):
h = 1e-5 #in theory h is an infinitesimal
return (fun(x+h)-fun(x))/h
Anda juga dapat menggunakan turunan Symmetric untuk hasil yang lebih baik:
def d_fun(x):
h = 1e-5
return (fun(x+h)-fun(x-h))/(2*h)
Menggunakan contoh Anda, kode lengkap akan terlihat seperti ini:
def fun(x):
return x**2 + 1
def d_fun(x):
h = 1e-5
return (fun(x+h)-fun(x-h))/(2*h)
Sekarang, Anda dapat menemukan turunannya secara numerik di x=5
:
In [1]: d_fun(5)
Out[1]: 9.999999999621423
Saya akan melempar metode lain ke tumpukan ...
scipy.interpolate
Banyak splines interpolasi mampu menghasilkan turunan. Jadi, dengan menggunakan spline linier ( k=1
), turunan dari spline (menggunakan derivative()
metode) harus setara dengan perbedaan maju. Saya tidak sepenuhnya yakin, tapi saya percaya menggunakan turunan spline kubik akan mirip dengan turunan perbedaan terpusat karena menggunakan nilai dari sebelum dan sesudah untuk membuat spline kubik.
from scipy.interpolate import InterpolatedUnivariateSpline
# Get a function that evaluates the linear spline at any x
f = InterpolatedUnivariateSpline(x, y, k=1)
# Get a function that evaluates the derivative of the linear spline at any x
dfdx = f.derivative()
# Evaluate the derivative dydx at each x location...
dydx = dfdx(x)
Untuk menghitung gradien, komunitas pembelajaran mesin menggunakan Autograd:
Untuk memasang:
pip install autograd
Berikut ini contohnya:
import autograd.numpy as np
from autograd import grad
def fct(x):
y = x**2+1
return y
grad_fct = grad(fct)
print(grad_fct(1.0))
Ia juga dapat menghitung gradien fungsi kompleks, misalnya fungsi multivariasi.
Bergantung pada tingkat presisi yang Anda butuhkan, Anda dapat mengerjakannya sendiri, menggunakan bukti diferensiasi sederhana:
>>> (((5 + 0.1) ** 2 + 1) - ((5) ** 2 + 1)) / 0.1
10.09999999999998
>>> (((5 + 0.01) ** 2 + 1) - ((5) ** 2 + 1)) / 0.01
10.009999999999764
>>> (((5 + 0.0000000001) ** 2 + 1) - ((5) ** 2 + 1)) / 0.0000000001
10.00000082740371
kita tidak bisa benar-benar mengambil batas gradien, tapi ini agak menyenangkan. Anda harus berhati-hati karena
>>> (((5+0.0000000000000001)**2+1)-((5)**2+1))/0.0000000000000001
0.0
Anda dapat menggunakan scipy
, yang sangat mudah:
scipy.misc.derivative(func, x0, dx=1.0, n=1, args=(), order=3)
Temukan turunan ke-n dari suatu fungsi pada suatu titik.
Dalam kasus Anda:
from scipy.misc import derivative
def f(x):
return x**2 + 1
derivative(f, 5, dx=1e-6)
# 10.00000000139778