Giovanni Paiela
Giovanni Paiela

Reputation: 1

While True loop stuck at a certain iteration while trying to optimize for the best curve fit given a data set in python

So basically I wanted to make my own function to fit a curve given a dataset. I generally applied the least square method for the types polynomial, exponential and logarithmic but I noticed that this method is not that good on its own for fitting a curve on exponential data sets. I did the same curve fit with scipy and it gave a much better result. Because of that I decided to use the trial and error method of curve fitting, with initial estimates of a and b given by the least square method. I encountered a new problem. The time for the loop to spit out an error given a trial in each iteration gradually decreased and at some point the loop was just stuck at one place.

The code I have right now:

def exp_func(x,i,a,b):
    return a*np.exp(b*x[i])

def error_function(x,y,i,a,b):
    approximation = exp_func(x,i,a,b)
    residual = (abs(y[i]-approximation))/y[i]
    return residual
...
...
def curve_fit(data,x,type,degree=None):  
     if type == 'exp':
          A = np.ones((len(data),2))
          for i in range(0,len(data)):
             A[i,1] = x[i]
          data = np.log(data)
          data = np.transpose(data)
          y = np.linalg.inv(np.transpose(A)@A)@(np.transpose(A)@data)
          y[0] = np.exp(y[0])
          data = np.exp(data)
          data = np.transpose(data)
          learning_rate = 1
          tolerance = 0.5
          previous_error = (sum(error_function(x,data,i,y[0],y[1]) for i in range(0,len(data))))
          new_error = (sum(error_function(x,data,i,y[0],y[1]) for i in range(0,len(data))))
          while True:
              if new_error < tolerance:
                  break
              y_0new = y[0] + learning_rate*(np.random.uniform(-1,1))
              y_1new = y[1] + learning_rate*(np.random.uniform(-1,1))
              new_error =  (sum(error_function(x,data,i,y_0new,y_1new) for i in range(0,len(data))))
              if new_error < previous_error:
                  y[0] = y_0new
                  y[1] = y_1new
                  previous_error = new_error
          return y
x = np.linspace(0,5,20) #Testing it out
test1 = np.array([1,10,25,40,50])
t1 = np.arange(1,6)
a,b = cf.curve_fit(test1,t1,'exp')

fig, ax = plt.subplots()
plt.grid()
plt.plot(t1,test1,marker='o',ms=5,linestyle='')
plt.plot(x,a*np.exp(b*x),color='black')
plt.show()

I assume you don't require the code for the other types of curves.

Upvotes: 0

Views: 64

Answers (0)

Related Questions