[SciPy-Dev] Regarding taking up project ideas and GSoC 2015

Per.Brodtkorb at ffi.no Per.Brodtkorb at ffi.no
Thu Mar 19 09:59:24 EDT 2015


Hi,

For your information I have reimplemented the approx._fprime and approx._hess code found in statsmodels and added the epsilon extrapolation
method of Wynn. The result you can see here:
https://github.com/pbrod/numdifftools/blob/master/numdifftools/nd_cstep.py

I have also compared the accuracy and runtimes for the different alternatives here:
https://github.com/pbrod/numdifftools/blob/master/numdifftools/run_benchmark.py


Personally I like the class interface better than the functional one because you can pass the resulting object as function to other methods/functions and these functions/methods do not need to know what it does behind the scenes or what options are used. This simple use case is exemplified here:

>>> g = lambda x: 1./x
>>> dg = Derivative(g, **options)
>>> my_plot(dg)
>>> my_plot(g)

In order to do this with a functional interface one could wrap it like this:

>>> dg2  = lambda x: fprime(g, x, **options)
>>> my_plot(dg2)

If you like the one-liner that the function gives, you could call the Derivate class like this

>>> Derivate(g, **options)(x)

Which is very similar to the functional way:
>>> fprime(g, x, **options)

Another argument for having it as a class is that a function will be large and
“large functions are where classes go to hide<http://mikeebert.tumblr.com/post/25998669005/large-functions-are-where-classes-go-to-hide>”. This  is a quote of Uncle Bob’s that we hear frequently in the third and fourth Clean Coders<http://www.cleancoders.com/> episodes. He states that when a function starts to get big it’s most likely doing too much— a function should do one thing only and do that one thing well. Those extra responsibilities that we try to cram into a long function (aka method) can be extracted out into separate classes or functions.

The implementation in https://github.com/pbrod/numdifftools/blob/master/numdifftools/nd_cstep.py is an attempt to do this.

For the use case where n>=1 and the Richardson/Romberg extrapolation method, I propose to factor this out in a separate class e.g. :
>>> class NDerivative(object):
….      def __init__(self, f, n=1, method=’central’, order=2, …**options):

It is very difficult to guarantee a certain accuracy for derivatives from finite differences. In order to get error-estimates for the derivatives one must do several functions evaluations. In my experience with numdifftools it is very difficult to know exactly which step-size is best. Setting it too large or too small are equally bad and difficult to know in advance. Usually there is a very limited window of useful step-sizes which can be used for extrapolating the evaluated differences to a better final result. The best step-size can often be found around (10*eps)**(1./s)*maximum(log1p(abs(x)), 0.1) where s depends on the method and derivative order.  Thus one cannot improve the results indefinitely by adding more terms. With finite differences you can hope the chosen sampling scheme gives you reasonable values and error-estimates, but many times, you just have to accept what you get.

Regarding the proposed API I wonder how useful the input arguments epsabs, epsrel  will be?
I also wonder how one can compute the outputs abserr_round, abserr_truncate accurately?


Best regards
Per A. Brodtkorb



I am also putting a simple thought about possible API implementation for calculating derivative (gradient or jacobian), though this is a simple approach I was wondering about. Please do correct me if I overlooked some important points. Waiting to hear from you.

1.     approx_fprime

arguments:   f  : callable function

                  x : ndarray values at which the derivative needs to be calculated

                  method : str method to be used to approximate the derivative - 'central', 'forward', 'backward', 'complex', 'richardson'

                  n : Integer from 1 to 4 (Default 1) defining derivative order.

                  order : Integer from 1 to 4 (Default 2) defining order of basic method used. For 'central' methods, it must be from the set [2,4].

                  args : tuple arguments for the function f

                  kwargs : dict Keyword arguments for function `f`.

                  epsabs : float or int optional Absolute error tolerance.

                  epsrel : float or int, optional Relative error tolerance.

                  disp : bool Set to True to print error messages.

return :  res : DiffResult

     The differentiation result represented as a DiffResult object. Important attributes are:

         x: ndarray solution array,

              success : bool a flag indicating if the derivative was calculated successfully

              message : str which describes the cause of the error, if occurred

              nfev : int number of function evaluations

              abserr_round  : float absolute value of the roundoff error, if applicable

              abserr_truncate : float absolute value of the truncation error, if applicable


Cheers,
Maniteja
_______________________________________________
SciPy-Dev mailing list
SciPy-Dev at scipy.org<mailto:SciPy-Dev at scipy.org>
http://mail.scipy.org/mailman/listinfo/scipy-dev




-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/scipy-dev/attachments/20150319/63d0f972/attachment.html>


More information about the SciPy-Dev mailing list