我是scipy.optimize的新手,在看了它的教程和参考之后,我仍然不明白我在代码中做错了什么。我读过这篇文章,也不明白:Scipy optimize.minimize function
这里D是M*N矩阵,y是M*1矩阵。X应该是一个N*1矩阵(因为我需要计算它)。我需要最小化x中的L2范数,确保x中的每个元素都大于0。也须遵守Dx=y。最后:
极小维x_x_2
Dx=y
x>=0
import scipy
from numpy import *
def square_sum(x):
#x must be 1*N?
x = x.reshape(len(x),1)
y = dot(x.T,x)
return y
def lessObsConstrain(x,D,y):
#Dy=x equals (Dy-x)^2=0
temp = y - dot(D,x.reshape(len(x),1))
temp = temp.reshape(1,len(temp))
return dot(temp,temp.T)
x0=ones((D.shape[1],))
result = scipy.optimize.minimize(square_sum, x0, args=(), method='SLSQP', jac=None, bounds=scipy.optimize.Bounds(0, 1), constraints=[{'type':'eq','fun':lessObsConstrain,'args':(D,y)}], tol=None, callback=None, options={'maxiter': 100, 'ftol': 1e-06, 'iprint': 1, 'disp': False, 'eps': 1.4901161193847656e-08})
但我知道这个错误:
在
c=串联((c_eq,c_ieq)) ValueError中,_minimize_slsqp c=串联((c_eq,c_ieq)) ValueError:所有输入数组必须具有相同的维数
谁能告诉我怎么改正我的代码吗?
发布于 2019-09-20 21:08:07
我找到了一种很难看的方法来传递这个错误。结果表明,1*1矩阵不同于标量矩阵。所以问题是数据维。
import scipy
from numpy import *
def square_sum(x):
return dot(x,x)
def lessObsConstrain(x,D,y):
temp = y - dot(D,x.reshape(len(x),1))
temp = temp.reshape(1,len(temp))
return asscalar(dot(temp,temp.T))
x0=ones((D.shape[1],))
result = scipy.optimize.minimize(square_sum, x0, args=(), method='SLSQP', jac=None, bounds=scipy.optimize.Bounds(0, 1), constraints=[{'type':'eq','fun':lessObsConstrain,'args':(D,y)}], tol=None, callback=None, options={'maxiter': 100, 'ftol': 1e-06, 'iprint': 1, 'disp': False, 'eps': 1.4901161193847656e-08})
发布于 2019-09-22 19:36:27
In [37]: from scipy import optimize
虚拟数组,只用于测试形状:
In [39]: D = np.eye(4,3); y = np.ones((4,1))
In [40]: D
Out[40]:
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.],
[0., 0., 0.]])
In [41]: y
Out[41]:
array([[1.],
[1.],
[1.],
[1.]])
In [42]: x0 = np.ones((D.shape[1],))
您的最新功能:
In [57]: def square_sum(x):
...: return np.dot(x,x)
...:
...: def lessObsConstrain(x,D,y):
...: temp = y - np.dot(D,x.reshape(len(x),1))
...: temp = temp.reshape(1,len(temp))
...: return np.asscalar(np.dot(temp,temp.T))
在最初的版本中,它们都产生了2d数组:
In [44]: square_sum(x0)
Out[44]: array([[3.]])
In [45]: lessObsConstrain(x0,D,y)
Out[45]: array([[1.]])
约束处理程序抱怨说它无法加入等式和不等式约束(我不确定它到底在连接什么):
c = concatenate((c_eq, c_ieq))
ValueError: all the input arrays must have same number of dimensions, but the array at index 0 has 2 dimension(s) and the array at index 1 has 1 dimension(s)
使用asscalar
时,lessObsConstrain
是标量的,并且连接可以工作。
In [60]: optimize.minimize(square_sum, x0, args=(), method='SLSQP', jac=None, bo
...: unds=optimize.Bounds(0, 1), constraints=[{'type':'eq','fun':lessObsCons
...: train,'args':(D,y)}], tol=None, callback=None, options={'maxiter': 100,
...: 'ftol': 1e-06, 'iprint': 1, 'disp': False, 'eps': 1.4901161193847656e-
...: 08})
/usr/local/bin/ipython3:7: DeprecationWarning: np.asscalar(a) is deprecated since NumPy v1.16, use a.item() instead
Out[60]:
fun: 2.9994000807884227
jac: array([1.99980003, 1.99980003, 1.99980003])
message: 'Positive directional derivative for linesearch'
nfev: 218
nit: 20
njev: 16
status: 8
success: False
x: array([0.99990001, 0.99990001, 0.99990001])
我推荐的是一个简单的dot
,它不需要整形。但是y
也需要1d (如x0
):
In [61]: def square_sum(x):
...: return np.dot(x,x)
...:
...: def lessObsConstrain(x,D,y):
...: #Dy=x equals (Dy-x)^2=0
...: temp = y - np.dot(D,x)
...: return np.dot(temp,temp)
In [62]: y = np.ones((4))
最小化调用会产生相同的结果:
In [56]: optimize.minimize(square_sum, x0, args=(), method='SLSQP', jac=None, bo
...: unds=optimize.Bounds(0, 1), constraints=[{'type':'eq','fun':lessObsCons
...: train,'args':(D,y)}], tol=None, callback=None, options={'maxiter': 100,
...: 'ftol': 1e-06, 'iprint': 1, 'disp': False, 'eps': 1.4901161193847656e-
...: 08})
Out[56]:
fun: 2.9994000807884227
jac: array([1.99980003, 1.99980003, 1.99980003])
message: 'Positive directional derivative for linesearch'
nfev: 218
nit: 20
njev: 16
status: 8
success: False
x: array([0.99990001, 0.99990001, 0.99990001])
更仔细地查看lessObsConstrain
。第一个点产生一个大小为M的数组(MxN与N):
In [62]: np.dot(D,x0)
Out[62]: array([1., 1., 1., 0.])
In [63]: y # (N,1)
Out[63]:
array([[1.],
[1.],
[1.],
[1.]])
In [65]: lessObsConstrain(x0,D,y)
Out[65]:
array([[0., 0., 0., 1.],
[0., 0., 0., 1.],
[0., 0., 0., 1.],
[0., 0., 0., 1.]])
(N,1)用(N,N)广播以产生(N,N)。如果y
为(N,),则temp
为1d,其dot
为标量:
In [66]: lessObsConstrain(x0,D,np.ones((4,)))
Out[66]: 1.0
dot
将A的最后一个轴与B的最后一个轴结合在一起,但是对于一维数组,它是标量矢量点,震级:
In [67]: np.dot(np.arange(3),np.arange(3))
Out[67]: 5
In [68]: np.dot(np.arange(3)[:,None],np.arange(3)[None,:])
Out[68]:
array([[0, 0, 0], # (3,1) with (1,3) => (3,3)
[0, 1, 2],
[0, 2, 4]])
In [69]: np.dot(np.arange(3)[None,:],np.arange(3)[:,None])
Out[69]: array([[5]]) # (1,3) with (3,1) => (1,1)
https://stackoverflow.com/questions/58020888
复制相似问题