我被要求在python中使用签名gradient(f, P0, gamma, epsilon)
编写渐变下降的实现,其中f是未知且可能是多变量函数,P0是梯度下降的起点,gamma是常量步长, epsilon停止标准。
我觉得棘手的是如何在f
处不知道任何内容的情况下评估P0
点f
的渐变。我知道有numpy.gradient
但我不知道在我不知道f
的尺寸的情况下如何使用它。此外,numpy.gradient
适用于函数的样本,那么如何选择正确的样本来计算某个点的渐变而没有关于函数和点的任何信息?
答案 0 :(得分:2)
我假设在这里,So how can i choose a generic set of samples each time I need to compute the gradient at a given point?
表示函数的维度是固定的,可以从起点推断出来。
使用scipy的approx_fprime来考虑这个演示,这是一个更容易使用的数字微分包装方法,当需要jacobian时,也可以在scipy的优化器中使用,但不会给出。
当然你不能忽略参数epsilon,它可以根据数据产生影响。
(这段代码也忽略了优化的args-parameter,这通常是一个好主意;我使用的事实是A和b在这里的范围内;肯定不是最佳实践)
import numpy as np
from scipy.optimize import approx_fprime, minimize
np.random.seed(1)
# Synthetic data
A = np.random.random(size=(1000, 20))
noiseless_x = np.random.random(size=20)
b = A.dot(noiseless_x) + np.random.random(size=1000) * 0.01
# Loss function
def fun(x):
return np.linalg.norm(A.dot(x) - b, 2)
# Optimize without any explicit jacobian
x0 = np.zeros(len(noiseless_x))
res = minimize(fun, x0)
print(res.message)
print(res.fun)
# Get numerical-gradient function
eps = np.sqrt(np.finfo(float).eps)
my_gradient = lambda x: approx_fprime(x, fun, eps)
# Optimize with our gradient
res = res = minimize(fun, x0, jac=my_gradient)
print(res.message)
print(res.fun)
# Eval gradient at some point
print(my_gradient(np.ones(len(noiseless_x))))
输出:
Optimization terminated successfully.
0.09272331925776327
Optimization terminated successfully.
0.09272331925776327
[15.77418041 16.43476772 15.40369129 15.79804516 15.61699104 15.52977276
15.60408688 16.29286766 16.13469887 16.29916573 15.57258797 15.75262356
16.3483305 15.40844536 16.8921814 15.18487358 15.95994091 15.45903492
16.2035532 16.68831635]
使用:
# Get numerical-gradient function with a way too big eps-value
eps = 1e-3
my_gradient = lambda x: approx_fprime(x, fun, eps)
表明eps是一个关键参数,导致:
Desired error not necessarily achieved due to precision loss.
0.09323354898565098