Làm cách nào để tính đạo hàm của một hàm, chẳng hạn
y = x 2 +1
sử dụng numpy
?
Giả sử, tôi muốn giá trị của đạo hàm tại x = 5 ...
Làm cách nào để tính đạo hàm của một hàm, chẳng hạn
y = x 2 +1
sử dụng numpy
?
Giả sử, tôi muốn giá trị của đạo hàm tại x = 5 ...
Câu trả lời:
Bạn có bốn lựa chọn
Sự khác biệt hữu hạn không yêu cầu công cụ bên ngoài nhưng dễ bị sai số và nếu bạn đang ở trong tình huống đa biến, có thể mất một lúc.
Sự khác biệt mang tính biểu tượng là lý tưởng nếu vấn đề của bạn đủ đơn giản. Những ngày này, các phương pháp tượng trưng đang trở nên khá mạnh mẽ. SymPy là một dự án tuyệt vời để tích hợp tốt với NumPy. Xem các chức năng autowrap hoặc lambdify hoặc xem bài đăng trên blog của Jensen về một câu hỏi tương tự .
Các dẫn xuất tự động rất tuyệt, không dễ bị lỗi số, nhưng yêu cầu một số thư viện bổ sung (google cho điều này, có một vài tùy chọn tốt). Đây là sự lựa chọn mạnh mẽ nhất nhưng cũng phức tạp / khó thiết lập nhất. Nếu bạn chỉ giới hạn bản thân với numpy
cú pháp thì Theano có thể là một lựa chọn tốt.
Đây là một ví dụ sử dụng 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
(không chắc chắn nhưng chúng chính xác là gì).
Cách dễ hiểu nhất mà tôi có thể nghĩ đến là sử dụng hàm gradient của numpy :
x = numpy.linspace(0,10,1000)
dx = x[1]-x[0]
y = x**2 + 1
dydx = numpy.gradient(y, dx)
Bằng cách này, dydx sẽ được tính bằng cách sử dụng các khác biệt trung tâm và sẽ có cùng độ dài với y, không giống như numpy.diff, sử dụng chênh lệch chuyển tiếp và sẽ trả về vectơ kích thước (n-1).
dx
cho numpy.gradient
thay vì x
? (ii) Chúng tôi cũng có thể làm dòng cuối cùng của bạn như sau dydx = numpy.gradient(y, numpy.gradient(x))
:?
NumPy không cung cấp chức năng chung để tính toán các dẫn xuất. Tuy nhiên, nó có thể xử lý trường hợp đặc biệt đơn giản của đa thức:
>>> p = numpy.poly1d([1, 0, 1])
>>> print p
2
1 x + 1
>>> q = p.deriv()
>>> print q
2 x
>>> q(5)
10
Nếu bạn muốn tính đạo hàm bằng số, bạn có thể sử dụng thương số chênh lệch trung tâm cho phần lớn các ứng dụng. Đối với đạo hàm tại một điểm duy nhất, công thức sẽ giống như
x = 5.0
eps = numpy.sqrt(numpy.finfo(float).eps) * (1.0 + x)
print (p(x + eps) - p(x - eps)) / (2.0 * eps * x)
nếu bạn có một mảng x
abscissae với một mảng y
giá trị hàm tương ứng , bạn có thể tính các giá trị gần đúng của các đạo hàm với
numpy.diff(y) / numpy.diff(x)
1 * x**2 + 1
. Họ đặt 2
ở dòng trên vì nó là số mũ. Nhìn nó từ xa.
Giả sử bạn muốn sử dụng numpy
, bạn có thể tính toán số học đạo hàm của một hàm tại bất kỳ thời điểm nào bằng cách sử dụng định nghĩa chặt chẽ :
def d_fun(x):
h = 1e-5 #in theory h is an infinitesimal
return (fun(x+h)-fun(x))/h
Bạn cũng có thể sử dụng đạo hàm Đối xứng để có kết quả tốt hơn:
def d_fun(x):
h = 1e-5
return (fun(x+h)-fun(x-h))/(2*h)
Sử dụng ví dụ của bạn, mã đầy đủ sẽ trông giống như sau:
def fun(x):
return x**2 + 1
def d_fun(x):
h = 1e-5
return (fun(x+h)-fun(x-h))/(2*h)
Bây giờ, bạn có thể tìm bằng số về đạo hàm tại x=5
:
In [1]: d_fun(5)
Out[1]: 9.999999999621423
Tôi sẽ ném một phương pháp khác lên đống ...
scipy.interpolate
Nhiều splines nội suy có khả năng cung cấp các dẫn xuất. Vì vậy, bằng cách sử dụng một spline tuyến tính ( k=1
), đạo hàm của spline (sử dụng derivative()
phương pháp) sẽ tương đương với một hiệu số chuyển tiếp. Tôi không hoàn toàn chắc chắn, nhưng tôi tin rằng việc sử dụng đạo hàm spline lập phương sẽ tương tự như một đạo hàm chênh lệch tâm vì nó sử dụng các giá trị từ trước và sau để tạo spline lập phương.
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)
Để tính toán độ dốc, cộng đồng học máy sử dụng Autograd:
Để cài đặt:
pip install autograd
Đây là một ví dụ:
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))
Nó cũng có thể tính toán độ dốc của các hàm phức tạp, ví dụ như các hàm đa biến.
Tùy thuộc vào mức độ chính xác mà bạn yêu cầu, bạn có thể tự giải quyết bằng cách sử dụng bằng chứng phân biệt đơn giản:
>>> (((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
chúng ta không thể thực sự hiểu giới hạn của gradient, nhưng nó khá thú vị. Bạn phải cẩn thận mặc dù vì
>>> (((5+0.0000000000000001)**2+1)-((5)**2+1))/0.0000000000000001
0.0
Bạn có thể sử dụng scipy
, khá đơn giản:
scipy.misc.derivative(func, x0, dx=1.0, n=1, args=(), order=3)
Tìm đạo hàm cấp n của một hàm số tại một điểm.
Trong trường hợp của bạn:
from scipy.misc import derivative
def f(x):
return x**2 + 1
derivative(f, 5, dx=1e-6)
# 10.00000000139778