Python SciPy&x27;s minimize根本不是迭代

Python SciPy&x27;s minimize根本不是迭代,python,scipy,scipy-optimize,Python,Scipy,Scipy Optimize,我试图最小化一个基本上如下所示的函数: 实际上,它有两个自变量,但由于x1+x2=1,它们不是真正独立的 现在是目标函数 def calculatePVar(w,covM): w = np.matrix(w) return (w*covM*w.T) [0,0] wnere w是每个资产的权重列表,covM是由参数的.cov()返回的协方差矩阵 这里调用了优化函数: w0 = [] for sec in portList: w0.append(1/len(portLis

我试图最小化一个基本上如下所示的函数:

实际上,它有两个自变量,但由于x1+x2=1,它们不是真正独立的

现在是目标函数

def calculatePVar(w,covM):
    w = np.matrix(w)
    return (w*covM*w.T) [0,0]
wnere w是每个资产的权重列表,covM是由参数的.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
现在函数有了一个明确的最小值,但minimize只会吐出初始值作为结果,它确实表示“优化成功终止”。有什么建议吗

优化结果:


附加图片作为链接,因为我不符合要求

您的代码中只有一些令人困惑的变量,所以我刚刚清除了这些变量并简化了一些行,现在最小化工作正常了。然而,现在的问题是:结果是否正确?它们有意义吗?这由你来判断:

将numpy导入为np
从scipy.optimize导入最小化
def f(w,cov_矩阵):
返回(np.矩阵(w)*cov_矩阵*np.矩阵(w).T)[0,0]
cov_矩阵=np.数组([[1,2,3],
[4, 5, 6],
[7, 8, 9]])
p=[1,2,3]
w0=[(1/len(p))表示p中的e]
bnds=元组((0,1)表示w0中的e)
cons=({'type':'eq','fun':lambda w:np.sum(w)-1.0})
res=最小化(f,w0,
args=cov_矩阵,
方法='SLSQP',
约束=约束,
边界=bnds)
权重=res.x
打印(res)
打印(重量)
更新:

根据您的评论,在我看来-也许-您的函数有多个极小值,这就是为什么
scipy.optimize.minimize
被困在那里的原因。我建议使用
scipy.optimize.basinhopping
作为替代方法,这将使用一个随机步骤来遍历函数的大部分极小值,并且仍然很快。代码如下:

将numpy导入为np
从scipy.optimize导入basinhopping
类MyBounds(对象):
定义初始化(self,xmax=[1,1],xmin=[0,0]):
self.xmax=np.array(xmax)
self.xmin=np.array(xmin)
定义呼叫(自我,**kwargs):
x=kwargs[“x_新”]
tmax=bool(np.all(x=self.xmin))
返回tmax和tmin
def f(w):
全局cov_矩阵
返回(np.矩阵(w)*cov_矩阵*np.矩阵(w).T)[0,0]
cov_矩阵=np.数组([[0.000244181,0.000198035],
[0.000198035, 0.000545958]])
p=['ABEV3','BBDC4']
w0=[(1/len(p))表示p中的e]
bnds=元组((0,1)表示w0中的e)
cons=({'type':'eq','fun':lambda w:np.sum(w)-1.0})
bnds=MyBounds()
极小值_kwargs={“方法”:“SLSQP”,“约束”:cons}
res=基准面(f,w0,
接受(测试=bnds)
权重=res.x
打印(res)
打印(“重量:”,重量)
输出:

                        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导入为np
从scipy.optimize导入最小化
def f(w,cov_矩阵):
返回(np.矩阵(w)*cov_矩阵*np.矩阵(w).T)[0,0]
cov_矩阵=np.数组([[1,2,3],
[4, 5, 6],
[7, 8, 9]])
p=[1,2,3]
w0=[(1/len(p))表示p中的e]
bnds=元组((0,1)表示w0中的e)
cons=({'type':'eq','fun':lambda w:np.sum(w)-1.0})
res=最小化(f,w0,
args=cov_矩阵,
方法='SLSQP',
约束=约束,
边界=bnds)
权重=res.x
打印(res)
打印(重量)
更新:

根据您的评论,在我看来-也许-您的函数有多个极小值,这就是为什么
scipy.optimize.minimize
被困在那里的原因。我建议使用
scipy.optimize.basinhopping
作为替代方法,这将使用一个随机步骤来遍历函数的大部分极小值,并且仍然很快。代码如下:

将numpy导入为np
从scipy.optimize导入basinhopping
类MyBounds(对象):
定义初始化(self,xmax=[1,1],xmin=[0,0]):
self.xmax=np.array(xmax)
self.xmin=np.array(xmin)
定义呼叫(自我,**kwargs):
x=kwargs[“x_新”]
tmax=bool(np.all(x=self.xmin))
返回tmax和tmin
def f(w):
全局cov_矩阵
返回(np.矩阵(w)*cov_矩阵*np.矩阵(w).T)[0,0]
cov_矩阵=np.数组([[0.000244181,0.000198035],
[0.000198035, 0.000545958]])
p=['ABEV3','BBDC4']
w0=[(1/len(p))表示p中的e]
bnds=元组((0,1)表示w0中的e)
cons=({'type':'eq','fun':lambda w:np.sum(w)-1.0})
bnds=MyBounds()
极小值_kwargs={“方法”:“SLSQP”,“约束”:cons}
res=基准面(f,w0,
接受(测试=bnds)
权重=res.x
打印(res)
打印(“重量:”,重量)
输出:

                        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]

例如,您可能想尝试另一种方法,如
'Nelder-Mead'
。此外,您需要澄清,您的变量是什么?它们是权重
w_i
还是
x_i
。你还需要区分*乘法和点乘法,并确定哪一种适合你的需要。我很难找到其他接受约束的方法,我相信我是为内尔德·米德得到了这个错误。关于变量,权重(calculatePVar函数中的w0和w)是我的变量。至于乘法,我不知道有什么区别?正在发生的是矩阵乘法,但*正在发挥作用(数学正在验证)。您能为
portList
nCov
提供一个示例吗?portList只是一个字符串列表,但这里有一个示例:
portList=['ABEV3','BBDC4']
和dfCov(h