I am using Mathematica's FindFit function to fit a parametric solution to my data and I am getting the error

FindFit::nrnum: The function value [complicated expression] is not a real number at {ka,kd,beta} = {0.7,0.1,0.1}

he initial guesses of the parameters {ka=0.7,kd=0.1,beta=0.1} are very close to the values I used to mock up the data, and I can't figure out where I am going wrong. I posted a similar version of this question on stack exchange but didn't get any response.

First I use the ParametricNDSolveValue function to parametrically solve two coupled first order differential equations for the functions 'a[t]' and 'b[t]' with parameters ka, kd, and beta:

sol = ParametricNDSolveValue[{D[a[t], t] == -kd*a[t] + ka*(1 - a[t] - b[t]), a[0] == ka/(ka + kd), 
  D[b[t], t] == -kd*b[t] + ka*(1 - Exp[-beta*t]) (1 - a[t] - b[t]), b[0] == 0 }, {a, b}, 
  {t, 0, 20}, {ka, kd, beta}]

I can extract the solution for a[t] for ka=0.7, kd=0.1, beta=0.1 by using:

y1 = sol[0.7, 0.1, 0.1][[1]]

Plotting y1 as a function of t gives the expected curve:

Plot[y1[t], {t, 0, 20}, PlotRange -> All]

Then I create a data table eyeballing the values from the above plot:

dataA = {{0, 0.87}, {5, 0.84}, {10, 0.75}, {15, 0.68}, {20, 0.62}}

Finally to test FindFit, I use FindFit with sol[ka, kd, beta][[1]][t] to fit the data giving the same initial values for ka, kd, and beta that I used to generate the above data:

fit = FindFit[dataA, sol[ka, kd, beta][[1]][t], {{ka, 0.7}, {kd, 0.1}, {beta, 0.1}}, t]

At which point I get the error:

FindFit::nrnum: "The function value 1/2\ ((-0.87+Abs[0.7[0.]])^2+(-0.84+Abs[0.7[5.]])^2+(-0.75+Abs[0.7[10.]])^2+(-0.68+Abs[0.7[15.]])^2+(-0.62+Abs[0.7[20.]])^2) is not a real number at {ka,kd,beta} = {0.7,0.1,0.1}."

I tried using Abs[sol[ka, kd, beta][[1]][t]] in FindFit, that didn't work. Then I tried adding constraints:

fit = FindFit[dataA, {Abs[sol[ka, kd, beta][[1]][t]], {ka > 0, kd > 0, 
  beta > 0}}, {{ka, 0.7}, {kd, 0.1}, {beta, 0.1}}, t]

And that failed too.

Any clues what is wrong with my code? Thanks a lot!

  • $\begingroup$ Welcome to Mathematica.SE! I suggest that: 1) You take the introductory Tour now! 2) When you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge. Also, please remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign! 3) As you receive help, try to give it too, by answering questions in your area of expertise. $\endgroup$ – bbgodfrey Feb 3 '15 at 17:42
  • $\begingroup$ Take a close look at your error output message. Your variable substitution is problematic and you end up with terms like Abs[0.7[5.]] repeatedly. 0.7 is not a function and cannot be addressed as such. $\endgroup$ – John Morganthau Feb 3 '15 at 20:00
sol = ParametricNDSolve[{D[a[t], t] == -kd*a[t] + ka*(1 - a[t] - b[t]), a[0] == ka/(ka + kd), 
                        D[b[t], t] == -kd*b[t] + ka*(1 - Exp[-beta*t]) (1 - a[t] - b[t]), 
                        b[0] == 0}, {a, b}, {t, 0, 20}, {ka, kd, beta}];

dataA = {{0, 0.87}, {5, 0.84}, {10, 0.75}, {15, 0.68}, {20, 0.62}};

fit = FindFit[dataA, a[ka, kd, beta][t] /. sol, {{ka, 0.7}, {kd, 0.1}, {beta, 0.1}}, t]

 (* {ka -> 0.932926, kd -> 0.136649, beta -> 0.0603393} *)

Plot[{a[.7, .1, .1][t] /. sol, a[ka, kd, beta][t] /. fit /. sol}, {t, 0, 20}, PlotRange -> All]

Mathematica graphics

  • $\begingroup$ +1 But could you explain why the result of 'ParametricNDSolveValue' isn't working here? $\endgroup$ – Matariki Feb 3 '15 at 20:34
  • $\begingroup$ @Matariki I haven't tried it :) $\endgroup$ – Dr. belisarius Feb 3 '15 at 20:44
  • $\begingroup$ @belisarius Thanks a lot, this worked! I think my syntax of finding "the solution for a[t]" from ParametricNDSolveValue is incorrect, i.e. it is incorrect to use sol[ka, kd, beta][[1]][t] in FindFit, but I don't know why. Also, an excellent post by @Oleksandr R. on the question of simultaneously fitting multiple datasets with a parametric solution of coupled differential equations can be found here: link $\endgroup$ – Sam Feb 3 '15 at 21:13
  • $\begingroup$ @Sam Glad to hear it helped $\endgroup$ – Dr. belisarius Feb 3 '15 at 21:15

The problem is that sol[ka, kd, beta][[1]][t] evaluates to ka[t] before numeric values are substituted for the parameters. You need to prevent evaluation of [[1]] until after sol has evaluated to a list of solutions.

Thanks to Mr.Wizard for pointing out Indexed, which will do what we're after.

fit = FindFit[dataA, Indexed[sol[ka, kd, beta], 1][t], {{ka, 0.7}, {kd, 0.1}, {beta, 0.1}}, t]
(*  {ka -> 0.932928, kd -> 0.136649, beta -> 0.0603392}  *)

In pre-V10, something like this will work (original answer):

firstIfList[l_List] := First[l]

fit = FindFit[dataA, firstIfList[sol[ka, kd, beta]][t], {{ka, 0.7}, {kd, 0.1}, {beta, 0.1}}, t]
(*  {ka -> 0.932928, kd -> 0.136649, beta -> 0.0603392}  *)

See Prevent Part[] from trying to extract parts of symbolic expressions for a similar issue with Part.

  • $\begingroup$ Indexed[sol[ka, kd, beta], 1][t] also works. $\endgroup$ – Mr.Wizard Feb 4 '15 at 11:43
  • $\begingroup$ @Mr.Wizard Thanks! I knew there was something new that solved this problem, but I forgot the name. $\endgroup$ – Michael E2 Feb 4 '15 at 11:44
  • $\begingroup$ It's in this answer in the Q&A you linked, if you'd like to vote for it. ;^) $\endgroup$ – Mr.Wizard Feb 4 '15 at 11:45
  • 1
    $\begingroup$ @Mr.Wizard Oops! I didn't read far enough. +1. :) $\endgroup$ – Michael E2 Feb 4 '15 at 11:46
  • $\begingroup$ Thanks everybody for answering my questions! Good to know about Indexed! $\endgroup$ – Sam Feb 4 '15 at 18:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.