5.5 梯度下降番外:非常有用的调试方式及总结学习笔记

梯度下降法的使用,一个非常重要的步骤是:我们要求出定义的损失函数某一点上对应的梯度是什么。在复杂函数的情况下,求导得到梯度并不容易。如果我们梯度的计算错误了,在后续的程序中也不会报错。那么我们如何去发现这个错误呢?

介绍一种简单的方法,能够对梯度下降法中求梯度的公式推导进行调试。

下面我们在一组数据上,分别使用数学公式法和调试法来计算梯度,主要观察其结果与所消耗的时间。


# 首先定义损失函数
def J(theta, X_b, y):
    try:
        return np.sum((y - X_b.dot(theta))**2) / len(X_b)
    except:
        return float('inf')

# 使用数学公式推导的方式,求损失函数J在参数theta上的梯度
def dJ_math(theta, X_b, y):
    return X_b.T.dot(X_b.dot(theta) - y) * 2. / len(y)

# 使用上文提到的梯度调试的方法
def dJ_debug(theta, X_b, y, epsilon=0.01):
    # 先创建一个与参数组等长的向量
    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

# 梯度下降的过程
def gradient_descent(dJ, X_b, y, initial_theta, eta, n_iters = 1e4, epsilon=1e-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

然后我们先调用 d J d e b u g dJ_debug dJdebug函数,看看正确的梯度结果是什么。

import numpy as np
X_b = np.hstack([np.ones((len(X), 1)), X])
initial_theta = np.zeros(X_b.shape[1])
eta = 0.01
%time theta = gradient_descent(dJ_debug, X_b, y, initial_theta, eta)
theta

然后我们再调用 d J m a t h dJ_math dJmath,来检验我们的求导公式对不对:

%time theta = gradient_descent(dJ_math, X_b, y, initial_theta, eta)
theta

最终发现,我们求得的梯度公式得到的答案是正确的。

但是观察到,使用debug的方式要比用求导公式的执行时间慢很多,如果在真实数据集上,可能会差的更多了。因此我们在求梯度的时候,可以用这种通用的debug方式先在小数据集上对求导公式进行检验。

对梯度下降法的总结

在之前的系列文章中,我们介绍了两种梯度下降法:

  • 批量梯度下降法 Batch Gradient Descent
  • 随机梯度下降法 Stochastic Gradient Descent
    批量梯度下降法每次对所有样本都看一遍,缺点是慢,缺点是稳定。随机梯度下降法每次随机看一个,优点是快,缺点是不稳定。

其实还有一种中和二者优缺点的方法小批量梯度下降法 MBGD(Mini-Batch Gradient Descent):在每次更新时用b个样本,其实批量的梯度下降就是一种折中的方法,用一些小样本来近似全部。优点:减少了计算的开销量,降低了随机性。

在机器学习领域,随机具有非常大的意义,因为计算速度很快。对于复杂的损失函数来说,随机可以跳出局部最优解,并且有更快的速度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值