这篇文章主要讲:
相信这个对于大部分人来说并不陌生,听过吴恩达公开课的都知道(escape….)
我们知道梯度方向是函数下降最快的方向(书上有证明).梯度下降就是沿着梯度负方向构造一个点: xx−αxx (粗体表示列向量),将其泰勒展开我们有
那么我们有当 α 足够小的时候,有 f(xx−αxx)<f(xx)
因此我们可以用如下迭代公式来求极小值点
αk 称为步长.
这其实只是改进 αk 的选择方法. αk 选择方式如下
注意 注意到上面的函数只是一个一维优化因此可以用前面的Introduction to Optimization:一维最优化方法
来优化,其中 αk 并不需要很好的精度
这里给出几个停机准则:
|fk+1−fk|max{1,|fk|}<ϵ
||xxk+1−xxk||max{1,||xxk||}<ϵ
||∇fk||<ϵ
这里不加证明的记录几条关于最速降的性质
最速降算法收敛阶为 1阶 收敛很慢
完整代码在这里https://github.com/DylanFrank/optimize
def fast_gradient(fun, grad, x0, tol=1e-7, max_iter=500):
phi = lambda alpha, x: fun(x - alpha * np.array(grad(x))) # 最速降参数
iters = max_iter
while iters > 0:
iters -= 1
res = minimize_scalar(phi, method='brent', args=x0, tol=1e-5)
x_next = x0 - res.x * np.array(grad(x0))
if is_stop(x_next, x0, tol):
break
x0 = x_next
return OptimizeResult({'x': x0, 'fun': fun(x0), 'jac': grad(x0), 'nit': max_iter - iters})
只有几行,代码非常短
用rosenbrock 函数来测试一下
my opt
fun: 3.5307940531271921e-11
jac: array([ 7.90266005e-06, 1.98987364e-06])
nit: 17613
x: array([ 1.00000594, 1.00001189])
scipy.opt.minimize
fun: 9.817296647123749e-14
hess_inv: array([[ 0.48098005, 0.95985458],
[ 0.95985458, 1.92027267]])
jac: array([ -8.75835534e-06, 4.59236316e-06])
message: 'Optimization terminated successfully.'
nfev: 42
nit: 35
njev: 42
status: 0
success: True
x: array([ 1.00000021, 1.00000045])
用最速降方法迭代了接近 20000次而用scipy.optimize 的NM单纯形只用了35次简直是天壤之别难怪optimize 里没有实现。别急没多久就要学到 N-M单纯形了
转载请注明本文链接 http://blog.csdn.net/Dylan_Frank/article/details/78220959