Optimization parameters in a for loop equation in Python

Viewed 239

I need to fit a model with two parameters to data. The model, however, is calculated in recursive way (the current calculation is calculated based on the previous calculation) and should be >= 0.

I used several panda frames with about 180 columns and 365 rows, but to frame it right I give just simple examples here.

the code is something like this:

A = {'col1': [1, 2, 3, 4], 'col2': [3, 4, 5, 6]} #model variables

B = {'col1': [0, 50, 156, 318], 'col2': [0, 182, 427, 735]} #data for model fitting

a = {'col1': [1], 'col2': [3]} #parameter to be optimized
b = {'col1': [4], 'col2': [5]} #parameter to be optimized

X.loc[0] = 0

for index in range(1,364):
    X.loc[index]=np.where(
        X.loc[index-1]-(a-(b*7*(1-A.loc[index])))<0,0,
        X.loc[index-1]-(a-(b*7*(1-A.loc[index])))

the columns in X should fit the columns in B by changing parameter a and b. I tried scipy.curve_fit but it does not work.

def Y(A,a,b):
    return #this is where it gets tricky#
    for index in range(1,364):
    X.loc[index]=np.where(
        X.loc[index-1]-(a-(b*7*(1-A.loc[index])))<0,0,
        X.loc[index-1]-(a-(b*7*(1-A.loc[index])))

popt, pcov = curve_fit(X, A, B,p0=([1, 3],[4, 5])) 

Does anyone know how to fix this equation? Or suggest the best way to optimize this equation?

Thank you.

1 Answers

Have a look at this, just consider this as a template with single independent variable but it considers previous objective value. Our objective function is the goal(). We save all the objective values in a list so that we can use the previous value of any given point.

import random

from scipy.optimize import curve_fit


best = None
N = 6  # available data sample

def goal(x, a, b):
    global best

    # In the beginning we don't have previous best value so we set it to zero or so.
    if best is None:
        prev_best = list(0 for _ in range(N))
        best = []
        print(f'init_best: {prev_best}')
    else:
        prev_best = best[len(best) - 1]
        print(f'prev_best: {prev_best}')

    y = prev_best - (a - (b * 7 * (1 - x)))
    print(f'curr best: {y}')
    
    # Modify elements of y, replace negative value with zero.
    y[y < 0] = 0
    print(f'modified best: {y}')

    # Backup our best because we will use it in the next call.
    best.append(y.tolist())
    print(f'saved best: {best}')

    return y


def optim():
    x = [random.randint(-10, 10) for i in range(N)]  # independent
    y = [random.randint(-1, 100) for i in range(N)]  # dependent

    popt, _ = curve_fit(goal, x, y)
   
    a, b = popt
    print(f'a: {a:0.2f}, b: {b:0.2f}')


# Start
optim()

Output

From the start we don't have previous value yet so I just set it to zero. Then we calculate the goal value which is curr best: [-29. 55. 55. -50. 6. 6.], then we set the value to zero if value is below zero in modified best: [ 0. 55. 55. 0. 6. 6.] and finally we save the value in saved best: [[0.0, 55.0, 55.0, 0.0, 6.0, 6.0]] because we will use it next time.

init_best: [0, 0, 0, 0, 0, 0]
curr best: [-29.  55.  55. -50.   6.   6.]
modified best: [ 0. 55. 55.  0.  6.  6.]
saved best: [[0.0, 55.0, 55.0, 0.0, 6.0, 6.0]]
prev_best: [0.0, 55.0, 55.0, 0.0, 6.0, 6.0]
curr best: [-29. 110. 110. -50.  12.  12.]
modified best: [  0. 110. 110.   0.  12.  12.]
saved best: [[0.0, 55.0, 55.0, 0.0, 6.0, 6.0], [0.0, 110.0, 110.0, 0.0, 12.0, 12.0]]

...
a: 1.00, b: 1.00
Related