1

I have a set of data that I want to fit two functions to it. First one is hyperbolic and the second one is exponential. Obviously the transition from hyperbolic to exponential should be smooth. I tried to adapt this example for linear regression to my need, but I'm not getting proper result.

import pandas as pd
from scipy import optimize
import matplotlib.pyplot as plt
import numpy as np

def piecewise_nonlinear(x, x0, k1, k2,k3,k4,k5):
    return np.piecewise(x, [x < x0, x >= x0], [lambda x:k1/((1+k2*k3*x)**(1/k3)), lambda x:k4*np.exp(-1*k5*x)])

x = np.array([ 30,  60,  90, 120, 150, 180, 210, 240, 270, 300, 330, 360, 390,420, 450, 480, 510, 540, 570, 600, 630, 660, 690, 720, 750, 780])
y = np.array([685806, 488008, 374536, 366452, 317325, 289852, 269000, 269161, 261033, 243107, 236150, 220606, 235519, 227069, 171397, 192005,166051, 163804, 147755, 157127, 157244, 143962, 148628, 159093,162164, 152667])

p , e = optimize.curve_fit(piecewise_nonlinear, x, y)
xd = np.linspace(0, 780, 780)
plt.plot(x, y, "o")
plt.plot(xd, piecewise_nonlinear(xd, *p))

The result of the above code is this picture: Result of code

if we print p and e, all the values of p array are all 1, and values of e are all inf.

It would be great if you could point me to the right direction or show me what I'm doing wrong.

mminaei
  • 11
  • 4
  • 1) I've looked at your data - I don't see why you want to fit hyperbolic+exp. It seems hyperbolic would be enough. 2) At SO follow [minimal working example convention](https://stackoverflow.com/help/minimal-reproducible-example) to ask questions. In your case `piecewise_linear` is not defined. 3) I don't understand this 10^x multiplication - please explain more clearly. – rpoleski May 04 '20 at 17:22
  • Thanks for your comment @rpoleski. The piecewise_linear was a typo which I edited. The reason that I want to fit two functions is that based on some papers, we expect the function change at some point. This has been observed in different datasets. Hyperbolic fits are pretty good, but hyperbolc+exponential should be better, or closer to reality. The 10^6 multiplier is just for clarification to see that *p is not a straight line, but it goes from 1 to infinity – mminaei May 04 '20 at 17:49
  • In that case you have to use some more advanced fitting method. The problem seems much more complicated than just a few lines of standard functions. I'm still not getting 10^6. Why not simply `print(p)` and `print(e)`? – rpoleski May 04 '20 at 17:57
  • @rpoleski I guess it's more of a distraction rather than clarification. I removed that 10^6 multiplication. And yes, it needs more advanced fitting, hence my question here. I couldn't find a method with extensive search. Maybe I'm missing something – mminaei May 04 '20 at 18:32
  • I suggest using MCMC or similar methods. I thinkg `emcee` package is very useful. – rpoleski May 04 '20 at 19:02
  • Thanks @rpoleski I will check it out. – mminaei May 05 '20 at 02:10

0 Answers0