河南南阳收割机被堵事件:官员缺德,祸患无穷

极目新闻领导公开“记者毕节采访被打”细节:他们打人后擦去指纹

突发!员工跳楼!只拿低保工资!央企设计院集体罢工!

退休后的温家宝

突发!北京某院集体罢工!

生成图片,分享到微信朋友圈

自由微信安卓APP发布,立即下载! | 提交文章网址
查看原文

ML/DL---梯度下降算法的快速理解

胡萝卜酱 DataGo数据狗 2022-07-01

梯度下降(Gradient Descent)算法是机器学习和神经网络模型训练最常用的优化算法。当前流行的机器学习库或者深度学习库都会包括梯度下降算法的不同变种实现。本文将从数学上解释其原理,然后通过例子来进一步理解。


梯度下降的原理


梯度下降的基本思想是将函数比作一座山,寻求最优解的过程就是下山的过程。但是当你被困在上山时,你并不知道从哪条路下山,那么你将以目前所处的位置为基准,朝四周看,从哪个方向向下走一步能够下降的最快。同理,如果你的目标是从山底出发爬到山顶,那么你需要的是朝着最陡峭的方向向上走(梯度上升)。每走一定距离,都反复采用同一个方法,最后成功到达山谷或山顶。


梯度下降的推导


Python数据分析之逻辑回归(logistic regression)一文中,已经介绍过梯度上升法,其实梯度上升法求得是极大值,梯度下降法求解的是最小值,两者原理是一样的。

首先,需要理解什么是梯度。对多元函数的参数求∂偏导数,把求得的各个参数的偏导数以向量的形式写出来,就是梯度。比如函数f(x,y), 分别对x,y求偏导数,求得的梯度向量就是(∂f/∂x, ∂f/∂y)T。

其次,我们需要理解下面这些概念:

  •  步长(Learning rate):步长决定了在梯度下降迭代的过程中,每一步沿梯度负方向前进的长度。

  • 特征(feature):指的是样本中输入部分。

  • 损失函数(loss function):为了评估模型拟合的好坏,通常用损失函数来度量拟合的程度。损失函数极小化,意味着拟合程度最好,对应的模型参数即为最优参数。在线性回归中,损失函数通常为样本输出和假设函数的差取平方。比如对于m个样本,采用线性回归,损失函数为:


    梯度下降的步骤如下:

    1. 对θ赋初始值,这个值可以是随机的,也可以让θ是一个全零的向量。

    2. 改变θ的值,使得目标损失函数J(θ)按梯度下降的方向进行减少。


    其中为学习率或步长,需要人为指定,若过大会导致震荡即不收敛,若过小收敛速度会很慢。

    3.当下降的高度小于某个定义的值,则停止下降。


    梯度下降的分类


    • 批量梯度下降(Batch gradient descent) 

    每次使用全量的训练集样本来更新模型参数,即给定一个步长,然后对所有的样本的梯度的和进行迭代。

    优点:全局最优解;易于并行实现;总体迭代次数不多。

    缺点:当样本数目很多时,训练过程会很慢,每次迭代需要耗费大量的时间。

    • 随机梯度下降(Stochastic gradient descent) 

    随机梯度下降算法每次从训练集中随机选择一个样本来进行迭代。

    优点:训练速度快,每次迭代计算量不大。

    缺点:准确度下降,并不是全局最优;不易于并行实现;总体迭代次数比较多。

    • 小批量梯度下降法(Mini-Batch Gradient Descent)

    Mini-batch梯度下降综合了batch梯度下降与stochastic梯度下降,在每次更新速度与更新次数中间取得一个平衡,其每次更新从训练集中随机选择b,b<m个样本进行学习。


    代码演示


    下面是批量梯度下降法的代码(非原创):

    1import numpy as np
    2from scipy import stats
    3import matplotlib.pyplot as plt
    4
    5# 构造训练数据
    6x = np.arange(0.10.0.2)
    7m = len(x)  # 训练数据点数目
    8print (m)
    9x0 = np.full(m, 1.0)
    10input_data = np.vstack([x0, x]).T  # 将偏置b作为权向量的第一个分量
    11target_data = 2 * x + 5 + np.random.randn(m)
    12
    13# 两种终止条件
    14loop_max = 10000  # 最大迭代次数(防止死循环)
    15epsilon = 1e-3
    16
    17# 初始化权值
    18np.random.seed(0)
    19theta = np.random.randn(2)
    20
    21alpha = 0.001  # 步长(注意取值过大会导致振荡即不收敛,过小收敛速度变慢)
    22diff = 0.
    23error = np.zeros(2)
    24count = 0  # 循环次数
    25finish = 0  # 终止标志
    26
    27while count < loop_max:
    28    count += 1
    29
    30    # 标准梯度下降是在权值更新前对所有样例汇总误差,而随机梯度下降的权值是通过考查某个训练样例来更新的
    31    # 在标准梯度下降中,权值更新的每一步对多个样例求和,需要更多的计算
    32    sum_m = np.zeros(2)
    33    for i in range(m):
    34        dif = (np.dot(theta, input_data[i]) - target_data[i]) * input_data[i]
    35        sum_m = sum_m + dif  # 当alpha取值过大时,sum_m会在迭代过程中会溢出
    36
    37    theta = theta - alpha * sum_m  # 注意步长alpha的取值,过大会导致振荡
    38    # theta = theta - 0.005 * sum_m      # alpha取0.005时产生振荡,需要将alpha调小
    39
    40    # 判断是否已收敛
    41    if np.linalg.norm(theta - error) < epsilon:
    42        finish = 1
    43        break
    44    else:
    45        error = theta
    46    print ('loop count = %d' % count, '\tw:',theta)
    47print ('loop count = %d' % count, '\tw:',theta)
    48
    49# check with scipy linear regression
    50slope, intercept, r_value, p_value, slope_std_error = stats.linregress(x, target_data)
    51print ('intercept = %s slope = %s' % (intercept, slope))
    52
    53plt.plot(x, target_data, 'g*')
    54plt.plot(x, theta[1] * x + theta[0], 'r')
    55plt.show()

    Python数据分析之逻辑回归(logistic regression)一文中,有随机梯度上升和改进版梯度上升的代码,这里就不在重复。但这里重点给大家推荐sklearn里面的SGDClassifier,超级好用。

    SGDClassifier支持多分类,它以”one-vs-all(OVA)”的方式通过结合多个二分类来完成。对于K个类中的每个类来说,一个二分类器可以通过它和其它K-1个类来进行学习得到。在测试时,我们会为每个分类器要计算置信度(例如:到超平面的有符号距离)并选择最高置信度的类。具体参数如下:


    结语


    其实梯度下降还是蛮简单的,大家可不要被公式吓到了。掌握了它,对机器学习和深度学习之后的公式推导会更容易理解,多练几次,就熟悉了。


    此文花费了不少功夫,赞赏、点赞、转发都是对作者的认可和支持。

    文章有问题?点此查看未经处理的缓存