Numpyを使用して導関数を計算するにはどうすればよいですか?


91

関数の導関数を計算するにはどうすればよいですか。

y = x 2 +1

使用してnumpy

たとえば、x = 5での導関数の値が欲しいとしましょう...


5
Sympyを使用する必要があります。sympy.org/ en / index.html NumpyはPython用の数値計算ライブラリです
prrao

または、導関数の数値を推定する方法が必要ですか?これには有限差分法を使用できますが、ひどくうるさい傾向があることを覚えておいてください。
Henry Gomersall

回答:


142

4つのオプションがあります

  1. 有限差分
  2. 自動デリバティブ
  3. 記号による区別
  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]: 2x

In [7]: f = lambdify(x, yprime, 'numpy')
In [8]: f(np.ones(5))
Out[8]: [ 2.  2.  2.  2.  2.]

申し訳ありませんが、これが馬鹿げているように思われる場合は、3。
DrStrangeLove

11
私が「記号による差別化」と言ったとき、私はそのプロセスがコンピューターによって処理されたことを意味するつもりでした。原則として、3と4は、作業を行う人、コンピュータ、またはプログラマのみが異なります。一貫性、スケーラビリティ、および遅延のため、3は4よりも優先されます。3が解決策を見つけられない場合、4が必要です。
MRocklin 2012

4
7行目で、yの導関数xを計算する関数fを作成しました。8では、この導関数をすべて1のベクトルに適用し、すべて2のベクトルを取得します。これは、6行目で述べたように、yprime = 2 * xだからです。
MRocklin 2012

完全を期すために、積分によって微分を行うこともできます(コーシーの積分公式を参照)。これは、たとえばに実装されていますmpmath(ただし、正確に何をしているのかわかりません)。
DerWeh、

自分で実装せずにnumpyで有限差分を行う簡単な方法はありますか?たとえば、定義済みの点での関数の勾配を見つけたいのですが。
アレックス

41

私が考えることができる最も簡単な方法は、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と同じ長さになります。


2
dxが一定でない場合はどうなりますか?
weberc2 2015

3
@ weberc2、その場合、1つのベクトルを別のベクトルで除算する必要がありますが、前方および後方微分で手動でエッジを個別に処理します。
Sparkler、2015

2
または、定数dxでyを補間してから、勾配を計算することもできます。
IceArdor 2016年

@Sparklerご提案ありがとうございます。私が2つの小さな質問をするかもしれない場合、(i)なぜ私たちは代わりにパスdxするnumpy.gradientxですか?(ii)次のように最後の行も実行できますdydx = numpy.gradient(y, numpy.gradient(x))か?
user929304

2
v1.13以降、2番目の引数として配列を使用して、不均一な間隔を指定できます。このページの例のセクションを参照してください
Nathaniel Jones

26

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)

2
「より一般的な場合の数値微分の計算は簡単です」-違いますが、一般的な場合の数値微分の計算は非常に困難です。うまく動作する関数を選択しただけです。
高性能マーク

>>> print pの後に2はどういう意味ですか?(2行目)
DrStrangeLove

@DrStrangeLove:それは指数です。数学的表記をシミュレートするためのものです。
Sven Marnach

@SvenMarnachそれは最大指数ですか?または何??なぜ指数は2だと思いますか?係数のみを入力しました...
DrStrangeLove

2
@DrStrangeLove:出力はとして読み取られることになっています1 * x**2 + 12指数なので、上の行に入れました。遠くから見てください。
Sven Marnach

14

を使用したい場合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

8

山に別の方法を投げます...

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)

試してみたところ、この関数からエラーが発生し続けますAxisError:軸-1は次元0の配列の範囲外であり、コミュニティにもこれに対する回答が表示されません。
Ayan Mitra、

問題を新しい質問として投稿し、ここにリンクしてください。エラーが発生する原因となる例を提供することがおそらく必要になります。interp関数で発生するエラーは通常、データが適切に形成されていないためです-繰り返される値、間違った次元数、配列の1つが誤って空になっている、データがxに対して並べ替えられていない、または並べ替えがaでない場合有効な関数など。scipyがnumpyを誤って呼び出している可能性がありますが、ほとんどありません。x.shapeとy.shapeを確認してください。np.interp()が機能するかどうかを確認します。機能しない場合は、より役立つエラーが表示される可能性があります。
flutefreak7

5

勾配を計算するために、機械学習コミュニティはAutogradを使用します。

numpyコードの導関数を効率的に計算します。

インストールするには:

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))

また、多変量関数などの複雑な関数の勾配を計算することもできます。


こんにちは、この関数を使用して、ステップ長を指定することにより、データの2つの列を数値で区別できますか?感謝
Ayan Mitra、

3

必要な精度のレベルに応じて、微分の簡単な証明を使用して、自分で解決できます。

>>> (((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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.