Python 用张量流逃逸局部极小值

Python 用张量流逃逸局部极小值,python,tensorflow,gradient-descent,equation-solving,nonlinear-optimization,Python,Tensorflow,Gradient Descent,Equation Solving,Nonlinear Optimization,我用张量流解这个方程组: f1 = y - x*x = 0 f2 = x - (y - 2)*(y - 2) + 1.1 = 0 如果我选择了坏的起点(x,y)=(-1.3,2),那么我将进入局部极小值,使用以下代码优化f1^2+f2^2: f1 = y - x*x f2 = x - (y - 2)*(y - 2) + 1.1 sq=f1*f1+f2*f2 o = tf.train.AdamOptimizer(1e-1).minimize(sq) with tf.Session() as s

我用张量流解这个方程组:

f1 = y - x*x = 0
f2 = x - (y - 2)*(y - 2) + 1.1 = 0

如果我选择了坏的起点(x,y)=(-1.3,2),那么我将进入局部极小值,使用以下代码优化f1^2+f2^2:

f1 = y - x*x
f2 = x - (y - 2)*(y - 2) + 1.1
sq=f1*f1+f2*f2
o = tf.train.AdamOptimizer(1e-1).minimize(sq)
with tf.Session() as sess:
    init = tf.global_variables_initializer()
    sess.run([init])
    for i in range(50):
        sess.run([o])
        r=sess.run([x,y,f1,f2])
        print("x",r)
如何使用内置的tensorflow工具避开这个局部极小值?可能还有其他TF方法可以用来解决这个问题吗?

Tensorflow(TF)不包括内置的全局优化方法。依赖于初始化,TF中所有基于梯度的方法(如Adam)都可以收敛到非凸损失函数的局部最小值。对于大型神经网络来说,这通常是可以接受的(如果不需要的话),因为在接近全局最小值时存在过拟合问题

对于此特定问题,您可能需要scipy的根解决例程:


目前,没有内置tensorflow的全局优化方法。通过在scipy world上打开了一个窗口,但它(当前?)仅包装scipy的
最小化
,这是一个局部最小化

但是,您仍然可以将tensorflow的执行结果视为任何其他函数,这些函数可以提供给您选择的优化器。假设您想使用scipy的全局优化器进行实验。你可以写

import numpy as np
from scipy.optimize import basinhopping
import tensorflow as tf

v = tf.placeholder(dtype=tf.float32, shape=(2,))
x = v[0]
y = v[1]

f1 = y - x*x
f2 = x - (y - 2)*(y - 2) + 1.1
sq = f1 * f1 + f2 * f2
starting_point = np.array([-1.3, 2.0], np.float32)

with tf.Session() as sess:
  o = basinhopping(lambda x: sess.run(sq, {v: x}), x0=starting_point, T=10, niter=1000)
print(o.x)
# [0.76925635 0.63757862]
(我不得不调整
basinhopping
的温度和迭代次数,因为默认值通常不会让解脱离作为起点的局部最小值的范围)

通过将tensorflow视为优化器的黑盒,优化器无法访问由tensorflow自动计算的渐变。从这个意义上说,它不是最优的——尽管您仍然受益于GPU加速来计算您的函数

编辑

由于您可以明确提供
basinhopping
使用的局部最小值的梯度,因此您可以输入tensorflow的梯度结果:

import numpy as np
from scipy.optimize import basinhopping
import tensorflow as tf

v = tf.placeholder(dtype=tf.float32, shape=(2,))
x = v[0]
y = v[1]

f1 = y - x*x
f2 = x - (y - 2)*(y - 2) + 1.1
sq = f1 * f1 + f2 * f2
sq_grad = tf.gradients(sq, v)[0]
init_value = np.array([-1.3, 2.0], np.float32)

with tf.Session() as sess:
  def f(x):
    return sess.run(sq, {v: x})
  def g(x):
    return sess.run(sq_grad, {v: x})
  o = basinhopping(f, x0 = init_value, T=10.0, niter=1000, minimizer_kwargs={'jac': g})
print(o.x)
# [0.79057982 0.62501636]

出于某种原因,这比不提供梯度要慢得多——不过可能是提供了梯度,最小化算法不同,因此比较可能没有意义。

我的understanding@Metahominid,那是错误的,SGD在我们有批次时有效。此问题中没有批次。