使用Scipy检查数据

cig3rfwq  于 2023-10-20  发布在  其他
关注(0)|答案(2)|浏览(101)

我想使用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)

z2acfund

z2acfund1#

你得到的错误是因为check_gradient只接受平面点数组。如果你使用一个形状为(20,)的数组x0而不是(4, 5),它应该可以工作。但事实并非如此!
下面是我的安装中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])

因此,它似乎真的没有准备好在其他地方的非平面阵列了。但无论哪种方式,实现都非常破碎:你应该提交一份bug报告。

rqdpfwrv

rqdpfwrv2#

关于你的代码(需要 * 矢量化 * -如果你确实需要-做 flatten()ravel()):

import numpy as np
from scipy import optimize

def sigmoid_obj(x, gradient=False):
    y = 1 / (1 + np.exp(-1*x))
    res= np.multiply(y, 1 - y) if gradient else y
    return sum(res)  # must return scalar !

def num_gradient(x):
    return optimize.approx_fprime(x, sigmoid_obj, eps)

x = np.array(np.random.uniform(-30, 30, (4, 5)))     # shape(4,5)
##x0= [0,]        # guess !! var(s) used in objective_func

eps = np.sqrt(np.finfo(float).eps)

error = optimize.check_grad(sigmoid_obj, num_gradient, x.flatten() )
print(error)

但通常情况下,objective_func只用于y_target一个x_point投影,从x0=guess开始优化。在最简单的代码版本中:

import numpy as np
from scipy import optimize

def sigmoid_obj(x, gradient=False):
    y = 1 / (1 + np.exp(-1*x))
    res= np.multiply(y, 1 - y) if gradient else y
    return res

def num_gradient(x):
    return optimize.approx_fprime(x, sigmoid_obj, eps)

x = np.array(np.random.uniform(-30, 30, (4, 5)))
x0= [0,]        # guess !! init_var(s) used in objective_func

eps = np.sqrt(np.finfo(float).eps)

error = optimize.check_grad(sigmoid_obj, num_gradient, x0 )
print(error)

?如果假设initial_guess只有一个x,则guess=x0必须是[0,]
P.S. optimize.check_grad()在内部使用optimize.approx_fprime(),最新的计算是从一个点投影到y [本地]. OR可以分析计算(使用SymPy或手动计算,如docs的示例):将numpy作为np从scipy import optimize导入

def func(x):
    return x[0]**2 - 0.5 * x[1]**3
def grad(x):
    return [2 * x[0], -1.5 * x[1]**2]   # here can be numerical_gradient=optimize.approx_fprime(...)
from scipy.optimize import check_grad
print(check_grad(func, grad, x0= [1.5, -1.5]))

相关问题