赞
踩
高次方程没有通解,可以依靠牛顿迭代法来求解。没有根式解不意味着方程解不出来,数学家也提供了很多方法,牛顿迭代法就是其中一种。
首先,切线是曲线的线性逼近。可以通过研究简单切线的解来近似的逼近复杂曲线的解随便找一个曲线上的A点(为什么随便找,根据切线是切点附近的曲线的近似,应该在根点附近找,但是很显然我们现在还不知道根点在哪里),做一个切线,切线的根(就是和x轴的交点)与曲线的根,还有一定的距离。我们从这个切线的根出发,做一根垂线,和曲线相交于B点,继续重复刚才的工作;B点比之前A点更接近曲线的根点,我们继续重复刚才的工作;经过多次迭代后会越来越接近曲线的根,从数学的角度上说,切线收敛了,此时我们就得到了一个曲线近似的解。
from sympy import * # step为迭代步数,x0为初始位置,obj为要求极值的函数 def newtons(step, x0, obj): i = 1 # 记录迭代次数的变量 x0 = float(x0) # 浮点数计算更快 obj_deri = diff(obj, x) # 定义一阶导数,对应上述公式 obj_sec_deri = diff(obj, x, 2) # 定义二阶导数,对应上述公式 while i <= step: if i == 1: # 第一次迭代的更新公式 xnew = x0 - (obj_deri.subs(x, x0)/obj_sec_deri.subs(x, x0)) print('迭代第%d次:%.5f' %(i, xnew)) i = i + 1 else: #后续迭代的更新公式 xnew = xnew - (obj_deri.subs(x, xnew)/obj_sec_deri.subs(x, xnew)) print('迭代第%d次:%.5f' % (i, xnew)) i = i + 1 return xnew x = symbols("x") # x为字符变量 result = newtons(50, 10, x**6+x) print('最佳迭代的位置:%.5f' %result)
迭代第1次:8.00000 迭代第2次:6.39999 迭代第3次:5.11997 迭代第4次:4.09593 迭代第5次:3.27662 迭代第6次:2.62101 迭代第7次:2.09610 迭代第8次:1.67515 迭代第9次:1.33589 迭代第10次:1.05825 迭代第11次:0.82002 迭代第12次:0.58229 迭代第13次:0.17590 迭代第14次:-34.68063 迭代第15次:-27.74450 迭代第16次:-22.19560 迭代第17次:-17.75648 迭代第18次:-14.20519 迭代第19次:-11.36415 迭代第20次:-9.09132 迭代第21次:-7.27306 迭代第22次:-5.81846 迭代第23次:-4.65480 迭代第24次:-3.72391 迭代第25次:-2.97930 迭代第26次:-2.38386 迭代第27次:-1.90812 迭代第28次:-1.52901 迭代第29次:-1.22931 迭代第30次:-0.99804 迭代第31次:-0.83203 迭代第32次:-0.73518 迭代第33次:-0.70225 迭代第34次:-0.69886 迭代第35次:-0.69883 迭代第36次:-0.69883 迭代第37次:-0.69883 迭代第38次:-0.69883 迭代第39次:-0.69883 迭代第40次:-0.69883 迭代第41次:-0.69883 迭代第42次:-0.69883 迭代第43次:-0.69883 迭代第44次:-0.69883 迭代第45次:-0.69883 迭代第46次:-0.69883 迭代第47次:-0.69883 迭代第48次:-0.69883 迭代第49次:-0.69883 迭代第50次:-0.69883 最佳迭代的位置:-0.69883
关于梯度下降算法的直观理解,我们以一个人下山为例。比如刚开始的初始位置是山顶位置,那么现在的问题是该如何达到山底呢?按照梯度下降算法的思想,它将按如下操作达到最低点:
第一步,明确自己现在所处的位置
第二步,找到相对于该位置而言下降最快的方向
第三步, 沿着第二步找到的方向走一小步,到达一个新的位置,此时的位置肯定比原来低
第四部, 回到第一步
第五步,终止于最低点
按照以上5步,最终达到最低点,这就是梯度下降的完整流程。
梯度下降的基本过程就和下山的场景很类似。
首先,我们有一个可微分的函数。这个函数就代表着一座山。我们的目标就是找到这个函数的最小值,也就是山底。根据之前的场景假设,最快的下山的方式就是找到当前位置最陡峭的方向,然后沿着此方向向下走,对应到函数中,就是找到给定点的梯度 ,然后朝着梯度相反的方向,就能让函数值下降的最快!因为梯度的方向就是函数之变化最快的方向(在后面会详细解释)
所以,我们重复利用这个方法,反复求取梯度,最后就能到达局部的最小值,这就类似于我们下山的过程。而求取梯度就确定了最陡峭的方向,也就是场景中测量方向的手段
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import math
from mpl_toolkits.mplot3d import Axes3D
import warnings
导入一些必要的库特别是用于3D绘图的库
def f2(x1,x2):
return x1*x1+2*x2*x2-4*x1-2*x1*x2
X1 = np.arange(-4,4,0.2)
X2 = np.arange(-4,4,0.2)
X1, X2 = np.meshgrid(X1, X2) # 生成xv、yv,将X1、X2变成n*m的矩阵,方便后面绘图
Y = np.array(list(map(lambda t : f2(t[0],t[1]),zip(X1.flatten(),X2.flatten()))))
Y.shape = X1.shape # 1600的Y图还原成原来的(40,40)
%matplotlib inline
#作图
fig = plt.figure(facecolor='w')
ax = Axes3D(fig)
ax.plot_surface(X1,X2,Y,rstride=1,cstride=1,cmap=plt.cm.jet)
ax.set_title
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。