盆暗の学習記録

データサイエンス ,エンジニアリング,ビジネスについて日々学んだことの備忘録としていく予定です。初心者であり独学なので内容には誤りが含まれる可能性が大いにあります。

pythonで数値微分するときはnumdifftoolsが便利そう

scipy.optimize.approx_fprime

先日、フィッシャー情報量を対数尤度の2次の導関数から計算してみようと思い、ChatGPTに「pythonで数値微分するコードの例を出して」と尋ねてみました。

するとscipyの approx_fprime という関数が提案され、2次の導関数については approx_fprime を2回再帰的に適用する方法が提案されました。

これは例えば以下のように書くことができます。

import numpy as np
from scipy.optimize import approx_fprime
EPSILON = np.sqrt(np.finfo(float).eps)

def f(x):
    """微分したい対象の関数"""
    return np.sin(x)

def df(x):
    """1次の導関数"""
    return approx_fprime(x, f=f, epsilon=EPSILON)[0]

def ddf(x):
    """2次の導関数"""
    return approx_fprime(x, f=df, epsilon=EPSILON)[0]

ただ、これplotしてみると2階微分のほうはギザギザした曲線になるみたいです。

どうしてこうなるのかは approx_fprime の中身を知らないのでよくわからないのですが、とりあえず別の方法を探すことにしました。

numdifftools

numdifftools は数値微分をするためのパッケージで、 numdifftools.Derivative([対象の関数], n=[導関数の次数]) といった書き方で簡単に導関数を生成できます。

import numpy as np
import numdifftools as nd

def f(x):
    """微分したい対象の関数"""
    return np.sin(x)

df = nd.Derivative(f, n=1)
ddf = nd.Derivative(f, n=2)

これでプロットすると

と、滑らかな2次の導関数になっていることがわかります。