Mhmoud Khadija
Mhmoud Khadija

Reputation: 19

Optimizing a funcation using Scipy to estimate fitting parameters

I am trying to optimize a function by finding its minimum value using Scipy. The code must find the values of the variables g and tau that will give the minimum value of MSE. However, These values must be arrays not scalars. Below is the code

import numpy as np
import numpy as np
import pandas as pd
import math
import scipy.optimize as spo

## Insert the hihest numner of Prony Parameters for optimization.. 
N_Prony = 5

#########Intial_guess of g_i and tau_i################

#### Define Array for the guessing ########
Prony_0 = np.ones(N_Prony*2)    ## Five for the relaxtion time (taui) and five for g_i


# Initial guess of g_i and Tau_i
gini = 4
Taui = 0.8

Prony_0[0:N_Prony] = Prony_0[0:N_Prony]*gini
Prony_0[N_Prony:2*N_Prony] = Prony_0[N_Prony:2*N_Prony]*Taui


g = Prony_0[0:N_Prony] ## The first part of the array is g

tau = Prony_0[N_Prony:2*N_Prony] # The second part of the array is Tau


df1 = pd.read_excel(r'C:\Users\Mahmoud Khadijeh\Desktop\DSR Application\Testdata_Einf.xlsx')  ## Read the data from Excel file

w = df1.iloc[:,1] ## Read the frequency from the Excel file 

E_INF = df1.iloc[4,2]; NU = df1.iloc[0,5]   ## Read E_INF & Poission's Ratio from the EXCEL FILE 
G_INF = (E_INF)/2*(1+NU)    # Calculate G_INF from 
G0 = G_INF/(1-sum(g))       # Calculate G0 from G_INF
TANW_MEAS = (df1.iloc[:,3])/(df1.iloc[:,2])                          # Degree of Viscoelasticity 



list1 = []   # This list is to store G' from the loop in an array  {For each Frequnecy}
list2 = []   # This list is to store G'' from the loop in an array {For each Frequnecy} 

## Calculation.. 

for K in range(len(w)):  
    #Second part of Equation 5 -->  G'
    for L in range(N_Prony):
        GPrime_1 =   G_INF + G0*((g[L]*((tau[L])**2)*(w[K])**2)/(1+((tau[L]**2))*w[K]**2)*N_Prony)
    list1.append(GPrime_1)
    print(list1[0])


df1["G'"] =  list1          
df1["E'"] =  np.dot(2*(1+NU),list1) #Convert G' to E' and add it to the table 
print('df1 = ', df1)



for J in range(len(w)):  
    #Second part of Equation 5 -->  G'
    for i in range(N_Prony):
        GPrime_2 =   G0*((g[i]*((tau[i]))*w[J])/(1+((tau[i]**2))*w[J]**2)*N_Prony) 
    list2.append(GPrime_2)
    print(list2[0])


df1["G''"] =  list2        
df1["E''"] =  np.dot(2*(1+NU),list2)   #Convert G'' to E'' and add it to the table 




#### Initial Guess array
x0 = np.array([g, tau])


def objective(SE):
    global new_df
    g = SE[0]  # Variable 1 that we have to optimize
    tau = SE[1]  # Variable 2 that we have to optimize
    print('g::', g)
    print('tau::', tau)
    new_df = pd.DataFrame()
    new_df["E'_meas"] = df1.iloc[:,2]
    new_df["E''_meas"] =df1.iloc[:,3]
    #list1 = new_df["E'_meas"] 
    #list2 = new_df["E''_meas"] 
    new_df["E'_cal"] = list1 # Where list1 is E'
    new_df["E''_cal"] = list2 # Where list2 is E''
    new_df["Tan(d)_meas"] = TANW_MEAS
    new_df["Tan(d)_cal"] = new_df["E''_meas"]/new_df["E'_meas"]
    
    
    MSE = np.square(np.subtract(new_df["E'_meas"],new_df["E'_cal"])).mean()
    
    #minimize = (((new_df["E'_meas"] - new_df["E'_cal"])**2)/np.std(new_df["E'_meas"])) + \
    #           (((new_df["E''_meas"] - new_df["E''_cal"])**2)/np.std(new_df["E''_meas"])) + \
    #           (((new_df["Tan(d)_meas"] - new_df["Tan(d)_cal"])**2)/np.std(new_df["Tan(d)_cal"]))   

    return MSE

sol = spo.minimize(objective, x0, method='SLSQP', options={'disp': True})

print(sol)

However, the code is not changing the initial guess values.. For example: the output of the above code is:

Optimization terminated successfully    (Exit mode 0)
            Current function value: 3714530.31378857
            Iterations: 1
            Function evaluations: 11
            Gradient evaluations: 1
     fun: 3714530.31378857
     jac: array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
 message: 'Optimization terminated successfully'
    nfev: 11
     nit: 1
    njev: 1
  status: 0
 success: True
       x: array([4. , 4. , 4. , 4. , 4. , 0.8, 0.8, 0.8, 0.8, 0.8])

so g = [4,4,4,4,4] and tau = [0.8,0.8,0.8,0.8,0.8]

Any help!

Note I used two for-loops in the code to calculate the following equations:

For-loops

Upvotes: 1

Views: 82

Answers (1)

Rafnus
Rafnus

Reputation: 312

Im not seeing how you are using the input of your objective function SE. You convert that into g and tau, but those are not used either. Your objective function returns an output that is simply based on some values in a panda array, which stay the same every time. Your optimisation parameters simply have no impact on the objective value, so therefore they do not change from their initial value.

If you change the return value to be simply g + tau the output will be different from the initial values (note that I could not run this code myself, since I do not have your excel sheet):

def objective(SE):
    global new_df
    g = SE[0]  # Variable 1 that we have to optimize
    tau = SE[1]  # Variable 2 that we have to optimize
    print('g::', g)
    print('tau::', tau)
    new_df = pd.DataFrame()
    new_df["E'_meas"] = df1.iloc[:,2]
    new_df["E''_meas"] =df1.iloc[:,3]
    #list1 = new_df["E'_meas"] 
    #list2 = new_df["E''_meas"] 
    new_df["E'_cal"] = list1 # Where list1 is E'
    new_df["E''_cal"] = list2 # Where list2 is E''
    new_df["Tan(d)_meas"] = TANW_MEAS
    new_df["Tan(d)_cal"] = new_df["E''_meas"]/new_df["E'_meas"]
    
    
    MSE = np.square(np.subtract(new_df["E'_meas"],new_df["E'_cal"])).mean()
    
    #minimize = (((new_df["E'_meas"] - new_df["E'_cal"])**2)/np.std(new_df["E'_meas"])) + \
    #           (((new_df["E''_meas"] - new_df["E''_cal"])**2)/np.std(new_df["E''_meas"])) + \
    #           (((new_df["Tan(d)_meas"] - new_df["Tan(d)_cal"])**2)/np.std(new_df["Tan(d)_cal"]))   

    return g + tau

Upvotes: 0

Related Questions