5
$\begingroup$

I'm executing the command

NonlinearModelFit[data, c/(1 + a Exp[-b x]), {a, b, c}, x]

with the data being

data = { {0, 15576}, {10, 15935}, {20, 16326}, 
{30, 18235}, {40, 21680}, {50, 22927}, {60, 28667}, 
{70, 41674}, {80, 50020}, {90, 75979}, {100, 148700}, 
{110, 197200}, {120, 212801}, {130, 215499}, {140, 227511}}

and I'm getting a nonsensical result. It's a horrible fit. I've tried various Method options and I always get a bad fit. My goal is to try to replicate what a TI-84 would give.

I don't know enough about this stuff to know why the TI-84 always seems to give reasonable fits but Mathematica does not.

$\endgroup$
1
  • 1
    $\begingroup$ Here is a shallow description of how TI calculators do logistic fitting. $\endgroup$ Apr 25, 2013 at 9:56

2 Answers 2

6
$\begingroup$

I think you have to give some reasonable start values for the fit. E.g. try

fitFkt = NonlinearModelFit[data,c/(1 + a Exp[-b x]), {a, {b, 0.1}, {c, Max[data[[All, 2]]]}}, x]

As you can see from Show[ListPlot[data], Plot[fitFkt[x], {x, 0, 150}]], the fit is quite ok.

$\endgroup$
3
  • 2
    $\begingroup$ Indeed, the second example under "scope" in the documentation for NonlinearModelFit is exactly this kind of thing. Apparently, if you don't specify initial conditions, it assumes initial values 1. reference.wolfram.com/mathematica/ref/NonlinearModelFit.html $\endgroup$
    – bill s
    Apr 25, 2013 at 8:27
  • $\begingroup$ Now, suppose one was given a different set of data with a logistic trend. How does one pick out a reasonable initial guess for b? :) $\endgroup$ Apr 25, 2013 at 13:41
  • $\begingroup$ If another data set shows a similar trend and if you do not know which initial value for b you should chose, then you could try to change the Method. E.g. NonlinearModelFit[data, c/(1 + a Exp[-b x]), {a, b, {c, Max[data[[All, 2]]]}}, x, Method -> "Newton"] leads to the same result without any initial guess for b. $\endgroup$
    – partial81
    Apr 26, 2013 at 6:35
4
$\begingroup$

Here's a rather ad hoc procedure for logistic fitting that I use:

dat = N[{{0, 15576}, {10, 15935}, {20, 16326}, {30, 18235}, {40, 21680}, {50, 22927},
         {60, 28667}, {70, 41674}, {80, 50020}, {90, 75979}, {100, 148700}, {110, 197200},
         {120, 212801}, {130, 215499}, {140, 227511}}];

(* rough estimate of asymptote *)
c0 = Max[dat[[All, 2]]];

dm = DeleteCases[dat, {_, c0}];
(* linear regression of transformed data *)
{a0, b0} = {Exp[-\[FormalK]], \[FormalM]} /.
 FindFit[Transpose[{dm[[All, 1]], Log[#/(c0 - #)] &[dm[[All, 2]]]}],
         \[FormalK] + \[FormalM] \[FormalX], {\[FormalK], \[FormalM]}, \[FormalX]];

{at, bt, ct} = {\[FormalA], \[FormalB], \[FormalC]} /. 
          FindFit[dat, \[FormalC]/(1 + \[FormalA] Exp[-\[FormalB] \[FormalX]]),
                  {{\[FormalA], a0}, {\[FormalB], b0}, {\[FormalC], c0}}, \[FormalX]]
   {874.6314992136595, 0.07113415632530808, 242526.3213562982}

We obtain something a bit useful:

Plot[ct/(1 + at Exp[-bt x]), {x, 0, 140}, 
     Epilog -> {Directive[Red, AbsolutePointSize[6]], Point[dat]}]

a logistic fit

FWIW, I also tried the problem on my TI-83 Plus. Using the built-in logistic regression function, I obtained {a, b, c} = {874.6224282, 0.0711340415, 242526.4026}. Pretty close...

$\endgroup$
1
  • $\begingroup$ I figured you'd want to see a way to handle sigmoidally-shaped data in general instead of just the specific data set in the OP, so I presented one of the usual ways. $\endgroup$ Apr 25, 2013 at 15:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.