我不确定你要做什么
func(x + t*grad(x, A, b, c), A, b, c)
t 是什么?
无论如何,您对fmin_cg 的调用是不正确的——fmin_cg 的签名是
fmin_cg(f, x0, fprime=None, args=(), ...)
第一个参数需要是你的目标函数func,第二个需要是你对x的初始猜测,第三个(可选)参数是你的梯度函数grad,第四个是f 和 fprime 的附加 参数集(不包括 x)。
调用应该如下所示:
scipy.optimize.fmin_cg(func, x, fprime=grad, args=(A, b, c))
但是,由于您的数组尺寸存在问题,这仍然不起作用:
<ipython-input-49-bf5fa71345fe> in grad(x, A, b, c)
1 def grad(x, A, b, c):
----> 2 gradient = A * (1.0/(b - A.transpose()*x)) + c
3 return gradient
4
/home/alistair/.venvs/core/local/lib/python2.7/site-packages/numpy/matrixlib/defmatrix.pyc in __mul__(self, other)
341 if isinstance(other, (N.ndarray, list, tuple)) :
342 # This promotes 1-D vectors to row vectors
--> 343 return N.dot(self, asmatrix(other))
344 if isscalar(other) or not hasattr(other, '__rmul__') :
345 return N.dot(self, other)
ValueError: shapes (500,100) and (1,100) not aligned: 100 (dim 1) != 1 (dim 0)
要弄清楚为什么会发生这种情况,我们可以在grad 中设置断点:
import pdb
def grad(x, A, b, c):
pdb.set_trace()
gradient = A * (1.0/(b - A.transpose()*x)) + c
return gradient
在第一次调用grad 时,我们看到:
(Pdb) type(x)
<type 'numpy.ndarray'>
(Pdb) !x.shape
(100,)
fmin_cg 内部的某处,x 正在从 (100, 1) np.matrix 转换为 (100,) 1D np.ndarray。对于np.ndarray,* 运算符执行elementwise 乘法而不是矩阵乘法,这将失败,因为x 和A.transpose() 具有不兼容的维度。
基本上你遇到了这样一个事实,即np.matrix 没有被 numpy 和 scipy 中的许多函数完全支持,这些函数期望 np.ndarray。我强烈建议您从使用np.matrix 切换到np.ndarray - 使用np.matrix 是officially discouraged,并且在不久的将来可能会被弃用。
您的grad 函数可以重写为:
def grad(x, A, b, c):
gradient = A.dot(1.0/(b - A.T.dot(x))) + c
return gradient
...您的初始参数为:
np.random.seed(1234)
m = 500 #500
n = 100 #100
A = np.random.randint(low=-10, high=1, size=(n, m))
b = np.random.randint(low=500, high=1000, size=m)
c = np.random.randint(low=0.1, high=2, size=n)
x = np.random.randint(low=1, high=10, size=n)
...现在您拨打fmin_cg 应该可以了:
res = scipy.optimize.fmin_cg(func, x, fprime=grad, args=(A, b, c))