我正在为一个无约束优化问题创建一个基本的牛顿法算法,我的算法结果不是我所期望的这是一个简单的目标函数,因此很明显算法应该收敛于(1,1)我之前创建的梯度下降算法证实了这一点,这里:

def grad_descent(x, t, count, magnitude):
    xvalues.append(x)
    gradvalues.append(np.array([dfx1(x), dfx2(x)]))
    fvalues.append(f(x))
    temp=x-t*dfx(x)
    x = temp
    magnitude = mag(dfx(x))
    count+=1

    return xvalues, gradvalues, fvalues, count

我尝试创建牛顿法的算法如下:
def newton(x, t, count, magnitude):
  xvalues=[]
  gradvalues=[]
  fvalues=[]
  temp=x-f(x)/dfx(x)

  while count < 10:
    xvalues.append(x)
    gradvalues.append(dfx(x))
    fvalues.append(f(x))

    temp=x-t*f(x)/dfx(x)
    x = temp
    magnitude = mag(dfx(x))
    count+=1
    if count > 100:
      break
  return xvalues, gradvalues, fvalues, count

这里是目标函数和梯度函数:
f = lambda x: 100*np.square(x[1]-np.square(x[0])) + np.square((1-x[0]))
dfx = lambda x: np.array([-400*x[0]*x[1]+400*np.power(x[0],3)+2*x[0]-2, 200*(x[1]-np.square(x[0]))])

以下是初始条件注意,alpha和beta不用于newton方法。
x0, t0, alpha, beta, count = np.array([-1.1, 1.1]), 1, .15, .7, 1
magnitude = mag(np.array([dfx1(x0), dfx2(x0)]))

要调用函数:
xvalues, gradvalues, fvalues, iterations = newton(x0, t0, count, magnitude)

这产生了非常奇怪的结果。以下是xvalue、gradient value和function solution的前10次迭代,分别用于其各自的x输入:
[array([-1.1,  1.1]), array([-0.99315589,  1.35545455]), array([-1.11651296,  1.11709035]), array([-1.01732476,  1.35478987]), array([-1.13070578,  1.13125051]), array([-1.03603697,  1.35903467]), array([-1.14368874,  1.14364506]), array([-1.05188162,  1.36561528]), array([-1.15600558,  1.15480705]), array([-1.06599492,  1.37360245])]
[array([-52.6, -22. ]), array([142.64160215,  73.81918332]), array([-62.07323963, -25.90216846]), array([126.11789251,  63.96803995]), array([-70.85773749, -29.44900758]), array([114.31050737,  57.13241151]), array([-79.48668009, -32.87577304]), array([104.93863096,  51.83206539]), array([-88.25737032, -36.308371  ]), array([97.03403558, 47.45145765])]
[5.620000000000003, 17.59584998020613, 6.156932949106968, 14.29937453260906, 6.7080172227439725, 12.305727666787176, 7.297442528545537, 10.926625703722639, 7.944104584786208, 9.89743708419569]

以下是最终输出:
final_value = print('Final set of x values: ', xvalues[-1])
final_grad = print('Final gradient values: ', gradvalues[-1])
final_f = print('Final value of the object function with optimized inputs: ', fvalues[-1])
final_grad_mag = print('Final magnitude of the gradient with optimized inputs: ', mag(np.array([dfx1(xvalues[-1]), dfx2(xvalues[-1])])))
total_iterations = print('Total iterations: ', iterations)

显示一个3d绘图here
代码:
x = np.array([i[0] for i in xvalues])
y = np.array([i[1] for i in xvalues])
z = np.array(fvalues)
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.scatter(x, y, z, label='Newton Method')
ax.legend()

这是因为最初的猜测是如此接近最优点,还是因为我的算法有一些错误,我没有抓住?任何建议都将不胜感激。看起来溶液甚至可能在振荡,但很难说

最佳答案

我想我找到了问题的一部分。我使用了错误的牛顿算法在我使用之前:
x{k+1}=x{k}-f(x)/f(x)
正确的更新是:
x{k+1}=x{k}-[f'(x{k})]-1f'(x{k})
当我改变这一点时,结果仍然是不同的,但稍微好一点新功能如下:

f = lambda x: 100*np.square(x[1]-np.square(x[0])) + np.square((1-x[0]))
dfx1 = lambda x: -400*x[0]*x[1]+400*np.power(x[0],3)+2*x[0]-2
dfx2 = lambda x: 200*(x[1]-np.square(x[0]))
dfx = lambda x: np.array([-400*x[0]*x[1]+400*np.power(x[0],3)+2*x[0]-2, 200*(x[1]-np.square(x[0]))])
dfx11 = lambda x: -400*(x[1])+1200*np.square(x[0])+2
dfx12 = lambda x: -400*x[0]
dfx21 = lambda x: -400*x[0]
dfx22 = lambda x: 200
hessian = lambda x: np.array(([dfx11(x0), dfx12(x0)], [dfx21(x0), dfx22(x0)]))
inv_hessian = lambda x: inv(np.array(([dfx11(x0), dfx12(x0)], [dfx21(x0), dfx22(x0)])))

def newton(x, t, count, magnitude):
  xvalues=[]
  gradvalues=[]
  fvalues=[]
  temp = x-(inv_hessian(x).dot(dfx(x)))

  while count < 25:
    xvalues.append(x)
    gradvalues.append(dfx(x))
    fvalues.append(f(x))

    temp = x-(inv_hessian(x).dot(dfx(x)))
    x = temp
    magnitude = mag(dfx(x))
    count+=1
    if count > 100:
      break
  return xvalues, gradvalues, fvalues, count

最接近于收敛的解是在第一步之后,它到达了(-1.05,1.1)然而,它仍然存在分歧我从来没有用过牛顿法,所以我不确定这是否像算法要得到的那样精确。
python - 如何判断牛顿法是否失败-LMLPHP

10-08 19:59