找回密码
 立即注册
查看: 227|回复: 0

梯度下降

[复制链接]
发表于 2022-8-6 11:04 | 显示全部楼层 |阅读模式
一、了解梯度下降优化算法
梯度下降优化算法作用用来对原始模型的损失函数进行优化,以便寻找到最优的参数,使得损失函数的值最小。
梯度下降优化算法理解:梯度指向误差值增加最快的方向,导数为0(梯度为0向量)的点,就是优化问题的解。
损失函数值迭代公式: (a_{k+1},b_{k+1})=(a_{k+1}-\eta\frac{\partial L}{\partial a},b_{k+1}-\eta\frac{\partial L}{\partial b})
关于参数 \eta :我们已经知道,梯度对应的是下山的方向,而参数 \eta 对应的是步伐的长度。在学术上,我们称之为“学习率”(learning rate),是模型训练时的一个很重要的超参数,能直接影响算法的正确性和效率

  • 首先,学习率 \eta 不能太大。因此从数学角度上来说,一阶泰勒公式只是一个近似的公式,只有在学习率很小,也就是 \Delta a,\Delta b 很小时才成立。并且从直观上来说,如果学习率 \eta 太大,那么有可能会“迈过”最低点,从而发生“摇摆”的现象(不收敛),无法得到最低点
  • 其次,学习率 \eta 又不能太小。如果太小,会导致每次迭代时,参数几乎不变化,收敛学习速度变慢,使得算法的效率降低,需要很长时间才能达到最低点。
梯度算法缺点:在很多复杂函数中有很多极小值点,我们使用梯度下降法只能得到局部最优解,而不能得到全局最优解,对于梯度下降来说,初始点的位置,也是一个超参数。
解决方案:首先随机产生多个初始参数集,即多组;然后分别对每个初始参数集使用梯度下降法,直到函数值收敛于某个值;最后从这些值中找出最小值,这个找到的最小值被当作函数的最小值。当然这种方式不一定能找到全局最优解,但是起码能找到较好的。
二、手动实现梯度算法
python中有两种常见求导的方法,一种是使用Scipy库中的derivative方法,另一种就Sympy库中的diff方法。
三、线性回归中的梯度下降
最终得到梯度结果为: ▽J(\theta)=\frac{2}{m}X_{b}^{T}(x_{b}\theta-y)
代码演示
def fit_gd(self, X_train, y_train, eta=0.01, n_iters=1e4):
    """根据训练数据集X_train, y_train, 使用梯度下降法训练Linear Regression模型"""
    assert X_train.shape[0] == y_train.shape[0], \
        "the size of X_train must be equal to the size of y_train"

    def J(theta, X_b, y):
        try:
            return np.sum((y - X_b.dot(theta)) ** 2) / len(y)
        except:
            return float('inf')
        
    def dJ(theta, X_b, y):
        return X_b.T.dot(X_b.dot(theta) - y) * 2. / len(y)

    def gradient_descent(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

    X_b = np.hstack([np.ones((len(X_train), 1)), X_train])
    initial_theta = np.zeros(X_b.shape[1])
    self._theta = gradient_descent(X_b, y_train, initial_theta, eta, n_iters)

    self.intercept_ = self._theta[0]
    self.coef_ = self._theta[1:]

    return self在本篇文章中,对多元线性回归的损失函数进行求导,其结果是 \frac{2}{m}(X_{b}\theta-y)^{T}X_{b}
然后使用向量化的方式编写代码,但是发现在真实数据中效果比较差,这是因为数据的规模不一样,因此在梯度下降之前需要使用归一化。
数据归一化:
from sklearn.preprocessing import StandardScaler

standardScaler = StandardScaler()
standardScaler.fit(X_train)
X_train_std = standardScaler.transform(X_train)
lin_reg3 = LinearRegression()
lin_reg3.fit_gd(X_train_std, y_train)
X_test_std = standardScaler.transform(X_test)
lin_reg2.score(X_test, y_test)四、随机梯度下降法SGD
批量梯度下降法,每一次计算过程,都要将样本中所有信息进行批量计算。但是显然如果样本量很大的话,计算梯度就比较耗时。基于这个问题,改进的方案就是随机梯度下降法。即每次迭代随机选取一个样本来对参数进行更新。使得训练速度加快。
对损失函数的进行求导,得到的结果为: 2(X_{b}^{(i)})^{T}(X_{b}^{(i)}-y^{(i)})
批量梯度下降法BGD(Batch Gradient Descent)。

  • 优点:全局最优解;易于并行实现;
  • 缺点:当样本数据很多时,计算量开销大,计算速度慢。
针对于上述缺点,其实有一种更好的方法:随机梯度下降法SGD(stochastic gradient descent),随机梯度下降是每次迭代使用一个样本来对参数进行更新。

  • 优点:计算速度快;
  • 缺点:收敛性能不好
五、总结
批量梯度下降法BGD(Batch Gradient Descent)。

  • 优点:全局最优解;易于并行实现;
  • 缺点:当样本数据很多时,计算量开销大,计算速度慢。
针对于上述缺点,其实有一种更好的方法:随机梯度下降法SGD(stochastic gradient descent),随机梯度下降是每次迭代使用一个样本来对参数进行更新。

  • 优点:计算速度快;
  • 缺点:收敛性能不好
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-6-16 14:59 , Processed in 0.087706 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表