関数の導関数を計算するにはどうすればよいですか。
y = x 2 +1
使用してnumpy
?
たとえば、x = 5での導関数の値が欲しいとしましょう...
関数の導関数を計算するにはどうすればよいですか。
y = x 2 +1
使用してnumpy
?
たとえば、x = 5での導関数の値が欲しいとしましょう...
回答:
4つのオプションがあります
有限差分には外部ツールは必要ありませんが、数値エラーが発生しやすく、多変量の状況の場合は時間がかかる場合があります。
問題が十分に単純な場合は、記号による微分が理想的です。シンボリックメソッドは最近非常に堅牢になっています。SymPyは、NumPyとうまく統合できる優れたプロジェクトです。autowrap関数またはlambdify関数を確認するか、同様の質問についてJensenのブログ投稿を確認してください。
自動微分は非常に優れており、数値エラーが発生しませんが、追加のライブラリが必要です(これにはGoogleが行います。いくつかの優れたオプションがあります)。これは最も堅牢ですが、選択をセットアップするのに最も洗練された/困難です。numpy
構文に限定する場合は、Theanoを選択するのがよいでしょう。
これは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
(ただし、正確に何をしているのかわかりません)。
私が考えることができる最も簡単な方法は、numpyの勾配関数を使用することです:
x = numpy.linspace(0,10,1000)
dx = x[1]-x[0]
y = x**2 + 1
dydx = numpy.gradient(y, dx)
この方法では、前方差分を使用して(n-1)サイズのベクトルを返すnumpy.diffとは異なり、dydxは中央差分を使用して計算され、yと同じ長さになります。
dx
するnumpy.gradient
のx
ですか?(ii)次のように最後の行も実行できますdydx = numpy.gradient(y, numpy.gradient(x))
か?
NumPyは、導関数を計算する一般的な機能を提供しません。ただし、多項式の単純な特殊ケースを処理できます。
>>> p = numpy.poly1d([1, 0, 1])
>>> print p
2
1 x + 1
>>> q = p.deriv()
>>> print q
2 x
>>> q(5)
10
導関数を数値で計算する場合は、ほとんどのアプリケーションで中心差分商を使用することで問題を回避できます。単一点の導関数の場合、式は次のようになります
x = 5.0
eps = numpy.sqrt(numpy.finfo(float).eps) * (1.0 + x)
print (p(x + eps) - p(x - eps)) / (2.0 * eps * x)
あなたは、配列があればx
対応する配列と横軸のをy
関数値の、あなたがデリバティブの近似値をcomputすることができます
numpy.diff(y) / numpy.diff(x)
1 * x**2 + 1
。2
指数なので、上の行に入れました。遠くから見てください。
を使用したい場合numpy
、厳密な定義を使用して、任意の時点で関数の導関数を数値計算でき ます。
def d_fun(x):
h = 1e-5 #in theory h is an infinitesimal
return (fun(x+h)-fun(x))/h
より良い結果を得るために対称導関数を使用することもできます。
def d_fun(x):
h = 1e-5
return (fun(x+h)-fun(x-h))/(2*h)
例を使用すると、完全なコードは次のようになります。
def fun(x):
return x**2 + 1
def d_fun(x):
h = 1e-5
return (fun(x+h)-fun(x-h))/(2*h)
これで、次の場所で微分を数値で見つけることができますx=5
。
In [1]: d_fun(5)
Out[1]: 9.999999999621423
山に別の方法を投げます...
scipy.interpolate
の多くの補間スプラインは、導関数を提供できます。したがって、線形スプライン(k=1
)を使用すると、(derivative()
メソッドを使用した)スプラインの導関数は、前方差分と同等になります。完全にはわかりませんが、キュービックスプラインを作成する前と後の値を使用するため、キュービックスプラインの導関数を使用すると、中央差分微分と同様になると思います。
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)
勾配を計算するために、機械学習コミュニティはAutogradを使用します。
インストールするには:
pip install autograd
次に例を示します。
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))
また、多変量関数などの複雑な関数の勾配を計算することもできます。
必要な精度のレベルに応じて、微分の簡単な証明を使用して、自分で解決できます。
>>> (((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
グラデーションの限界を実際にとることはできませんが、ちょっと楽しいです。でも気をつけないと
>>> (((5+0.0000000000000001)**2+1)-((5)**2+1))/0.0000000000000001
0.0
を使用できますscipy
。これはかなり単純です。
scipy.misc.derivative(func, x0, dx=1.0, n=1, args=(), order=3)
ある点で関数のn次導関数を求めます。
あなたの場合:
from scipy.misc import derivative
def f(x):
return x**2 + 1
derivative(f, 5, dx=1e-6)
# 10.00000000139778