用python实现梯度下降算法

本文主要使用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()

de38a7f3a79642ab8d46a20847678245.jpg

 

好了,到此代码部分介绍完毕


下面是完整代码

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()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值