scipy 为什么改变x0的起始点会导致优化不起作用?

n53p2ov0  于 2023-06-23  发布在  其他
关注(0)|答案(1)|浏览(122)

我已经尝试运行一个优化器使用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))的解决方案能得到类似的优化结果,但它们完全不同。我是否应该使用另一个优化库?

jq6vz3qz

jq6vz3qz1#

对于优化器来说,这是一个难题,有几个原因。
首先,目标是R^2意味着将一个变量移到期望的解附近实际上会使目标变差。如果斜率不正确,求解器需要做的是一次增加或减少每个值,scipy.optimize中的大多数求解器都很难做到这一点。
其次,回归斜率有一个约束,这是另一件对大多数优化器来说很难做到的事情。通常情况下,当它们遇到约束时,它们会采取非常小的步骤,这使得它不太可能收敛。同样,在这种情况下,为了在不更改斜率的情况下取得进展,可能需要一次更改多个值。
出于这些原因,用更好的初始猜测替换x0可能是有帮助的。我发现了以下初始系数:

x0 = np.exp(returns['Returns'] * 14)

这两者都与您的目标完美相关,并满足斜率约束,无需优化。

相关问题