当前位置: 首页 > news >正文

【机器学习】梯度下降法及使用一元二次方程模拟使用梯度下降法的代码实现

梯度下降法

  • 一、摘要
  • 二、梯度下降法
  • 三、线性方程中使用梯度下降法

一、摘要

文本主要讲述了梯度下降法作为机器学习中的一种优化方法用于最小化损失函数。它并非直接解决机器学习问题,而是作为求解最优参数的工具。通过二维坐标图直观展示了梯度下降法的原理,即通过调整参数值来逐步减小损失函数值,直至找到最小值点。同时,强调了导数在梯度下降中的作用,即指示了损失函数随参数变化的趋势,从而指导参数调整的方向。

二、梯度下降法

  1. 概述

    1.梯度下降法是机器学习领域的一种重要方法,用于优化目标函数。
    2.梯度下降法用于最小化损失函数,而梯度上升法用于最大化效用函数
    3.梯度下降法是解决许多机器学习问题的常用工具,尤其是那些无法直接求解数学解的问题。

  2. 原理

    1.梯度下降法通过在损失函数上搜索最优解来最小化损失函数
    2.在二维坐标平面上,损失函数的最小值对应于参数θ的某个值
    3.通过计算损失函数对参数θ的导数,确定损失函数增大的方向,并沿其负方向移动。
    4.移动的步长称为学习率α,其取值影响算法收敛的速度。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    图中内容是关于机器学习中“学习率(η)”的知识点介绍:
    1. 学习率(η)是在机器学习优化算法,尤其是梯度下降法中的一个超参数。
    2. 它控制着每次参数更新的步长。如果学习率取值较小,算法会更谨慎地更新参数,虽然能保证算法的稳定性,但会使得收敛到最优解的速度变慢,需要更多的训练时间和计算资源。
    3. 而如果学习率取值过大,参数更新的步长就会很大,这可能导致算法在搜索最优解的过程中“跳过”最优解,无法收敛,甚至出现发散的情况,也就得不到最优解。
    4. 并不是所有函数都有唯一的极值点
    在这里插入图片描述
    解决办法
    1. 多次运行,随机化初始点
    2. 梯度下降法的初始点也是一个超参数

  3. 示例

    1.通过示例说明梯度下降法的具体步骤,包括计算导数确定移动方向步长
    2.梯度下降法的过程类似于球体在山谷中的滚落过程,直到到达谷底
    3.学习率α取值过大或过小都会影响算法的性能,甚至导致无法找到最优解。

  4. 注意事项

    1.梯度下降法可能陷入局部最优解,尤其是面对复杂函数时。
    2.初始点的选择对梯度下降法的结果有重要影响,不同的初始点可能导致不同的最优解。
    3.对于具有多个局部最优解的函数,多次运行梯度下降法并比较结果可以有助于找到更好的解。

