在梯度下降实现中进行更新时遇到问题?
Having trouble making update in gradient descent implementation?
您好,我正在研究使用回溯线搜索实现梯度下降。但是,当我尝试更新 f(x0) 时,该值不会改变。会不会是lambda表达式出了什么问题,我不是很熟悉?
import numpy as np
import math
alpha = 0.1
beta = 0.6
f = lambda x: math.exp(x[0] + 3*x[1] - 0.1) + math.exp(x[0] - 3*x[1] -0.1) + math.exp(-1*x[0] - 0.1)
dfx1 = lambda x: math.exp(x[0] + 3*x[1] - 0.1) + math.exp(x[0] - 3*x[1] -0.1) - math.exp(-x[0] - 0.1)
dfx2 = lambda x: 3*math.exp(x[0] + 3*x[1] - 0.1) - 3*math.exp(x[0] - 3*x[1] -0.1)
t = 1
count = 1
x0 = np.array([1.0,1.0])
dx0 = np.array([1e-3, 1e-3])
x = []
d = np.array([-1*dfx1(x0),-1*dfx2(x0)]);
grad = np.array([1*dfx1(x0),1*dfx2(x0)])
def backtrack(x0, dfx1, dfx2, t, alpha, beta, count):
while (f(x0 + t*d) > f(x0) + alpha*t*np.dot(d,grad) or count < 50 ):
d[0] = -1*dfx1(x0);
d[1] = -1*dfx2(x0);
grad[0] = dfx1(x0);
grad[1] = dfx2(x0);
x0[0] = x0[0] + t*d[0];
x0[1] = x0[1] + t*d[1];
t *= beta;
count += 1
x.append(f(x0));
return t
t = backtrack(x0, dfx1, dfx2, t, alpha, beta,count)
print("\nfinal step size :", t)
print(np.log(x))
print(f(x0))
新代码更新
好的,你的数字现在变化太大了!
在编写这些例程时,使用调试器单步执行代码对于检查代码是否按照您的要求执行非常有用。在这种情况下,您会在第二次通过循环时看到 x0 = [-1.32e+170, 3.96e+170]
。取其指数是导致问题的原因。如果您没有调试器,请尝试打印一些值。
你能做些什么来解决它?一种解决方法是减少 t
。以 t=1e-3
开头可以解决问题。
但是,我怀疑您还有其他问题。我不知道你正在尝试实施的技术,但我怀疑 t
不应该只是每一步减少一个固定的比率,并且 np.dot(...)
带有反平行向量的术语看起来也很可疑.
如果实现不是重点,是否有库函数可以满足您的需求?例如,如果您只想从起点 1, 1
最小化 f
,请参阅 SciPy [https://docs.scipy.org/doc/scipy/reference/generated/scipy 中的最小化函数。 optimize.minimize.html]
import scipy.optimize
import numpy as np
def get_exponentials(x):
a = np.exp(x[0] + 3 * x[1] - 0.1)
b = np.exp(x[0] - 3 * x[1] - 0.1)
c = np.exp(-x[0] - 0.1)
return a, b, c
def dfdx(x):
a, b, c = get_exponentials(x)
return np.array([a + b - c, 3 * (a - b)])
def f(x):
a, b, c = get_exponentials(x)
return a + b + c
scipy.optimize.minimize(f, np.array([1.0, 1.0]), jac=dfdx)
# x = [-3.46573682e-01, -5.02272755e-08]), f = 2.559267
如果行搜索对您特别重要,可以使用 [https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.line_search.html]:
scipy.optimize.line_search(f, dfdx, np.array([1.0, 1.0]), np.array([-1.0, -1.0]))
# alpha 1.0,
# number of function calls 2,
# number of gradient calls 1,
# new function value 2.7145122541078788,
# old function value 49.85777661748123,
# new gradient [0.90483742, 0.]
最后 - 您最初说过您对 lambda 不满意 - 根本没有必要使用它们。它们不常用于生成命名函数。有关更多讨论,请参阅 [
您好,我正在研究使用回溯线搜索实现梯度下降。但是,当我尝试更新 f(x0) 时,该值不会改变。会不会是lambda表达式出了什么问题,我不是很熟悉?
import numpy as np
import math
alpha = 0.1
beta = 0.6
f = lambda x: math.exp(x[0] + 3*x[1] - 0.1) + math.exp(x[0] - 3*x[1] -0.1) + math.exp(-1*x[0] - 0.1)
dfx1 = lambda x: math.exp(x[0] + 3*x[1] - 0.1) + math.exp(x[0] - 3*x[1] -0.1) - math.exp(-x[0] - 0.1)
dfx2 = lambda x: 3*math.exp(x[0] + 3*x[1] - 0.1) - 3*math.exp(x[0] - 3*x[1] -0.1)
t = 1
count = 1
x0 = np.array([1.0,1.0])
dx0 = np.array([1e-3, 1e-3])
x = []
d = np.array([-1*dfx1(x0),-1*dfx2(x0)]);
grad = np.array([1*dfx1(x0),1*dfx2(x0)])
def backtrack(x0, dfx1, dfx2, t, alpha, beta, count):
while (f(x0 + t*d) > f(x0) + alpha*t*np.dot(d,grad) or count < 50 ):
d[0] = -1*dfx1(x0);
d[1] = -1*dfx2(x0);
grad[0] = dfx1(x0);
grad[1] = dfx2(x0);
x0[0] = x0[0] + t*d[0];
x0[1] = x0[1] + t*d[1];
t *= beta;
count += 1
x.append(f(x0));
return t
t = backtrack(x0, dfx1, dfx2, t, alpha, beta,count)
print("\nfinal step size :", t)
print(np.log(x))
print(f(x0))
新代码更新
好的,你的数字现在变化太大了!
在编写这些例程时,使用调试器单步执行代码对于检查代码是否按照您的要求执行非常有用。在这种情况下,您会在第二次通过循环时看到 x0 = [-1.32e+170, 3.96e+170]
。取其指数是导致问题的原因。如果您没有调试器,请尝试打印一些值。
你能做些什么来解决它?一种解决方法是减少 t
。以 t=1e-3
开头可以解决问题。
但是,我怀疑您还有其他问题。我不知道你正在尝试实施的技术,但我怀疑 t
不应该只是每一步减少一个固定的比率,并且 np.dot(...)
带有反平行向量的术语看起来也很可疑.
如果实现不是重点,是否有库函数可以满足您的需求?例如,如果您只想从起点 1, 1
最小化 f
,请参阅 SciPy [https://docs.scipy.org/doc/scipy/reference/generated/scipy 中的最小化函数。 optimize.minimize.html]
import scipy.optimize
import numpy as np
def get_exponentials(x):
a = np.exp(x[0] + 3 * x[1] - 0.1)
b = np.exp(x[0] - 3 * x[1] - 0.1)
c = np.exp(-x[0] - 0.1)
return a, b, c
def dfdx(x):
a, b, c = get_exponentials(x)
return np.array([a + b - c, 3 * (a - b)])
def f(x):
a, b, c = get_exponentials(x)
return a + b + c
scipy.optimize.minimize(f, np.array([1.0, 1.0]), jac=dfdx)
# x = [-3.46573682e-01, -5.02272755e-08]), f = 2.559267
如果行搜索对您特别重要,可以使用 [https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.line_search.html]:
scipy.optimize.line_search(f, dfdx, np.array([1.0, 1.0]), np.array([-1.0, -1.0]))
# alpha 1.0,
# number of function calls 2,
# number of gradient calls 1,
# new function value 2.7145122541078788,
# old function value 49.85777661748123,
# new gradient [0.90483742, 0.]
最后 - 您最初说过您对 lambda 不满意 - 根本没有必要使用它们。它们不常用于生成命名函数。有关更多讨论,请参阅 [