A callable model does not always expose a symbolic formula for its slope. Finite-difference differentiation estimates that slope by sampling nearby values, which makes it useful for checking black-box functions and validating hand-written gradients.
SciPy's scipy.differentiate.derivative() computes the first derivative of an elementwise real scalar function and returns both the estimate and convergence metadata. The scipy.differentiate namespace was added in SciPy 1.15, so older environments must be upgraded before this import is available.
Finite differences work best for smooth functions at points where nearby evaluations remain inside the function's domain. Near a boundary, use step_direction for one-sided differences; for a noisy function, compare the reported error with the precision the application actually needs.
import numpy as np from scipy.differentiate import derivative def f(x): return np.sin(x) x = np.pi / 4
result = derivative(f, x) if not result.success: raise RuntimeError(f"derivative failed with status {result.status}")
expected = np.cos(x) absolute_error = abs(result.df - expected) np.testing.assert_allclose(result.df, expected, rtol=1e-10, atol=1e-12)
The known derivative of sin(x) is cos(x), so this assertion can fail independently if the numerical estimate is outside the chosen tolerance.
print(f"derivative: {result.df:.8f}") print(f"expected: {expected:.8f}") print(f"absolute error: {absolute_error:.2e}") print(f"status: {int(result.status)}") print(f"estimated error: {result.error:.2e}")
$ python3 derivative_demo.py derivative: 0.70710678 expected: 0.70710678 absolute error: 6.55e-15 status: 0 estimated error: 1.85e-12
Status 0 means SciPy met its convergence tolerance. The NumPy assertion exits with an error instead of printing this block when the estimate differs from cos(pi/4) beyond the specified tolerance.