1 声明
这是一篇关于梯度下降算法的个人学习笔记,非教程
2 目标函数
求函数
y
=
(
x
−
1
)
2
+
sin
(
x
)
+
1
y = (x-1)^2+\sin(x)+1
y=(x−1)2+sin(x)+1
的最小值
3 代码实现
运行环境:jutyper book
内核:python 3.9.11
%config InlineBackend.figure_format='svg'
import numpy as np
import sympy as sp
import matplotlib.pyplot as plt
# 目标函数
def f(x):
return (x-1)**2+1+np.sin(x)
x = sp.symbols('x')
y = (x-1)**2+1+sp.sin(x)
ttf = y.diff(x)
# 步长,步长太小则收敛过慢,步长太大则出现振荡
alpha = 0.5
# alpha = np.random.uniform(0,1)
# 随机选取一个初始值
x_bound = [0,2]
x_0 = np.random.uniform(x_bound[0], x_bound[1])
# 迭代50次
for i in range(50):
tf = ttf.subs({'x':x_0})
x_1 = x_0 - tf*alpha
x_0 = x_1
# 绘制图像
samples = 200
u = np.linspace(x_bound[0],x_bound[1],samples)
v = f(u)
# y_0 = y.subs({'x':x_0})
y_0 = f(float(x_0))
plt.plot(u,v,c='green')
plt.scatter(x_0,y_0,c='red')
plt.plot(u,[y_0]*samples,c='orange')
plt.show()
print('x_0 = {}\ny_0 = {}'.format(x_0,y_0))
4 运行结果
x
0
=
0.582437942769745
y
0
=
1.7244196258725681
x_0 = 0.582437942769745\\ y_0 = 1.7244196258725681
x0=0.582437942769745y0=1.7244196258725681
5 其他说明
-
该算法最关键的部分就是梯度下降公式:
x 1 = x 0 − α ∇ f x_1 = x_0 - \alpha \nabla f x1=x0−α∇f -
上述算法中的 x 1 x_1 x1 没有进行限制,当步长选取不恰当时,所得到的 x 1 x_1 x1 有可能超出取值范围 [ 0 , 2 ] [0,2] [0,2]
-
目前仅考虑了只有一个峰值的函数,对于多峰函数还需要研究
-
上述算法,为了求目标函数的导数,用 sympy 对目标函数又定义了一次,当目标函数变化时,就需要修改两处定义,该部分的简化是一个值得思考的问题
-
其他
# 以下用法错误,x_0 是一个Float对象,不是 float 数据类型(两者f的大小写不一样)
# y_0 = f(x_0)
# 正确用法
y_0 = f(float(x_0))