三、线性方程中使用梯度下降法

  1. 线性回归中使用梯度下降法目标:使 ∑ i = 1 m ( y ( i ) − y ^ ( i ) ) 2 \sum_{i = 1}^{m}(y^{(i)} - \hat{y}^{(i)})^{2} i=1m(y(i)y^(i))2损失函数值尽可能小。
  2. 线性回归法的损失函数具有唯一最优解
  3. 代码实现:
    • 导入相关依赖包并定义好损失函数方程且绘制出其图像:

      import numpy as np
      import matplotlib.pyplot as  plt
      # 定义损失函数中的x:取值[-1,6],样本数:141
      plot_x = np.linspace(-1,6,141)
      # 定义损失函数中的y:二元一次方程y=(x - 2.5)**2 -1,其中2.5是自定义的,可取任意一个数
      plot_y = (plot_x - 2.5)**2 -1 
      # 绘制当前损失函数在二维平面上的图像
      plt.plot(plot_x,plot_y)
      plt.show()
      

      执行结果:
      在这里插入图片描述

    • 定义求损失函数的导函数和求损失函数值:

      # 定义求导函数:得到梯度gradient值
      def dJ(theta):
          return 2*(theta - 2.5)
      # 定义J对于theta的损失函数
      def J(theta):
          try:
              return (theta-2.5)**2 - 1.
          except:
              return float('inf') # 返回float最大值
      
    • 定义求损失函数最小值函数:

      # 定义求损失函数最小值函数
      # p_eta: 学习率,控制每次参数更新的步长,默认值为0.1
      # p_epsilon: 收敛阈值,当两次迭代的损失函数差值小于该值时,认为算法收敛,默认值为1e-8
      # p_theta: 参数的初始值,默认值为0.0
      # n_iters:用于控制循环的参数,当无法找到最优解时,就终止,默认为1e4(10的4次方)
      def minJ(p_eta=0.1,p_epsilon=1e-8,n_iters=1e4,p_theta=0.0):
          # 定义局部变量,将传入的参数赋值给新的变量,方便后续操作
          eta = p_eta
          epsilon = p_epsilon
          theta = p_theta
          i_itera = 0
          
          while i_itera < n_iters:
              # 根据传入的theta计算出梯度,这里假设dJ函数已经定义好,用于计算梯度
              gradient = dJ(theta)
              # 将上一次的theta赋值给一个变量,用于存储上一次theta的值,以便后续比较损失函数的变化
              last_theta = theta
              # 重新计算当前的theta值,根据梯度下降的公式,让theta向梯度负方向前进一步
              theta = theta - eta * gradient
      
              # 计算上一次和当前的损失函数的差值的绝对值是否小于Epsilon
              # 如果小于,则说明已经接近损失函数的最小值,认为算法收敛,退出循环
              if(abs(J(theta) - J(last_theta)) < epsilon):
                  break
              i_itera += 1
              
          return theta, J(theta)
      

      执行结果:
      在这里插入图片描述

    • 定义一个测试函数minJViewThetaChange,用于可视化损失函数的中theta沿着梯度负方向前进的二维平面图上的轨迹:

      # 定义一个测试函数,用于可视化损失函数的中theta沿着梯度负方向前进的二维平面图上的轨迹
      # p_eta: 学习率,控制每次参数更新的步长,默认值为0.1
      # p_epsilon: 收敛阈值,当两次迭代的损失函数差值小于该值时,认为算法收敛,默认值为1e-8
      # p_theta: 参数的初始值,默认值为0.0
      # n_iters:用于控制循环的参数,当无法找到最优解时,就终止,默认为1e4(10的4次方)
      def minJViewThetaChange(p_eta=0.1,p_epsilon=1e-8,n_iters=1e4,p_theta=0.0,p_plot=plt):
          # 定义局部变量,将传入的参数赋值给新的变量,方便后续操作
          eta = p_eta
          epsilon = p_epsilon
          theta = p_theta
          # 定义用于存储theta每次计算得到的值,用于绘制图片
          theta_history = [theta]
          # 迭代次数
          i_itera = 0
          
          while i_itera < n_iters:
              # 根据传入的theta计算出梯度,这里假设dJ函数已经定义好,用于计算梯度
              gradient = dJ(theta)
              # 将上一次的theta赋值给一个变量,用于存储上一次theta的值,以便后续比较损失函数的变化
              last_theta = theta
              # 重新计算当前的theta值,根据梯度下降的公式,让theta向梯度负方向前进一步
              theta = theta - eta * gradient
              # 将每次计算得到的theta值放入theta_history历史数组当中
              theta_history.append(theta)
      
              # 计算上一次和当前的损失函数的差值的绝对值是否小于Epsilon
              # 如果小于,则说明已经接近损失函数的最小值,认为算法收敛,退出循环
              if(abs(J(theta) - J(last_theta)) < epsilon):
                  break
              i_itera += 1
          print("theta=",theta)
          print("J(theta)=",J(theta))
          print("theta_history前100个:",theta_history[:100])
          print("theta_history总长度:",len(theta_history))
          # 绘制x,y值,即绘制损失函数曲线图
          p_plot.plot(plot_x,J(plot_x))
          # 绘制每个theta沿着gradient负方向前进时的曲线
          p_plot.plot(np.array(theta_history),J(np.array(theta_history)),color='r',marker='+')
          # 将曲线显示出来
          p_plot.show()
      

      执行结果:
      在这里插入图片描述

    • 测试1:给定一个比较小的eta值(0.01),看看学习率的变化轨迹
      在这里插入图片描述

    • 测试2:给定一个更小的eta值(0.001),看看学习率的变化轨迹
      在这里插入图片描述

    • 测试3:给定一个比较大的eta值(0.8),看看学习率的变化轨迹
      在这里插入图片描述

    • 测试4:给定一个更大的eta值,看看学习率的变化轨迹
      在这里插入图片描述
      此时,如果调用minJ函数,得到的theta和损失函数的值都是nan
      在这里插入图片描述
      到此,我们可以看出来,学习率eta不能大小,也不能太大,否则将无法使得损失函数收敛。

相关文章:

  • 45.matlab产生正弦叠加信号
  • 系统运维方案,系统运维的主要工作内容和运维检查单等资料,设备监控,设备运维检查(Word)
  • Redis 中有序集合(Sorted Set)的使用方法
  • java进阶学习IO流
  • 大厂都在用的前端换肤方案:多品牌适配 + 夜间模式全解析
  • Vue 3 零基础入门:从计数器应用开始你的工程化之旅 - 深入理解 Vue 3 响应式系统
  • 详解 torch.triu:上三角矩阵的高效构造(中英双语)
  • Linux 之 Centos 安装Consul
  • maven Problem shading JAR的几个解决方案
  • java进阶学习脑图
  • deepseek_v3_base和deepseek_r1_zero和deepseek_r1
  • 【深入浅出:Core-JS Legacy 的降级兼容指南】
  • Filter-入门
  • uni-app 登录成功后自动跳转至登录前页面(H5\微信小程序)
  • 实战篇-java8中的垃圾回收器
  • python绑定udp时使用127.0.0.1作为ip,无法sendto,报错Invalid argument
  • Android 键盘输入按确认或换行 直接触发提交
  • 了解 PoE 扩展模式(Extend Mode)及其对数据速率的影响
  • python爬虫系列课程4:一个例子学会使用xpath语法
  • RK3399 Android7双WiFi功能实现
  • 网站架构设计师求职信/产品软文案例
  • 成都网站建设公司有哪几家/南京seo公司哪家
  • 做网站应达到什么效果/国外网站设计
  • 多个wordpress管理/北京seo优化哪家公司好
  • 网站子目录/今天热点新闻事件
  • 网站收录后才可以做排名吗/企业seo关键字优化