1

I'm trying to fit a function to data using FindFit, but I can't find a way to replace norm function RMSE with a RMSE in log space: Total[(Log10[a] - Log10[b])^2]

I tried:

logNorm [x_, y_] = Total[(Log10[x + 1] - Log10[y + 1])^2];
nlm = FindFit[data, x*a+b, {a, b}, x, NormFunction -> (logNorm[#] &)]

But I get an error:

The function value logNorm[<long list>] is not a real number at {a,b} = {1.,1.}.

Oleksandr R.
  • 23,023
  • 4
  • 87
  • 125
  • 3
    NormFunction operates on the list of residuals, which are already formed and provided to this function. You seem to want it to represent the log-distance to the point. Sorry, but it cannot do this; you should use FindMinimum instead with a suitable objective function. FindFit just calls FindMinimum internally, if that makes you feel better. – Oleksandr R. Dec 20 '15 at 22:46
  • But, perhaps I misunderstood your question. Is Norm[Log10[## + 1], 2] & what you want? I am not sure I understand what your x and y arguments to logNorm are supposed to represent. – Oleksandr R. Dec 20 '15 at 22:54
  • Thanks. I wanted to replace RMSE with LRMSE. If residuals are already formed, then it's not possible and I'd have to use FindMinimum. In logNorm, x corresponds to observed value and y to fitted value provided by a model. In other words I wanted to replace current residuals calculated as "x-y" with "Log10[x+1]-Log10[y+1]". – Krzysztof Narkowicz Dec 21 '15 at 09:31
  • @Krzysztof Narkowicz, I guess the norm-function should be represented as f[Delta=observed-calculated], so you should transform your logarithmic expression to this form instead of your f[observed,calculated]. – Rom38 Dec 21 '15 at 10:50

1 Answers1

4

You can pass your data to the NormFunction:

myNorm[residuals_, data_] := 
   Total[(Log[data[[All, 2]] + 1] - 
          Log[data[[All, 2]] + residuals + 1])^2];
data = {#, 2 # + 10 + # RandomReal[{0, 2}]} & /@ Range[100];
fit = x*a + b /. 
    FindFit[data, x*a + b, {a, b}, x, 
         NormFunction -> (myNorm[#, data] &)] 

10.3158 + 2.86435 x

Show[{ListPlot[data], Plot[fit, {x, 0, 100}]}]

enter image description here

or even do this: NormFunction -> (logNorm[data[[All, 2]] + #, data[[All, 2]]] &) and your function as originally defined will work.

george2079
  • 38,913
  • 1
  • 43
  • 110