欢迎光临
一起学习,一起进步

关于梯度的调试

一、梯度下降法的调试

 1)疑问 / 难点

  • 如何确定梯度下降法的准确性?
  • 损失函数的变量 theta 在某一点上对应的梯度是什么?
  • 在更负责的模型中,求解梯度更加不易;
  • 有时候,推导出公式后,并将其运用到程序中,但当程序运行时,有时对梯度的计算可能会出现错误,怎么才能发现这种错误?

 

 

 2)梯度下降法的调试思路

  • 调试思路
  1. 如果机器学习的算法涉及到求解梯度,先使调试方式求出梯度,提前得到此机器学习算法的正确结果;
  2. 数学推导方式(根据算法模型推导出的求解梯度的公式)求出梯度的数学解,将数学解带入机器学习算法中,得出结果;
  3. 对比两种最终得到的结果是否一致,如果一样,则此数学推导公式可用,如果不一样,则此数学推导公式待改进;

 

 

 3)公式的确定

  • 导数的推导过程
  • 公式:

 

  • 梯度的求解的思路,与导数类似
  • 最终推导出的调试的公式
  1. θ:损失函数的变量(theta)
  2. θ1+  =  θ + ε:表示 θ 右侧的点的变量;
  3. θ1  =  θ – ε:表示 θ 左侧的点的变量;
  4. θ1+  –  θ  ==  θ  –  θ1  ==  ε

 

  • 调试公式的特点:时间复杂度高,每求一次梯度都要花相当多的时间,因此一般此种求解梯度的方式只用于调试;

 

 4)代码实现

  • 数学模型推导方式求梯度
    复制代码
    import numpy as np
    import matplotlib.pyplot as plt
    
    np.random.seed(666)
    X = np.random.random(size=(1000, 10))
    true_theta = np.arange(1, 12, dtype=float)
    
    X_b = np.hstack([np.ones((len(X), 1)), X])
    y = X_b.dot(true_theta) + np.random.normal(size=1000)
    
    
    def J(theta, X_b, y):
        """求当前 theta 的损失函数"""
        try:
            return np.sum((y - X_b.dot(theta)) ** 2) / len(X_b)
        except:
            return float('inf')
    
    
    def dJ_math(theta, X_b, y):
        """使用模型推导公式求当前 theta 对应的梯度"""
        return X_b.T.dot(X_b.dot(theta) - y) * 2. / len(y)true_theta
    复制代码
  1. true_theta:有 11 个元素,因为包含截距;
  2. true_theta = np.arange(1, 12, dtype=float):是一个一位数组,并没有转置为向量;
  3. X_b.dot(true_theta) + np.random.normal(size = 1000):此时用 矩阵 . dot(一维数组) + 一维数组;

 

  • 调试方式求梯度:
    复制代码
    def dJ_debug(theta, X_b, y, epsilon=0.01):
        """使用调试方式求当前 theta 对应的梯度"""
        
        res = np.empty(len(theta))
        for i in range(len(theta)):
            theta_1 = theta.copy()
            theta_1[i] += epsilon
            theta_2 = theta.copy()
            theta_2[i] -= epsilon
            res[i] = (J(theta_1, X_b, y) - J(theta_2, X_b, y)) / (2*epsilon)
            
        return res
    复制代码
  1. res:当前 theta 对应的梯度;
  2. theta_1 = theta.copy():将 theta 向量复制给 theta_1;#  此处的 copy() 是序列的方法;
  3. 特点由于该求解过程与函数 J() 的内部实现无关,该过程适用于所有函数的梯度求解;

 

  • 批量梯度下降法优化
    复制代码
    def gradient_descent(dJ, X_b, y, initial_theta, eta, n_iters=10**4, epsilon=10**-8):
        
        theta = initial_theta
        cur_iter = 0
        
        while cur_iter < n_iters:
            gradient = dJ(theta,X_b, y)
            last_theta = theta
            theta = theta - eta * gradient
            if (abs(J(theta, X_b, y) - J(last_theta, X_b, y)) < epsilon):
                break
                
            cur_iter += 1
            
        return theta
    复制代码
  1. dJ:代表求梯度的函数,这里作为参数,可以传入不同方法求解梯度;

 

  • 初始化后得到结果(一):使用调试方式求解梯度
    复制代码
    initial_theta = np.zeros(X_b.shape[1])
    eta = 0.01
    
    %time theta = gradient_descent(dJ_debug, X_b, y, initial_theta, eta)
    theta
    # 输出:Wall time: 4.89 s
           array([ 1.1251597 ,  2.05312521,  2.91522497,  4.11895968,  5.05002117,
            5.90494046,  6.97383745,  8.00088367,  8.86213468,  9.98608331,
           10.90529198])
    复制代码
  1. initial_theta:theta 的初始化值,为一个向量,一般设置为全 0 向量;

 

  • 初始化后得到结果(二):使用模型推导的公式求解梯度
    复制代码
    %time theta = gradient_descent(dJ_math, X_b, y, initial_theta, eta)
    theta
    # 输出:Wall time: 652 ms
           array([ 1.1251597 ,  2.05312521,  2.91522497,  4.11895968,  5.05002117,
            5.90494046,  6.97383745,  8.00088367,  8.86213468,  9.98608331,
           10.90529198])
    复制代码

 

 

  • 两种结果对比:
  1. 调试公式求梯度,最终可以得到结果,但运行速度较慢;
  2. 通过(dJ_debug 函数)计算过程可以看出,这种调试方法对梯度的计算,适用于一切目标函数;

 

 

