【问题标题】:Checking Gradients with Scipy用 Scipy 检查梯度
【发布时间】:2013-02-09 00:29:09
【问题描述】:

我想使用scipy.optimize.check_grad 来检查我对sigmoid function 的实现的梯度;这是我的 Python 函数:

def sigmoid(x, gradient=False):
    y = 1 / (1 + numpy.exp(-x))
    return numpy.multiply(y, 1 - y) if gradient else y

这里是参数和对check_grad的调用:

x0 = numpy.random.uniform(-30, 30, (4, 5))
func = sigmoid
grad = lambda x: sigmoid(x, gradient=True)
error = scipy.optimize.check_grad(func, grad, x0)

我收到以下错误。形状不匹配是指操作xk+d。知道是什么原因造成的吗?

文件“scipy\optimize\optimize.py”,第 597 行,在 approx_fprime
grad[k] = (f(*((xk+d,)+args)) - f0) / d[k]
ValueError: 操作数不能与形状一起广播 (4,5) (4)

【问题讨论】:

  • 如下所述,这是因为要检查梯度,您必须遍历矩阵的每个元素和 +/- 一些 epsilon 才能计算导数(使用标准方程)。 Scipy 可以为您展平您的矩阵。但是,使用M.flatten() 自己传递一个扁平化版本应该很容易。在 Matlab 中,您只需执行 M(:).

标签: python math scipy gradient


【解决方案1】:

你得到的错误是因为check_gradient 只接受点的平面数组。如果您使用形状为(20,) 而不是(4, 5) 的数组x0,它应该可以工作。但事实并非如此!

这是approx_fprime在我的安装中的实现(scipy.__version__ = '0.9.0'):

def approx_fprime(xk,f,epsilon,*args):
    f0 = f(*((xk,)+args))
    grad = numpy.zeros((len(xk),), float)
    ei = numpy.zeros((len(xk),), float)
    for k in range(len(xk)):
        ei[k] = epsilon
        grad[k] = (f(*((xk+ei,)+args)) - f0)/epsilon
        ei[k] = 0.0
    return grad

我已经看了好几遍,很难相信这么糟糕的代码会在 scipy 发行版中,我确信我一定遗漏了一些东西......但我担心它是错误的。如果您将其替换为:

def approx_fprime(xk,f,epsilon,*args):
    return (f(*((xk + epsilon,) + args)) - f(*((xk,) + args))) / epsilon

它现在对我有用。使用x0.shape = (20,) 我得到:

In [2]: error
Out[2]: 1.746097524556073e-08

还有x0.shape = (4, 5):

In [4]: error
Out[4]: 
array([  1.03560895e-08,   1.45994321e-08,   8.54143390e-09,
         1.09225833e-08,   9.85988655e-09])

所以它似乎真的没有为其他地方的非平面数组做好准备。但无论哪种方式,实现都非常糟糕:您应该提交错误报告。

【讨论】:

  • 这种近似梯度的方法不起作用。您应该一次将每个参数增加一个eps。例如,当f 将数组映射到标量时:梯度应该是一个数组,但(f(x+eps) - f(x)) / eps 会产生一个标量。
  • @PaulManta 我明白了,毕竟它并没有那么错,这就是问题所在......在我看来,它仍然是一个非常无用的函数。我认为它的设置方式仅适用于将向量转换为标量的函数,然后x0 必须是单个向量,而不是一堆向量。在您的情况下,如果x0.shape = (1,),您可以让您的电话工作,即如果您给它一个长度为1的向量,它不适用于标量。据我所知,这和它被打破一样好!
  • 是的,很遗憾,check_grad 在很多情况下都没有用。嗯,算法很容易实现,所以应该不是什么大问题。
猜你喜欢
  • 1970-01-01
  • 2011-09-27
  • 2017-03-30
  • 1970-01-01
  • 2021-06-12
  • 2016-04-17
  • 2022-06-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多