我已经尝试运行一个优化器使用scipy优化。但是,为什么如果我改变x0,它会导致一个次优的结果?
代码的工作行是如果x0如下所示:x0=np.random.uniform(0.01, 50, len(returns))
.然而,如果我将这一行更改为其他值,例如x0=np.random.uniform(0.01, 500, len(returns))
,输出不再是最优的,尽管值仍然落在设定的范围内。
下面是完整的代码。该代码的目标是找到一个数字列表,当对给定的数字列表进行回归时,该数字列表将给予最高的R平方。
import pandas as pd
import numpy as np
from scipy import stats
from scipy.optimize import minimize, LinearConstraint
returns = {'Returns': [0.060458679, 0.061902247, 0.066269106, 0.080471895, 0.10595085, 0.086491221, 0.113036617, 0.137770782, 0.0777593, 0.070083323, 0.072254624]}
startvalues = {'Value': [14214252.35, 1401493.11, 14877567.11, 30553699.53, 11417231.53, 3698585.80, 4449329.62, 7111866.99, 4714928.31, 7196446.00, 22750284.22]}
returns = pd.DataFrame(returns)
startvalues = pd.DataFrame(startvalues)
def objective_function(values):
returns['Risk Not Optimal'] = values
returns['Log Risk Not Optimal'] = np.log(returns['Risk Not Optimal'])
_, _, r_value, _, _ = stats.linregress(returns['Returns'], returns['Log Risk Not Optimal'])
r_squared = r_value ** 2
return -r_squared
def slope_constraint(values):
returns['Risk Not Optimal'] = values
slope, _, _, _, _ = stats.linregress(returns['Returns'], np.log(returns['Risk Not Optimal']))
return slope - 14
# Define the bounds for the values of 'Risk Not Optimal'
bounds = [(0.01, 100000000)] * len(returns) # Use the length of the DataFrame
# Define the slope constraint
slope_cons = {'type': 'eq', 'fun': slope_constraint}
# Perform optimization to maximize the negative R-squared
result = minimize(objective_function, x0=np.random.uniform(0.01, 50, len(returns)), constraints=slope_cons, bounds=bounds)
best_list = result.x
best_r_squared = -result.fun # Convert back to positive
print("Best List:", best_list)
print("Best R-squared:", best_r_squared)
理想情况下,我想将x0设置为x0=startvalues
。但这并不奏效,这就是我发现问题的地方。我觉得我一定错过了一些基本的东西,关于scipy optimize如何计算最优值。
我试过改变约束条件,看起来去除斜率约束有所帮助,但这并不能帮助我找到解决方案。我希望x0=np.random.uniform(0.01, 50, len(returns))
和x0=np.random.uniform(0.01, 50, len(returns))
的解决方案能得到类似的优化结果,但它们完全不同。我是否应该使用另一个优化库?
1条答案
按热度按时间jq6vz3qz1#
对于优化器来说,这是一个难题,有几个原因。
首先,目标是R^2意味着将一个变量移到期望的解附近实际上会使目标变差。如果斜率不正确,求解器需要做的是一次增加或减少每个值,scipy.optimize中的大多数求解器都很难做到这一点。
其次,回归斜率有一个约束,这是另一件对大多数优化器来说很难做到的事情。通常情况下,当它们遇到约束时,它们会采取非常小的步骤,这使得它不太可能收敛。同样,在这种情况下,为了在不更改斜率的情况下取得进展,可能需要一次更改多个值。
出于这些原因,用更好的初始猜测替换x0可能是有帮助的。我发现了以下初始系数:
这两者都与您的目标完美相关,并满足斜率约束,无需优化。