Reputation: 19
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:
Upvotes: 1
Views: 82
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