<div dir="ltr"><div>I appologize for the anecdotal nature of my experience, but I have used curve_fit() since it was first introduced and I just took a tour of almost all the times I've used it (well over 100 times, all told) and not once did I fail to provide initial parameters - even if I merely set them to all ones which it turns out I did more than I care to admit. This covers "production-level" code used by others as well as one-off throw-away jupyter notebooks. It may be that it never occured to me that p0 was optional.</div><div><br></div><div>Anyways, I'm all for correctness and quality over backward-compatibility, even in the libraries and modules I consume, so I'd vote for making p0 required.<br></div><div><div><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature">-- <a href="https://sites.google.com/site/theodoregoetz/" target="_blank">Johann</a></div></div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Jan 30, 2019 at 8:05 AM Matt Newville <<a href="mailto:newville@cars.uchicago.edu">newville@cars.uchicago.edu</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Hi Ilhan,</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Jan 29, 2019 at 10:54 AM Ilhan Polat <<a href="mailto:ilhanpolat@gmail.com" target="_blank">ilhanpolat@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>> The problem<span style="font-family:arial,helvetica,sans-serif"><span class="gmail_default" style="font-family:arial,helvetica,sans-serif"></span> I have with this is that there really is not an<span class="gmail_default" style="font-family:arial,helvetica,sans-serif"> option to</span><span class="gmail_default" style="font-family:arial,helvetica,sans-serif"> </span>"try automatic first". There is "try </span><span class="gmail_default" style="font-family:arial,helvetica,sans-serif">`np.ones(n_variables)`</span><span style="font-family:arial,helvetica,sans-serif"> first"</span><span class="gmail_default" style="font-family:arial,helvetica,sans-serif">. This, or any other value, is really not a defensible choice for starting values. </span><span style="font-family:arial,helvetica,sans-serif"> <span class="gmail_default" style="font-family:arial,helvetica,sans-serif">Starting values </span>always<span class="gmail_default" style="font-family:arial,helvetica,sans-serif"> </span>depend on the function use</span><span class="gmail_default" style="font-family:arial,helvetica,sans-serif">d and the data being fit. <br></span></div><div><br></div><div>Why not? 1.s are as good as any other choice.</div></div></blockquote><div><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Well, I agree that `np.ones(n_variables)` is as good as any other choice. All default choices are horrible and not defensible. </div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Mathematically, algorithmically, and conceptually, initial values ARE REQUIRED for non-linear least squares optimization. The codes underlying `curve_fit()` (including `leastsq` and the mess that is `least_square`) do not permit the user to not provide initial values. The algorithms used simply do not make sense without initial values. </div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Programmatically, an optional keyword argument to a function, say with a default value of `None`, implies that there is a sensible default for that value. Thus, default fitting tolerances might be 1.e-7 (or, perhaps square root of machine precision) or the default value for "method to calculate jacobian" might be `None` to mean "calculate by finite difference". For these optional inputs, the function (say, `curve_fit()`) has a sensible default value that will work independently from the other input.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">That notion of "independent, sensible default value" is not ever possible for the initial values `p0` for `curve_fit`. Sensible initial values always depend on the data to be fit and the function modeling the data. Change the data values dramatically and `p0` must change. Change the definition of the function (or even the order of the arguments), and `p0` must change. There is not and cannot be a sensible default. </div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Telling the user that `p0` is optional and can be `None` (as the current documentation does clearly state) is utterly and profoundly wrong. It is mathematically indefensible. It is horrible API design. It harms the integretiy of `scipy.optimize` to tell the user this.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><span class="gmail_default" style="font-family:arial,helvetica,sans-serif"> </span>I don't know anything about the curve fit I will get in the end. So I don't need to pretend that I know a good starting value.</div></div></blockquote><div><span style="font-family:arial,helvetica,sans-serif"><br></span></div><div><span style="font-family:arial,helvetica,sans-serif">It is not possible to do curve-fitting or non-linear least-squares minimization when you "don't know anything". The user MUST provide data to be modeled and MUST provide a function to model that data. It is "pretending" to think that this is sufficient. The user also must provide initial values.</span></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><span class="gmail_default" style="font-family:arial,helvetica,sans-serif"> </span>Maybe for 3 parameter functions, fine I can come up with an argument but you surely don't expect me to know the starting point if I am fitting a 7 parameter func involving esoteric structure. At that point I am completely ignorant about anything about this function. So not knowing where to start is not due to my noviceness about the tools but because by definition. My search might even turn out to be convex so initial value won't matter.<br></div></div></blockquote><div><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">It is not possible to do curve-fitting or non-linear least-squares minimization when one is completely ignorant of the the function. <br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div></div><div><br></div><div>> Currently `curve_fit` converts `p0=None` to `np.ones(n_variables)` without warning or explanation. Again, I do not use `curve_fit()` myself. I find several aspects of it unpleasant.</div><div><br></div><div></div><div>It is documented in the p0 argument docs. I am using this function quite often. That's why I don't like extra required arguments. It's annoying to enter some random array just to please the API where I know that I am just taking a shot in the dark.</div></div></blockquote><div><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">It is not an extra keyword argument. It is required input for the problem. `curve_fit()` is converting your feigned (or perhaps obstinate) ignorance to a set of starting values for you. But starting values simply cannot be independent of the input model function or input data.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>I am pretty confident that if we force this argument most of the people you want to educate will enter np.zeros(n). Then they will get an even weirder error then they'll try np.ones(n) but misremember n then they get another error to remember the func parameter number which has already trippped up twice. This curve_fit function is one of those functions that you don't run just once and be done with it but over and over again until you give up or satisfied. Hence defaults matter a lot from a UX perspective. "If you have an initial value in mind fine enter it otherwise let me do my thing" is much better than "I don't care about your quick experiment give me some values or I will keep tripping up".<br></div><div></div><div><br></div></div></blockquote><div><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">I refuse to speculate on what "most users" will do, and I also refuse to accept your speculation on this without evidence. There a great many applications of curve-fitting for which `np.ones(n_variables)` and `np.zeros(n_variables)` will completely fail -- the fit will never move from the starting point. For the kinds of fits done in the programs I support, either of these would mean that essentially all fits would never move from its starting point, as at least one parameter being 0 or 1 would essentially always mean the model function was 0 over the full data range. </div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">But, again, I don't use `curve_fit` but other tools built on top of `scipy.optimize()`. Generally, the model function and data together imply sensible or at least guessable default values, but these cannot independent of model or data. In lmfit we do not permit the user to not supply default starting values -- default parameter values are `None` which will quickly raise a ValueError. I don't recall ever getting asked to change this. Because it should be obvious to all users that each parameter requires an initial value. Where appropriate and possible, we do provide methods for model functions to make initial guesses based on data. But again, the starting values always depend on model function and data. </div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Default arguments *do* matter from a UX perspective when defaults are sensible. `curve_fit` has three required positional arguments: a model function (that must be annoying to have to provide), "y" data to be fit (well, I guess I have that), and "x" data. Why are those all required? Why not allow `func=None` to be a function that calculates a sine wave? Why not allow `y=None` to mean `np.ones(1000)`? Why not allow `x=None` to mean `np.arange(len(y))`? Wouldn't that be friendlier to the user?</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div></div><div>><span class="gmail_default" style="font-family:arial,helvetica,sans-serif"> </span> But this behavior strikes me as utterly wrong and a disservice to the scipy ecosystem. I do not think that a documentation change is sufficient. <br></div><div><br></div><div>Maybe a bit overzealous? <br></div><div></div><div></div><div><span class="gmail_default" style="font-family:arial,helvetica,sans-serif"></span></div>
<br></div></blockquote><div><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Nope, just trying to help `curve_fit()` work better. </div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><span style="font-family:Arial,Helvetica,sans-serif">--Matt</span></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><span style="font-family:Arial,Helvetica,sans-serif"><br></span></div></div></div>
_______________________________________________<br>
SciPy-Dev mailing list<br>
<a href="mailto:SciPy-Dev@python.org" target="_blank">SciPy-Dev@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/scipy-dev" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/scipy-dev</a><br>
</blockquote></div>