本文主要使用python实现梯度下降算法
我们这里主要根据导数的正负和大小来判断位移方向和步长
主要原理是:当导数(文中变量名为:zf)值为负值时,我们向右位移,步长为:导数的绝对值乘以学习率
abs(zf) * Lr
用这样的方法不断循环,当导数值小于0.1或等于零时结束循环。当然,您可以调的更小。
本文主要使用的第三方库有
- numpy
- math
- matplotlib
- sympy
- random
如果你还未安装
pip install numpy
pip install math
pip install matplotlib
pip install sympy
pip install random
首先导入我们需要的库
import numpy as np
import math
import matplotlib.pyplot as plt
import sympy as sp
from random import randint as ran
接下来,构建主要函数用于实现梯度下降
def Gdt(function, s, e, Lr):
x = sp.Symbol('x') # 创建符号变量 x
f = sp.sympify(function) # 将输入的函数转换为 SymPy 的表达式
f_der = sp.lambdify(x, sp.diff(f, x), 'numpy') # 将导数函数转换为数值计算函数
x_new = list(range(s, e+1))# 创建初始的 x 值列表
y_new = [f.subs(x, xi) for xi in x_new] # 计算函数在 x_new 值下的结果
while True:
zf_list=[]
for i in range(0, len(x_new)):
zf = f_der(x_new[i]) # 计算梯度值
zf_list.append(zf)
if zf > 0:
x_new[i] -= zf * Lr # 使用梯度进行更新
else:
x_new[i] += abs(zf * Lr) # 使用梯度进行更新
y_new = [f.subs(x, xi) for xi in x_new] # 更新函数在 x_new 值下的结果
bbn=0
for i in zf_list:
if i>0.1:
bbn+=1
else:
pass
if bbn==0:
break
return x_new#, y_new
让我们定义一个函数来测试功能
def f3(x):
return np.sin(x)
让我们在给定区内生成多个点同时进行梯度下降
在这里面使用一个点进行梯度下降有可能会遇到局域最优解,对于尽可能找到全局最优解,我们可以在更大的范围使用更多的点同时梯度下降,以此来达到尽可能找到全局最优解的目的
x = np.linspace(-22, 22, 100)
y = f3(x)
接下来是绘制图像
cc=Gdt('sin(x)',0,5,0.05)
y2=f3(cc)
# 绘制函数图像
plt.plot(x, y)
plt.scatter(cc,y2)
# 添加标题和坐标轴标签
plt.title("Function Plot")
plt.xlabel("x")
plt.ylabel("f(x)")
# 显示图像
plt.show()
好了,到此代码部分介绍完毕
下面是完整代码
import numpy as np
import math
import matplotlib.pyplot as plt
import tkinter
import sympy as sp
from random import randint as ran
def Gdt(function, s, e, Lr):
x = sp.Symbol('x') # 创建符号变量 x
f = sp.sympify(function) # 将输入的函数转换为 SymPy 的表达式
f_der = sp.lambdify(x, sp.diff(f, x), 'numpy') # 将导数函数转换为数值计算函数
x_new = list(range(s, e+1))# 创建初始的 x 值列表
y_new = [f.subs(x, xi) for xi in x_new] # 计算函数在 x_new 值下的结果
while True:
zf_list=[]
for i in range(0, len(x_new)):
zf = f_der(x_new[i]) # 计算梯度值
zf_list.append(zf)
if zf > 0:
x_new[i] -= zf * Lr # 使用梯度进行更新
else:
x_new[i] += abs(zf * Lr) # 使用梯度进行更新
y_new = [f.subs(x, xi) for xi in x_new] # 更新函数在 x_new 值下的结果
bbn=0
for i in zf_list:
if i>0.1:
bbn+=1
else:
pass
if bbn==0:
break
return x_new#, y_new
#print(Gdt('x**2', -2, 5, 0.0005))
# 定义函数
def f(x):
return 1/(1 + np.exp(-x))#
def f2(x):
return np.power(x,2)
def f3(x):
return np.sin(x)
# 生成 x 值的范围
x = np.linspace(-22, 22, 100) # 在-2到2之间生成100个等间距的值
# 计算对应的 y 值
y = f3(x)
cc=Gdt('sin(x)',0,5,0.05)
y2=f3(cc)
# 绘制函数图像
plt.plot(x, y)
plt.scatter(cc,y2)
# 添加标题和坐标轴标签
plt.title("Function Plot")
plt.xlabel("x")
plt.ylabel("f(x)")
# 显示图像
plt.show()