我希望获得与Excel中的Solver函数类似的结果。我一直在阅读Scipy优化,并试图构建一个函数来输出我想要找到的最大值。该公式基于四个不同的变量,参见下面的代码:
import pandas as pd
import numpy as np
from scipy import optimize
cols = {
'Dividend2': [9390, 7448, 177],
'Probability': [341, 376, 452],
'EV': [0.53, 0.60, 0.55],
'Dividend': [185, 55, 755],
'EV2': [123, 139, 544],
}
df = pd.DataFrame(cols)
def myFunc(params):
"""myFunc metric."""
(ev, bv, vc, dv) = params
df['Number'] = np.where(df['Dividend2'] <= vc, 1, 0) \
+ np.where(df['EV2'] <= dv, 1, 0)
df['Return'] = np.where(
df['EV'] <= ev, 0, np.where(
df['Probability'] >= bv, 0, df['Number'] * df['Dividend'] - (vc + dv)
)
)
return -1 * (df['Return'].sum())
b1 = [(0.2,4), (300,600), (0,1000), (0,1000)]
start = [0.2, 600, 1000, 1000]
result = optimize.minimize(fun=myFunc, bounds=b1, x0=start)
print(result)因此,当更改变量ev、bv、vc和dv时,我想在df中找到列返回的最大值。我希望它们在ev: 0.2-4,bv: 300-600,vc: 0-1000和dv: 0-1000之间。
当运行我的代码时,函数似乎停止在x0。
发布于 2022-05-17 07:57:08
正如我在评论中提到的,关键问题是np.where()是,既不可微,也不连续。因此,您的目标函数违反了scipy.optimize.minimize框架下的大多数(基于派生的)算法的数学假设。
所以,基本上,你有三个选择:
np.where()替换为光滑的近似,这样您的目标就会不断地可微性。由于@CypherX答案追求的是方法1,所以我想集中讨论2,这里的主要思想是近似np.where函数。一种可能的近似是
def smooth_if_then(x):
eps = 1e-12
return 0.5 + x/(2*np.sqrt(eps + x*x))它是连续的和可微的。然后,给定一个np.ndarray arr和一个标量值x,表达式np.where(arr <= x, 1, 0)等效于smooth_if_then(x - arr)。
因此,目标函数成为:
div = df['Dividend'].values
div2 = df['Dividend2'].values
ev2 = df['EV2'].values
ev = df['EV'].values
prob = df['Probability'].values
def objective(x, *params):
ev, bv, vc, dv = x
div_vals, div2_vals, ev2_vals, ev_vals, prob_vals = params
number = smooth_if_then(vc - div2_vals) + smooth_if_then(dv - ev2_vals)
part1 = smooth_if_then(bv - prob_vals) * (number * div_vals - (vc + dv))
part2 = smooth_if_then(-1*(ev - ev_vals)) * part1
return -1 * part2.sum()使用trust-constr算法(这是scipy.optimize.minimize内部最健壮的算法),将产生以下结果:
res = minimize(lambda x: objective(x, div, div2, ev2, ev, prob), x0=start, bounds=b1, method="trust-constr") barrier_parameter: 1.0240000000000006e-08
barrier_tolerance: 1.0240000000000006e-08
cg_niter: 5
cg_stop_cond: 0
constr: [array([8.54635975e-01, 5.99253512e+02, 9.95614973e+02, 9.95614973e+02])]
constr_nfev: [0]
constr_nhev: [0]
constr_njev: [0]
constr_penalty: 1.0
constr_violation: 0.0
execution_time: 0.2951819896697998
fun: 1.3046631387761482e-08
grad: array([0.00000000e+00, 0.00000000e+00, 8.92175218e-12, 8.92175218e-12])
jac: [<4x4 sparse matrix of type '<class 'numpy.float64'>'
with 4 stored elements in Compressed Sparse Row format>]
lagrangian_grad: array([-3.60651033e-09, 4.89643010e-09, 2.21847918e-09, 2.21847918e-09])
message: '`gtol` termination condition is satisfied.'
method: 'tr_interior_point'
nfev: 20
nhev: 0
nit: 14
niter: 14
njev: 4
optimality: 4.896430096425101e-09
status: 1
success: True
tr_radius: 478515625.0
v: [array([-3.60651033e-09, 4.89643010e-09, 2.20955743e-09, 2.20955743e-09])]
x: array([8.54635975e-01, 5.99253512e+02, 9.95614973e+02, 9.95614973e+02])最后但并非最不重要的一点是:使用光滑逼近是实现可微性的常见方法。但是,值得一提的是,这些近似不是凸的。在实践中,这意味着您的优化问题不是凸的,因此,您无法保证找到的平稳点(局部极小值)是全局最优的。为此,需要使用全局优化算法或将问题描述为MIP。从数学和实践的角度来看,后者都是推荐的方法。
https://stackoverflow.com/questions/72193393
复制相似问题