[SciPy-Dev] curve_fit() should require initial values for parameters

Evgeni Burovski evgeny.burovskiy at gmail.com
Sun Feb 3 16:29:52 EST 2019


On Sat, Feb 2, 2019 at 8:55 AM Ralf Gommers <ralf.gommers at gmail.com> wrote:
>
>
>
> On Thu, Jan 31, 2019 at 6:30 AM Matt Newville <newville at cars.uchicago.edu> wrote:
>>
>>
>>
>> On Wed, Jan 30, 2019 at 2:26 PM Stefan van der Walt <stefanv at berkeley.edu> wrote:
>>>
>>> On Wed, 30 Jan 2019 14:27:29 -0500, josef.pktd at gmail.com wrote:
>>> > (I'm strongly in favor of trying "defaults" first, and if that doesn't
>>> > work, then dig into or debug likely candidates. in loose analogy of test
>>> > driven development instead of up-front design.)
>>>
>>> It seems unlikely that we will reach full agreement in this thread,
>>> given the differing experiences and philosophies at play.  But, that's
>>> probably OK if we can all agree to modify the documentation to be clearer
>>> about the risks of the preset values for p0, how to select better
>>> values, and how to handle failure modes.
>>>
>>> This won't 100% address Matt's concerns, but it will go a long way to
>>> keeping users out of trouble, without having to make breaking changes to
>>> the API.
>>>
>>> What do you think?
>>>
>>
>> Well, I'm not sure that agreement here should be the sole driver for what scipy developers do.  There will be disagreements in design philosophy, and someone needs to be willing and able to make decisions in such situations.   I do not know who is making such decisions or reviewing changes in `scipy.optimize`, but it appears to me that this has suffered for awhile, leaving conceptual, interface, and organizational messes.  I thought I would try to help by cleaning up one of the most egregious and simplest of these.
>>
>> The documentation for `curve_fit` does currrently state that `p0=None` is converted to `np.ones(n_variables)`.  It appears that some view this as sufficient and that these folks view some automated assignment of initial values is useful, even while acknowledging that it cannot be correct in general.
>>
>> The argument for requiring initial values might be summarized as "initial values are actually required".
>> The argument against might be summarized as "we don't want to change the current behavior".
>>
>> Anyway, I am perfectly willing to lose this argument (I do not use `curve_fit` myself, and do not feel compelled to support its use), and the decision is not mine to make.  I do hope someone sensible is making these decisions.
>
>
> To answer this "who makes the decisions" question: we usually try to get consensus on any decision. Preferably by everyone who speaks up, otherwise by all the core developers. If that doesn't happen (not often), then in most cases people step out of the discussion and leave the decision to the one or two core devs who worked in that area most. This discussion is a rare example of there being two sides of the argument, both having merit, and it's not really converging. The final decision options are:
> 1. The SciPy BDFL (Pauli) makes the final decision.
> 2. We can't get to an agreement and the BDFL doesn't decide, so the status quo wins.
>
> For now we should go ahead with improving the docs (Stefan's suggestions), and then if Pauli wants to make a decision that would be great. Otherwise we'll stick with just the doc improvements.
>
> Cheers,
> Ralf

Hi,

I'd suggest the following action plan:

1. add a big prominent note to the docstring of curve_fit, to
recommend setting initial values explicitly;
2. link from the curve_fit docstring to lmfit, and recommend that
lmfit is used for anything more complicated than one-off quick fitting
exercise;
3. add to the tutorial walk-through of using curve_fit and an
eqiuvalent invocation of least_squares. This should discuss a simple
problem (current examples in the least_squares docstring may be
intimidating for new users);
4. add a worked example of lmfit usage to the scipy cookbook (I seem
to remember that there are/were examples, but these looked somewhat
clunky);
5. In curve_fit, check whether the popt equals p0, and raise a
RuntimeWarning (or a subclass).

The last part is a code change, and it assumes that the most common
failure mode is `popt == p0`  (not sure if that's the case for
problems with bounds).

6. A possible enhancement could be to overload the p0 parameter to
accept a dictionary with keys being the names of the variables. I.e.,
`curve_fit(lambda x, a, b: a*x**b, x, y, p0={'a': 1, 'b': 2})`

Cheers,

Evgeni


More information about the SciPy-Dev mailing list