Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Now I am trying to fit some data with a implicit model function.

Firstly, I tried a toy example.

Toy example with input and output

data = {{1, 1}, {2, 1.4}, {3, 1.8}, {4, 2.4}, {5, 2.9}};
fitfunc[a_,b_,x_] := y /. FindRoot[a y + b Log[y] == x, {y, 1}];
FindFit[data, fitfunc[a, b, x], {a, b}, x]

Mathematica gives the following warning message and answer:

FindRoot::nlnum: The function value {0. +1. a-1. x} is not a list of numbers with dimensions {1} at {y} = {1.}. >>
ReplaceAll::reps: {FindRoot[a y+b Log[y]==x,{y,1}]} is neither a list of replacement rules nor a valid dispatch table, and so cannot be used for replacing. >>
{a -> 0.986636, b -> 1.96879}

The fit seems good.

Show[ListPlot[data], ContourPlot[Evaluate[a y + b Log[y] == x /. %], {x, 1, 5}, {y, 1, 4}]]

The fit result:

enter image description here

I have read the documentation of Symbolic Evaluation, and tried to use NumberQ in the function declaration, but I got the same warning message.

What am I doing wrong and how to solve this problem to avoid the warning message?

share|improve this question

3 Answers 3

data = {{1, 1}, {2, 1.4}, {3, 1.8}, {4, 2.4}, {5, 2.9}};
fitfunc[a_, b_, x_] := y /. Solve[a y + b Log[y] == x, {y},InverseFunctions -> True];
FindFit[data, fitfunc[a, b, x], {a, b}, x]

When inverse functions are allowed, Solve solves for f[expr] first, then applies InverseFunction[f] to the result, equates it to expr, and continues trying to solve for the remainder of the variables.

share|improve this answer
    
This provides another method to fit a implicit function. I appreciate your nice answer. –  lyon Aug 31 '12 at 11:49

It's an evaluation problem. fitfunc[a, b, x] evaluates to your definition which is y /. FindRoot[a y + b Log[y] == x, {y, 1.}] this returns the error, since it cannot find the root without numeric arguments for a and b. To avoid it, you need to tell it not to evaluate your function until you have numeric arguments. I assume this is what you tried to do with NumberQ.

 data = {{1, 1}, {2, 1.4}, {3, 1.8}, {4, 2.4}, {5, 2.9}};
 fitfunc[a_?NumericQ, b_?NumericQ, x_?NumericQ] := 
             y /. FindRoot[a y + b Log[y] == x, {y, 1.}];

 FindFit[data, fitfunc[a, b, x], {a, b}, x]

Returns

{a -> 0.986636, b -> 1.96879}

With no warning messages

share|improve this answer
    
Thanks very much! It works well now. –  lyon Aug 31 '12 at 11:43
4  
Of course, in this toy example, explicit solution is also available. $y = \frac{b}{a} W\left(\frac{a}{b}\exp\left(\frac{x}{b}\right)\right)$. Using fitfuncExact[a_, b_, x_] := LambertW[a/b Exp[x/b]] b/a gives the same fitted parameters. –  Sasha Aug 31 '12 at 12:48

One can always fall back on the definition of least-squares fitting, if the situation demands:

data = {{1, 1}, {2, 1.4}, {3, 1.8}, {4, 2.4}, {5, 2.9}};

{a, b} = NArgMin[Norm[Function[{x, y}, \[FormalA] y + \[FormalB] Log[y] - x] @@@ data],
                 {\[FormalA], \[FormalB]}]
   {0.9909829665303092, 1.952060702019563}

Show[ListPlot[data], ContourPlot[a y + b Log[y] == x, {x, 1, 5}, {y, 1, 4}]]

fit of implicit nonlinear model

Note the use of formal parameters as stand-ins for the parameters sought within NArgMin[].

share|improve this answer
    
Note, also, that this version returns a lower value for the least squares objective function (0.129153) as opposed to the version using FindFit[]+FindRoot[] (0.129416). –  J. M. Aug 31 '12 at 12:19
3  
+1 This answer is squarely within the spirit of the question: if the function is to be defined implicitly, then we are not emphasizing errors in either the x or y directions (unlike FindFit), but should be penalizing them in a symmetric way, which is what this approach does. –  whuber Aug 31 '12 at 13:21
    
A 2 per mil in the objective function ... OMG –  belisarius Aug 31 '12 at 13:58
    
@belisarius, if you're angling for four good digits... :) –  J. M. Aug 31 '12 at 14:03
    
JM: Help yourself and remove some data points :) –  belisarius Aug 31 '12 at 14:31

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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