二、梯度下降法的其它思考

  • 注:计算中有看不懂的地方,要对照着公式的推导过程理解;

 1)梯度下降法类型类

  • 批量梯度下降法(Batch Gradient Descent)
  1. 每一次都对所有样本进行计算,求出梯度
  2. 缺点:运算速度较慢;
  3. 优点:稳定,按此梯度方向,损失函数一定减小最快;

 

  • 随机梯度下降法(Stochastic Gradient Descent)
  1. 每一次只对随机抽取的一个样本,求出其梯度,作为 theta 的优化方向;
  2. 优点:运算速度较快;
  3. 缺点:不稳定,每一次的优化方向是不确定的,甚至有可能像反方向优化;

 

  • 小批量梯度下降法(Mini-Batch Gradient Descent)
  1. 综合了批量梯度下降法和随机梯度下降法的优点,避免了它们的确定;
  2. 思路:每次计算优化的方向(梯度),即不是查看所有样本也不只看一个样本,而是每次抽取 k 个样本,把这 k 个样本的梯度作为优化方向;
  3. 优点(一):比批量梯度下降法运算量小,速度快;
  4. 优点(二):比随机梯度下降法更稳定,获取的优化方向更能偏向批量梯度下降法中的梯度方向;
  5. 缺点:增加了一个新的超参数 k ,每一批该去多少个样本?
  6. k 个样本的梯度求解:和批量梯度下降法的求解过程一样;

 

 2)随机的优点

  1. 跳出局部最优解:更能找到损失函数的整体最优解,而不像批量梯度下降法那样,每次选取初始值后,可能只优化得到一个局部最小值,而不是损失函数整体的最小值;
  2. 更快的运行速度
  3. 机器学习领域很多算法都要使用随机的特点:随机森林、随机搜索
  • 机器学习领域解决的本身就是在不确定的世界中的不确定的问题,它本身可能就没有一个固定的最优解,因此随机扮演了一个重要的角色;

 

 3)梯度下降法理解回顾

  1. 不是一个机器学习算法
  2. 是一种基于搜索的最优化方法
  3. 作用:最小化一个损失函数

 

  • 梯度上升法
  1. 作用:最大化一个效用函数
  2. 每次参数 theta 加上变化量;

 

赞(0) 打赏
未经允许不得转载:openSL » 关于梯度的调试

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