SciPy 的最小化根本没有迭代
SciPy's minimize is not iterating at all
我正在尝试最小化一个基本如下所示的函数:
实际上它有两个自变量,但由于 x1 + x2 = 1,它们并不是真正独立的。
现在是 objective 函数
def calculatePVar(w,covM):
w = np.matrix(w)
return (w*covM*w.T) [0,0]
wnere w 是每个资产的权重列表,covM 是由 pandas
的 .cov() 返回的协方差矩阵
这里是调用优化函数的地方:
w0 = []
for sec in portList:
w0.append(1/len(portList))
bnds = tuple((0,1) for x in w0)
cons = ({'type': 'eq', 'fun': lambda x: np.sum(x)-1.0})
res= minimize(calculatePVar, w0, args=nCov, method='SLSQP',constraints=cons, bounds=bnds)
weights = res.x
现在函数有一个明确的最小值,但最小化只会吐出初始值作为结果,它确实显示 "Optimization terminated sucessfully"。有什么建议吗?
优化结果:
P.S。图片作为链接,因为我不符合要求!
你的代码只有一些令人困惑的变量,所以我只是清除了它并简化了一些行,现在最小化工作正常。然而,现在的问题是:结果是否正确?它们有意义吗?那就是给你判断:
import numpy as np
from scipy.optimize import minimize
def f(w, cov_matrix):
return (np.matrix(w) * cov_matrix * np.matrix(w).T)[0,0]
cov_matrix = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
p = [1, 2, 3]
w0 = [(1/len(p)) for e in p]
bnds = tuple((0,1) for e in w0)
cons = ({'type': 'eq', 'fun': lambda w: np.sum(w)-1.0})
res = minimize(f, w0,
args = cov_matrix,
method = 'SLSQP',
constraints = cons,
bounds = bnds)
weights = res.x
print(res)
print(weights)
更新:
根据您的评论,在我看来-也许-您的函数有多个最小值,这就是 scipy.optimize.minimize
被困在那里的原因。我建议 scipy.optimize.basinhopping
作为替代方案,这将使用随机步骤来遍历函数的大部分最小值,它仍然会很快。这是代码:
import numpy as np
from scipy.optimize import basinhopping
class MyBounds(object):
def __init__(self, xmax=[1,1], xmin=[0,0] ):
self.xmax = np.array(xmax)
self.xmin = np.array(xmin)
def __call__(self, **kwargs):
x = kwargs["x_new"]
tmax = bool(np.all(x <= self.xmax))
tmin = bool(np.all(x >= self.xmin))
return tmax and tmin
def f(w):
global cov_matrix
return (np.matrix(w) * cov_matrix * np.matrix(w).T)[0,0]
cov_matrix = np.array([[0.000244181, 0.000198035],
[0.000198035, 0.000545958]])
p = ['ABEV3', 'BBDC4']
w0 = [(1/len(p)) for e in p]
bnds = tuple((0,1) for e in w0)
cons = ({'type': 'eq', 'fun': lambda w: np.sum(w)-1.0})
bnds = MyBounds()
minimizer_kwargs = {"method":"SLSQP", "constraints": cons}
res = basinhopping(f, w0,
accept_test = bnds)
weights = res.x
print(res)
print("weights: ", weights)
输出:
fun: 2.3907094432990195e-09
lowest_optimization_result: fun: 2.3907094432990195e-09
hess_inv: array([[ 2699.43934183, -1184.79396719],
[-1184.79396719, 1210.50404805]])
jac: array([1.34548553e-06, 2.00122166e-06])
message: 'Optimization terminated successfully.'
nfev: 60
nit: 6
njev: 15
status: 0
success: True
x: array([0.00179748, 0.00118076])
message: ['requested number of basinhopping iterations completed successfully']
minimization_failures: 0
nfev: 6104
nit: 100
njev: 1526
x: array([0.00179748, 0.00118076])
weights: [0.00179748 0.00118076]
我有一个类似的问题,问题原来是函数和约束正在输出具有单个元素的 numpy 数组。将这两个函数的输出更改为浮点数解决了问题。
一个复杂问题的非常简单的解决方案。
我正在尝试最小化一个基本如下所示的函数:
实际上它有两个自变量,但由于 x1 + x2 = 1,它们并不是真正独立的。
现在是 objective 函数
def calculatePVar(w,covM):
w = np.matrix(w)
return (w*covM*w.T) [0,0]
wnere w 是每个资产的权重列表,covM 是由 pandas
的 .cov() 返回的协方差矩阵这里是调用优化函数的地方:
w0 = []
for sec in portList:
w0.append(1/len(portList))
bnds = tuple((0,1) for x in w0)
cons = ({'type': 'eq', 'fun': lambda x: np.sum(x)-1.0})
res= minimize(calculatePVar, w0, args=nCov, method='SLSQP',constraints=cons, bounds=bnds)
weights = res.x
现在函数有一个明确的最小值,但最小化只会吐出初始值作为结果,它确实显示 "Optimization terminated sucessfully"。有什么建议吗?
优化结果:
P.S。图片作为链接,因为我不符合要求!
你的代码只有一些令人困惑的变量,所以我只是清除了它并简化了一些行,现在最小化工作正常。然而,现在的问题是:结果是否正确?它们有意义吗?那就是给你判断:
import numpy as np
from scipy.optimize import minimize
def f(w, cov_matrix):
return (np.matrix(w) * cov_matrix * np.matrix(w).T)[0,0]
cov_matrix = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
p = [1, 2, 3]
w0 = [(1/len(p)) for e in p]
bnds = tuple((0,1) for e in w0)
cons = ({'type': 'eq', 'fun': lambda w: np.sum(w)-1.0})
res = minimize(f, w0,
args = cov_matrix,
method = 'SLSQP',
constraints = cons,
bounds = bnds)
weights = res.x
print(res)
print(weights)
更新:
根据您的评论,在我看来-也许-您的函数有多个最小值,这就是 scipy.optimize.minimize
被困在那里的原因。我建议 scipy.optimize.basinhopping
作为替代方案,这将使用随机步骤来遍历函数的大部分最小值,它仍然会很快。这是代码:
import numpy as np
from scipy.optimize import basinhopping
class MyBounds(object):
def __init__(self, xmax=[1,1], xmin=[0,0] ):
self.xmax = np.array(xmax)
self.xmin = np.array(xmin)
def __call__(self, **kwargs):
x = kwargs["x_new"]
tmax = bool(np.all(x <= self.xmax))
tmin = bool(np.all(x >= self.xmin))
return tmax and tmin
def f(w):
global cov_matrix
return (np.matrix(w) * cov_matrix * np.matrix(w).T)[0,0]
cov_matrix = np.array([[0.000244181, 0.000198035],
[0.000198035, 0.000545958]])
p = ['ABEV3', 'BBDC4']
w0 = [(1/len(p)) for e in p]
bnds = tuple((0,1) for e in w0)
cons = ({'type': 'eq', 'fun': lambda w: np.sum(w)-1.0})
bnds = MyBounds()
minimizer_kwargs = {"method":"SLSQP", "constraints": cons}
res = basinhopping(f, w0,
accept_test = bnds)
weights = res.x
print(res)
print("weights: ", weights)
输出:
fun: 2.3907094432990195e-09
lowest_optimization_result: fun: 2.3907094432990195e-09
hess_inv: array([[ 2699.43934183, -1184.79396719],
[-1184.79396719, 1210.50404805]])
jac: array([1.34548553e-06, 2.00122166e-06])
message: 'Optimization terminated successfully.'
nfev: 60
nit: 6
njev: 15
status: 0
success: True
x: array([0.00179748, 0.00118076])
message: ['requested number of basinhopping iterations completed successfully']
minimization_failures: 0
nfev: 6104
nit: 100
njev: 1526
x: array([0.00179748, 0.00118076])
weights: [0.00179748 0.00118076]
我有一个类似的问题,问题原来是函数和约束正在输出具有单个元素的 numpy 数组。将这两个函数的输出更改为浮点数解决了问题。
一个复杂问题的非常简单的解决方案。