[数值计算-10]:一元非线性函数求最小值 - 梯度下降法&Python法代码示例
Posted 文火冰糖的硅基工坊
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[数值计算-10]:一元非线性函数求最小值 - 梯度下降法&Python法代码示例相关的知识,希望对你有一定的参考价值。
作者主页(文火冰糖的硅基工坊):https://blog.csdn.net/HiWangWenBing
本文网址:https://blog.csdn.net/HiWangWenBing/article/details/119832688
目录
8.3 梯度下降法使用-学习率=0.5:一次性收敛,梯度为0
第1章 一元非线性函数
1.1 什么是函数的元
所谓元,就是函数未知数,未知数的个数,就是函数的元数。
一元函数,就是未知数只有一个,即g=f(x)
二元函数,就是未知数有两个,即g=f(x,y)
1.2 什么是非线性函数
线性函数是一次函数的别称,则非线性函数即函数图像不是一条直线的函数。
非线性函数包括指数函数、幂函数、对数函数、多项式函数等等基本初等函数以及他们组成的复合函数
1.3 非线性函数案例
y = f(x) = a3*x^3 + a1*x^1 + a0
另a3 = 1, a2=-1, a0=-1;得到:
y = f(x) = x^3 - x - 1
1.4 非线性函数的几何图形示意图
第2章 函数的导数
2.1 什么是函数的导数
导数也称为微分!!!
2.2 导数的几何意义
(1)瞬时速度
(2)切线与斜率
2.3 导函数
以x为自变量,以函数f(x)在x处的导数值为因变量y,而构成的函数为x的导函数,记成f'(x)。
实际上,大多数初等函数,都可以通过原函数f(x)直接获取f(x)的导函数。
有了导函数f'(x),就可以直接求y=f(x)在任意点处的导数。
2.4 函数的凹凸性:什么是凸函数和凹函数?
凸函数分为上凸和下凸,下凸又成为凹,因此,凸函数和凹函数,统称为凸函数。
(1)凹凸性的几何意义
简单的说:
上凸:在一个区间内,函数曲线上的点都在函数上任意两点的连线(直线)的上方。
下凸:在一个区间内,函数曲线上的点都在函数上任意两点的连线(直线)的下方。
(2)凹凸性的导数意义
第3章 极大与最值
3.1 什么是函数的最小值、极小值?
最值,是函数的定义域内的最高点和最低点。函数最值分为函数最小值与函数最大值。
简单来说,最小值即定义域中函数值的最小值,最大值即定义域中函数值的最大值。
函数最大(小)值的几何意义:函数图像的最高(低)点的纵坐标即为该函数的最大(小)值。
函数极值:是一定范围内(给定区间)内取得的最大值或最小值,分别称为极大值或极小值,极值也称为相对极值或局部极值。
3.2 求极值的重要意义
在科学计算中,为了通过调整参数,使得误差最小,因此需要求函数的最小值,以确保模型的精确性。特别是人工智能深度学习中,得到了广泛的应用。
通过不断调整参数,使得误差最小,就是深度学习的过程。
3.3 函数的单调性
函数的单调性(monotonicity)也可以叫做函数的增减性。
当函数 f(x) 的自变量在其定义区间内增大(或减小)时,函数值f(x)也随着增大(或减小),则称该函数为在该区间上具有单调性。
(1)函数单调性的几何特征:
在单调区间上,增函数的图象是上升的,减函数的图象是下降的
单调函数的是没有极值的,区间的两个端点就是最值。
3.4 什么样的函数有极小值和最小值?
(1)极限法描述
(2)导数法描述
y=f(x0)导数k=0:表示函数在x0的函数值y=f(x0)没有变化. y2 = y1
y=f(x0)导数k<0:表示函数向更小值的值方向发展,y2<y1,即k= (y2-y1)/(x2-x1),
y=f(x0)导数k>0:表示函数向更大值的值方向发展,y2>y1,即k= (y2-y1)/(x2-x1),
因此:
极大值(高点):
y=f(x)在x0左导数k>0(y增长),y=f(x)在x0导数k=0(y值不变),y=f(x)在x0由右导数k<0(y值下降)。
极小值(低点):
y=f(x)在x0左导数k>0(y下降),y=f(x)在x0导数k=0(y值不变),y=f(x)在x0由右导数k<0(y值增长)。
上升鞍点(震荡):
下降鞍点(震荡):
3.5 牛顿迭代法能求函数的最小值吗?
越靠近极值点的导数,越接近0,因此其直线方程越是与轴平行,与 X轴的交点越远离极值的。
因此,牛顿迭代法不适合求函数的极值点。
3.6 如何求函数的最小值?
以y= f(x) = x^2 + 2x + 2为例。
(1)解析法:直接公式法
x0 = -b/2a = -2/2 = -1.
最小值:f(-1)=1 -2 + 2 = 1
最小值:fmin = (4ac - b^2)/4a = (4*1*2 - 4)/4 = 1
(2)解析法:导数公式法
f'(x) = 2x + 2 = 0 => 导数为0处,是极值点 => x = -1
f''(x) = 2 > 0 => 二阶导数恒0, 因此最小值存在。
f(-1) = 1 -2 + 2 = 1 => 最值点位 1.
(3)迭代法:梯度下降法
求函数的极小值点与最小值点有很多方法,比较简单、常用的方法就是梯度下降法。
第4章 梯度下降法求函数最小值的原理
4.1 什么是物理意义上的梯度
梯:阶梯,台阶和梯子,是只一步步达到目标的途径。
梯度:相邻两个梯的高度,称为梯度。
下降:(1)在由原点到目的点的距离是逐渐下降的,(2)在由原点到目的点的过程中,每格梯的高度是下降的,越接近原点,其梯度越大,步伐越大。越接近目的点,其梯度越小,步伐越小。
4.2 什么数学意义上的梯度
梯度的本意是一个向量(矢量)方向,表示某一函数在该点处的方向导数,沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度的方向)变化最快,变化率最大(为该梯度的模)。
在空间曲线中,有所有方向的切线(斜率)组成的一个向量,称为梯度。
在一元平面曲线中,任意一点的切线,就称为梯度,切线的斜率值,就是梯度的模。
4.3 为什么叫梯度下降法
(1)梯度:
- 各个方向导数组成的向量的方向。
- 通过一步步迭代(即爬梯子)的方式一步步逼近目的地。
(2)下降:
- 由于梯度的方向是上升,因此这里采用的是导数反方向。
- 函数值由高点逐渐逼近最低点(不是零值)
- 在逼近的过程中,导数(梯度)也跟着逐渐变低,趋于为0(导数为0的地方,就是最小值)
第5章 梯度下降法求一元n次函数的极小值。
5.1 函数模型
5.2 迭代过程
上述迭代,每次迭代的步长与该点的导数强相干。当导数为0时,Xk就无法迭代了,这就是梯度消失。
学习率:调节导数对迭代步长的影响,学习率可以是固定值,也可以是动态变化。
特别注意:
迭代方向是梯度的反方法,这是因为梯度的方向是向上的方向,找最大值的方向,而这里是找最小值(极小值),因此方向是梯度的反方向。
5.3 学习率对迭代过程的影响
5.4 迭代退出的条件可选项
迭代的退出规则的选择是梯度下降法的一个难点之一,它与迭代算法和函数本身都是强关联的。
(1)五星*****: 迭代次数:
- 规则:
梯度下降法有可能反复震荡,无限制的迭代下去,因此可以通过限制迭代次数,可以防止永不收敛。
- 风险:
无法预知应该迭代多少次,迭代次数与初值有很大的相干性。
(2)三星***: 梯度的值(导数)接近于0
- 规则
梯度小于某一个极小值,这条规则可用的依据是,极小值点处的梯度为0,即导数为0。
- 风险
导数为零是必要条件,不是充要条件,以这条规则为收敛条件,有可能找到的是“鞍点” 而不是极值点。
(3)一星*: 相邻梯度的变化(二阶导数)接近于0
- 规则
梯度变化小于某一个极小值。
- 风险
这个规则谨慎使用,因为梯度不变化,不代表梯度不下降了。
如:线性下降,下降率是恒定值,因此相邻迭代点的梯度差为0,但此时还是继续下降的。
(4)三星***:x值的变化接近于0
- 规则
当x的变化很小时,表明已经接近导数为0的地方。
- 风险
这种判断规则的风险是:梯度消失现象,错把鞍点的值当成极值。
由于x的迭代值取决于梯度,当在鞍点处的梯度为0时,x的变化也是0。
(5)五星***:y值的变化接近于0
- 规则:
当y的变化很小时,表明已经接近导数为0的地方。
- 风险
如果步长比较大,在xk+1和fxk跨越xr时,可能会导致f(xk+1)和(fxk)的值接近,如下图f(x3)和f(x4)的值相乘接近于0,但很显然,无论是x3还是x4,都离真实的xr很远。
5.6 迭代退出的综合条件
从上所述,单一的退出条件都有各种的风险和问题。
因此,需要一种综合的规则,确保规避上述各自的风险。
5.7 迭代的误差
很显然,并不像就方程的根一样,f(xr)并不落在f(xk+1)和f(xk)之间。
因此无法直接求出y的误差。
但是,可以先求出f(xk+1)和f(xk)之间的误差,然后用中值公式 作为f(xr)的近似值。
第6章 多元函数的极小值
6.1 梯度下降法求二元n次函数的极小值
待续。。。。。
6.2 梯度下降法求多元N函数的极小值。
待续。。。。。
第7章 一元函数的极小值的代码案例
7.1 前置条件
#导入库
from math import *
import time
import numpy as np
import matplotlib.pyplot as plt
7.2 函数的定义
# 一元N次非线性函数
# y=f(x) = x^2 +2 x + 2
def f(x):
return(1.0*x**2 + 2.0*x + 2)
# 一阶导函数:y=fv1(x) =2x + 2
def fv1(x):
return(2.0*x + 2.0) #导函数
# 一阶导函数:y=fv2(x) =2
def fv2(x):
return(2.0) #导函数
# 一元二次函数的最小值公式
def fmin(a,b,c):
return ((4*a*c - b**2)/(4*a))
# 一元二次函数的最小值处的x值公式
def fmin_x(a,b,c):
return ((-b)/(2*a))
7.3 函数的可视化
# 原函数可视化
x_data = np.arange(-3,2,0.25)
y_data = []
print(x_data)
for x in x_data:
y_data.append(f(x)) #解析法依次求解
plt.scatter(x_data, y_data)
[-3. -2.75 -2.5 -2.25 -2. -1.75 -1.5 -1.25 -1. -0.75 -0.5 -0.25
0. 0.25 0.5 0.75 1. 1.25 1.5 1.75]
# 一阶导函数可视化
x_data = np.arange(-3,2,0.25)
y_data = []
print(x_data)
for x in x_data:
y_data.append(fv1(x)) #解析法依次求解
plt.scatter(x_data, y_data)
[-3. -2.75 -2.5 -2.25 -2. -1.75 -1.5 -1.25 -1. -0.75 -0.5 -0.25
0. 0.25 0.5 0.75 1. 1.25 1.5 1.75]
# 二阶导函数
x_data = np.arange(-3,2,0.25)
y_data = []
print(x_data)
for x in x_data:
y_data.append(fv2(x)) #解析法依次求解
plt.scatter(x_data, y_data)
[-3. -2.75 -2.5 -2.25 -2. -1.75 -1.5 -1.25 -1. -0.75 -0.5 -0.25 0. 0.25 0.5 0.75 1. 1.25 1.5 1.75]
7.3 公式法求极值
# 公式法求函数最小值
print("极值点处的x值:",fmin_x(1,2,2))
print("极值点处的y值:",fmin(1,2,2))
极值点处的x值: -1.0
极值点处的y值: 1.0
第8章 梯度下降法求极值
8.1 梯度下降法算法定义
# 梯度下降法求最小值的算法
def fmin_gradient_descent(f,fv1, a,b,c,init_x0, learning_rate, max_loop,show_flag=0):
x_data = []
y_data = []
z_data = []
x_k = init_x0
x_k1 = init_x0
for k in range(max_loop):
#计算梯度
step = learning_rate * fv1(x_k)
# 保存当前的迭代点
x_data.append(x_k1)
y_data.append(f(x_k1))
z_data.append(step)
x_k1 = x_k - step
# 为新一轮迭代做准备
x_k = x_k1
if (show_flag != 0):
plt.scatter(x_data, y_data)
plt.scatter(x_data, z_data)
return (x_k,f(x_k1))
8.2 梯度下降法使用-学习率=0.1:小碎步快速跑
# 梯度下降法算法的使用
a = 1
b = 2
c = 2
x0 = 2
learning_rate = 0.1
max_loop = 100
show_flag = 1
result = fmin_gradient_descent(f,fv1, a,b,c,x0, learning_rate, max_loop,show_flag)
print(result)
# 本案例中
# 学习率=0.1,学习率较小,通过小步碎跑的方式逐步收敛域目标点。
输出:
(-0.9999999993888892, 1.0)
蓝色曲线:x值迭代曲线,从右往左,x值从2逐步单调收敛-1,y=f(x)逐步单调收敛收敛于1.
橙色曲线:迭代步长曲线,从右往左,step值从2.0逐步单调收敛于0。
8.3 梯度下降法使用-学习率=0.5:一次性收敛,梯度为0
# 梯度下降法算法的使用
a = 1
b = 2
c = 2
x0 = 2
learning_rate = 0.5
max_loop = 100
show_flag = 1
result = fmin_gradient_descent(f,fv1, a,b,c,x0, learning_rate, max_loop,show_flag)
print(result)
# 在本案例中:
# 学习率等于0.5时,为最佳迭代,无论Xk在哪里,都能够只需要一步迭代,就能够到目标点。
# 然后目标点的导数为0,后续的迭代步长为0,因为这里不可能是鞍点。
# 这就是导数(切线)的神奇之处,不同点,其导数不同值不同,不同点的迭代步长不同
# 但都能够保证,一次能够找到目标最小值点(后续的导数为0)
输出:
(-1.0, 1.0)
蓝色曲线:x值迭代曲线,从右往左,x值从2一步收敛-1,y=f(x)一步收敛收敛于1.
橙色曲线:迭代步长曲线,从右往左,step值从2.0一步收敛于0。
8.4 梯度下降法使用-学习率=0.9:步伐过大,震荡收敛
# 梯度下降法算法的使用
a = 1
b = 2
c = 2
x0 = 2
learning_rate = 0.9
max_loop = 50
show_flag = 1
result = fmin_gradient_descent(f,fv1, a,b,c,x0, learning_rate, max_loop,show_flag)
print(result)
# 本案例中
# 学习率=0.9,学习率较大,通过震荡的方式逐渐收敛到目标点。
输出:
(-0.9999571825692188, 1.0000000018333324)
蓝色曲线:x值迭代曲线,从右往左,x值从2震荡收敛-1,y=f(x)逐步单调收敛收敛于1。
橙色曲线:迭代步长曲线,从右往左,step值从2.0逐步单调收敛于0。
因此,震荡收敛,是x值震荡,而不是y=f(x)震荡,是y=f(x)和步长都是单调收敛的。
作者主页(文火冰糖的硅基工坊):https://blog.csdn.net/HiWangWenBing
本文网址:https://blog.csdn.net/HiWangWenBing/article/details/119832688
以上是关于[数值计算-10]:一元非线性函数求最小值 - 梯度下降法&Python法代码示例的主要内容,如果未能解决你的问题,请参考以下文章
[数值计算-16]:最小二乘法求的解法1 - 一元2次方程解析法求解
[数值计算-11]:多元函数求最小值 - 偏导数与梯度下降法&Python法代码示例
[数值计算-6]:一元n次非线性方程求解-双点区间-二分迭代法&Python法代码示例