Python: linear curve_fit always gives slope and y-intercept 1

I'm trying to linearly fit some data, but I can't get curve_fit in python to give me anything other than bias and y-intercept 1. Here's an example of my code:

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

def func(x, a, b):
    return a*x + b

# This is merely a sample of some of my actual data
x = [290., 300., 310.]
y = [1.87e+21, 2.07e+21, 2.29e+21]

popt, pcov = curve_fit(func, x, y)

print popt

      

I also tried to give curve_fit a “guess”, but when I do that it gives me an overflow error, which I think is because the numbers are too large. Any suggestions would be much appreciated. Many thanks!

+3


source to share


3 answers


Another way to do it without using curve_fit

is using numpy polyfit .

import matplotlib.pyplot as plt
import numpy as np

# This is merely a sample of some of my actual data
x = [290., 300., 310.]
y = [1.87e+21, 2.07e+21, 2.29e+21]

xp = np.linspace(290, 310, 100)

z = np.polyfit(x, y, 1)
p = np.poly1d(z)
print (z)

fig, ax = plt.subplots()
ax.plot(x, y, '.')
ax.plot(xp, p(xp), '-')

plt.show()

      



This displays the odds just like the [2.10000000e+19 -4.22333333e+21]

following chart:

enter image description here

+1


source


I got something on a soccer field as Excel fits linearly using scipy basinhopping instead of curve_fit with lots of iterations. It takes a little time to run the iterations, and so does the error function, but it was done without scaling the original data. Basic equipment documents .

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import basinhopping

def func( x0, x_data, y_data ):

    error = 0
    for x_val, y_val in zip(x_data, y_data): 
        error += (y_val - (x0[0]*x_val + x0[1]))**2

    return error

x_data = [290., 300., 310.]
y_data = [1.87e+21, 2.07e+21, 2.29e+21]
a = 1
b = 1
x0 = [a, b]

minimizer_kwargs = { 'method': 'TNC', 'args': (x_data, y_data) }

res = basinhopping(func, x0, niter=1000000, minimizer_kwargs=minimizer_kwargs)

print res

      

This gives x: array ([7.72723434e + 18, -2.38554994e + 20]), but if you try again, you will see that this is a problem of inimitable results, although it will give similar ball values.



Here is a match comparison with Excel solution.

enter image description here

+1


source


Confirmed correct results are returned with:

x = [290., 300., 310.]
y = [300., 301., 302.]

      

I think the values ​​are ≅ 10²¹

too large for the function to work well.

What you can try to do is take the logarithm on both sides:

def func(x, a, b):
    # might need to check if ≤ 0.0
    return math.log(a*x + b)

# ... code omitted

y = [48.9802253837, 49.0818355602, 49.1828387704]

      

Then undo the transformation afterwards.

There is also a simple deterministic method for a simple linear approximation.

0


source







All Articles