1 .引言
我们在初中的时候学过一元二次函数。 在求解时引入求根公式,代入公式就可以得到不同的根。 如果想计算高次方程的解,能导出求根公式吗?
伽罗瓦在群论中证实,五次以上的多项式方程没有给出表示的求根式,但在行星轨道计算等科学研究中,对求解高次方程的真正需要较多。 既然得不到明确的求根公式,我们就可以用迭代的方法逼近真实的解。
求解多项式方程的问题实际上可以看作函数求极值,如果我们是对的
的解决得到驻地,代入驻地
可以计算出函数的极值。 很明显,低阶方程的求解可以用求根公式准确计算
的值,但要解高次方程,必须使用近似的思路,如梯度下降法、最速下降法、昏迷睫毛膏法等。 本文主要讨论用昏迷睫毛膏法和python对一元函数和多元函数求极值。
2 .昏迷睫毛膏法的基本原理
2.1 .一元函数昏迷睫毛膏法
函数时
是一元函数,使用潇洒鸭公式的二次近似即可得到
一元函数取极值的条件是
、两端分别求导(下式的等号写成等号)得到
整理后拿出来
的迭代公式
进而写出迭代关系式,得到
因为昏迷睫毛膏法的迭代关系基于要求求解极值函数的导数图像的点的斜率进行迭代,所以没有步骤的概念,在什么点可以获得极值仅取决于迭代的步骤数。 相应地,迭代的次数越多越接近极值点。
在上面介绍了抽象的表达式之后,让我们来看看这样的小例子。 函数是已知的
如果没有其他限制条件的话就求出
的极值。
用昏迷睫毛膏法计算极值前,用软件绘制
的图像,用肉眼大致观测极值在哪里,有助于在后续计算中验证是否正确。
image.png
首先,需要给出初始值
这是开始迭代的位置;
然后,计算初始位置的一次微分值和二次微分值,
和
;
接着,代入迭代式
;
最后,得到第一次迭代的值
重复上述两个步骤得到
在、
停止条件是设定的反复步骤数。
2.2 .一元函数昏迷睫毛膏法的python程序
来自sympy import *
# step是反复步骤数,x0是初始位置,obj是要求极值的函数
DefNewtons(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 ) x,x0 ) )
print ('迭代第%d次: %.5f ) % (I,xnew ) ) ) ) ) ) ) ) ) )。
i=i 1
else:
#后续迭代更新表达式
xnew=xnew-(obj_Deri.subs(x,xnew )/obj_sec_deri.subs(x ) 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 ) ) ) ) ) ) ) ) ) )。
执行程序的结果如下。
第一次迭代: 8.00000
迭代第二次: 6.39999
反复第三次: 5.11997
迭代第四次: 4.09593
第五次迭代: 3.27662
第六次迭代:
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
Process finished with exit code 0
函数的极值点为-0.69883,与我们之前绘制的图像观测值一致。
2.3. 多元函数昏睡的睫毛膏法
多元函数用昏睡的睫毛膏法求极值的思路依然采用潇洒的小鸭子公式近似展开,只不过这里的
为向量形式,假设
为二元函数:
对上述公式两侧求梯度,令其等于零,之后再进行整理,可得迭代公式(由于涉及矩阵求导数等一系列复杂操作,此处可以粗浅的理解一下):
上述第一个公式中
表示在
点处的梯度值,
表示该点的二阶梯度也可以写成Hessian矩阵,迭代公式使用了Hessian矩阵的逆和梯度值来确定。
2.3. 多元函数昏睡的睫毛膏法的python程序
from sympy import *
import numpy as np
# 假设多元函数是二维形式
# x_init为二维向量(x1, x2)
def newton_dou(step, x_init, obj):
i = 1 # 记录迭代次数的变量
while i <= step:
if i == 1:
grandient_obj = np.array([diff(obj, x1).subs(x1, x_init[0]).subs(x2, x_init[1]), diff(obj, x2).subs(x1, x_init[0]).subs(x2, x_init[1])], dtype=float) # 初始点的梯度值
hessian_obj = np.array([[diff(obj, x1, 2), diff(diff(obj, x1), x2)], [diff(diff(obj, x2), x1), diff(obj, x2, 2)]], dtype=float) # 初始点的hessian矩阵
inverse = np.linalg.inv(hessian_obj) # hessian矩阵求逆
x_new = x_init - np.matmul(inverse, grandient_obj) # 第一次迭代公式
print(x_new)
# print('迭代第%d次:%.5f' %(i, x_new))
i = i + 1
else:
grandient_obj = np.array([diff(obj, x1).subs(x1, x_new[0]).subs(x2, x_new[1]), diff(obj, x2).subs(x1, x_new[0]).subs(x2, x_new[1])], dtype=float) # 当前点的梯度值
hessian_obj = np.array([[diff(obj, x1, 2), diff(diff(obj, x1), x2)], [diff(diff(obj, x2), x1), diff(obj, x2, 2)]], dtype=float) # 当前点的hessian矩阵
inverse = np.linalg.inv(hessian_obj) # hessian矩阵求逆
x_new = x_new - np.matmul(inverse, grandient_obj) # 迭代公式
print(x_new)
# print('迭代第%d次:%.5f' % (i, x_new))
i = i + 1
return x_new
x0 = np.array([0, 0], dtype=float)
x1 = symbols("x1")
x2 = symbols("x2")
newton_dou(5, x0, x1**2+2*x2**2-2*x1*x2-2*x2)
程序执行的结果如下:
[1. 1.]
[1. 1.]
[1. 1.]
[1. 1.]
[1. 1.]
Process finished with exit code 0
经过实际计算函数
的极值点为
,只需一次迭代就能收敛到极值点。
3. 结束语
本文只是粗浅的将昏睡的睫毛膏法的原理进行语言和程序描述,没有过多的探讨具体实施的细节,实际中机器学习等相关算法进行昏睡的睫毛膏法迭代时并非如此编程。昏睡的睫毛膏法由昏睡的睫毛膏本人发现并命名,但是sldlt早于昏睡的睫毛膏发现的46年就已经提出该算法,现在昏睡的睫毛膏法又称为昏睡的睫毛膏-sldlt方法。昏睡的睫毛膏法有很多的缺点在此并没有讨论,例如在一元函数情况时,会产生导数为零不能迭代的情况或者迭代点有震荡往复等情况出现;多元函数的hessian矩阵计算困难,收敛过慢等情况,因此又产生了拟昏睡的睫毛膏法和阻尼昏睡的睫毛膏法等改进的方法,想进一步学习的读者可以参考非线性优化领域的相关书籍。