5

I want to fit a curve with the following data, but I get the error:

ipython-input>:2: RuntimeWarning: overflow encountered in exp

Does anyone know what is the reason for this problem? I fitted this curve with a different datatype for Matlab and it worked fine. I used the initial condition from my Matlab code. Both curves are the same but the values of the y-axes are much higher in this case.

import numpy as np
import scipy.optimize
#sympy.init_printing()
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

list_R1_fit = [
    19.53218114920747, 42.52167990454083, 60.95540646861309,
    70.10646960395906, 73.99897337091254, 75.36736639556727,
    75.69578522881915, 75.62147077733012, 75.42605227692485,
    75.21657113589387, 75.04519265636262, 74.94144261816007,
    74.92153132015117, 74.99475606015201, 75.15746897265564
]
tau_list = [
    0.052, 0.12, 0.252,
    0.464, 0.792, 1.264,
    1.928, 2.824, 4,
    5.600, 7.795, 10.806,
    14.928, 20.599, 28.000
]

array_R1_fit = np.asarray(list_R1_fit)
tau_array = np.asarray(tau_list)
plt.plot(tau_array, array_R1_fit, 'o') 

def func_R1_fit( t, a0, a1, a2, a3, a4):
    R1_fit_Curve = (
        a0 * np.exp(
            a1 * (1 - (28 / t)**(4 / 5))
        ) + 
        a2 * (t / ((a3)**a4 + t**a4))
    )
    return R1_fit_Curve

pars, cov = curve_fit(
    f=func_R1_fit, 
    xdata=tau_array, ydata=array_R1_fit, 
    p0=[
        0.249714296337621, 0.101851223776512,
        0.209343265573669, 0.306273529630680,
        1.511897539010256
    ],
    bounds=(-np.inf, np.inf),
    maxfev=100000
)

I have generated more data in the first part of the chart. Now I get another error.

<ipython-input-7-f61377d66140>:2: RuntimeWarning:
 invalid value encountered in double_scalars
  R1_fit_Curve=a0*np.exp(a1*(1-(28/t)**(4/5)))+a2*(t/((a3)**a4+t**a4))

The new lists are as follows:

list_R1_fit=[8.889450414508385, 13.832704635961235, 3.0955553517738656, 6.944672155278666, 19.53218114920747, 23.06912497313617, 32.92595485184, 42.52167990454083, 54.23640835031421, 60.95540646861309, 66.91996368676925, 70.10646960395906, 72.69136093289741, 73.99897337091254, 74.93277916119311, 75.36736639556727, 75.62190347933995, 75.69578522881915, 75.68268608294542, 75.62147077733012, 75.52270979845973, 75.42605227692485, 75.21657113589387, 75.04519265636262, 74.94144261816007, 74.92153132015117, 74.99475606015201, 75.15746897265564]
tau_list=[0.03,0.04,0.052/3,0.052/2,0.052,0.12/2,(0.052+0.12)/2,0.12,(0.252+0.12)/2,0.252,(0.464+0.252)/2,0.464,(0.464+0.792)/2,0.792,(1.264+0.792)/2,1.264,(1.264+1.928)/2,1.928,(2.824+1.928)/2,2.824,(2.824+4)/2,4,5.600,7.795,10.806,14.928,20.599,28.000]
Ali AlCapone
  • 121
  • 7
  • 1
    Looking at the output of the function ```func_R1_fit```, it appears that the values of ```a2*(t/((a3)**a4+t**a4))``` are sometimes so large that your system cannot represent them, leading to ```nan``` values. This in turn leads to ```nan``` values as an output of your function. In short: ```np.exp``` becomes large even with relatively 'small' numbers, leading to overflow warnings. – phuycke Sep 09 '21 at 12:15
  • @phuycke do you know how I can solve it? with sympy.exp or mp.exp perhaps? – Ali AlCapone Sep 09 '21 at 12:21
  • 1
    Add the plot of the function and the initial guess that you're using – Mad Physicist Sep 09 '21 at 12:24

2 Answers2

1

Exponentials often cause trouble in curve fitting on "smaller" datatypes. So what you want to do is cast your input to bigger representations like longdouble which should be the biggest your platform naturally supports.

array_R1_fit = np.asarray(list_R1_fit).astype(np.longdouble)
tau_array =np.asarray(tau_list).astype(np.longdouble)
Eumel
  • 1,298
  • 1
  • 9
  • 19
1

If you set the dtypes of array_R1_fit and tau_array to np.longdouble ornp.float64 should fix the RuntimeWarning: overflow encountered in exp that is:

array_R1_fit = np.asarray(list_R1_fit, dtype=np.longdouble)
tau_array =np.asarray(tau_list, dtype=np.longdouble)

Note that if you are on a Windows 64-bit computer np.longdouble will not result in float128 but is defined to be float64. You can try to run it on a linux system.

darth baba
  • 1,277
  • 5
  • 13
  • jup im on windows and it didnt help so now I have to try it on linux? – Ali AlCapone Sep 09 '21 at 12:26
  • 1
    https://stackoverflow.com/questions/29820829/cannot-use-128bit-float-in-python-on-64bit-architecture – darth baba Sep 09 '21 at 12:29
  • 1
    I also tried Mac, but it didn't work. Now I'm trying to get more points, but I'm not sure if it helps. – Ali AlCapone Sep 09 '21 at 14:19
  • in my mac, I can run float 128 but unfortunately, it didn't help. – Ali AlCapone Sep 09 '21 at 15:28
  • 1
    comment by @Matthias: Unless you've got a very unusual platform (e.g., IBM mainframe), NumPy almost certainly doesn't give you access to true 128-bit floats. On some platforms, NumPy supports the x87 80-bit floating-point format defined in the 1985 version of the IEEE 754 standard, and on some of those platforms, that format is reported as float128 (while on others it's reported as float96). But all that's going on there is that you have an 80-bit format with 48 bits (or 16 bits) of padding. https://stackoverflow.com/questions/29820829/cannot-use-128bit-float-in-python-on-64bit-architecture – darth baba Sep 09 '21 at 15:46