梯度下降算法

介绍
梯度下降法,又称最速下降法,是求解无约束最优化问题最常用的方法,它是一种迭代方法,每一步主要的操作是求解目标函数的梯度向量,将当前位置的负梯度方向作为搜索方向(因为在该方向上目标函数下降最快,这也是最速下降法名称的由来)。
直观解释
将函数比作一座山,我们站在某个山坡上,往四周看,从哪个方向向下走一小步,能够下降的最快。
同样,如果从任意一点出发,需要最快搜索到函数最大值,那么我们也应该从函数变化最快的方向搜索。
函数的梯度:函数变化最快的方向
梯度下降法特点:越接近目标值,步长越小,下降速度越慢。
直观上来看如下图所示:在这里插入图片描述

如果函数为一元函数,梯度就是该函数的导数
在这里插入图片描述
如果是二元函数,梯度的表示方法
在这里插入图片描述
梯度下降数学表示
在这里插入图片描述
在这里插入图片描述:是函数关于w的导数
如果需要找的是函数极小点,那么应该从负梯度的方向寻找,该方法称之为梯度下降法。
例如
在这里插入图片描述
批量梯度下降BGD(使用所有样本进行计算,慢但准确度好)
按照传统的思想,我们需要对上述损失函数中的每个求其偏导数,得到每个对应的梯度
在这里插入图片描述
这里表示第i个样本点的第j分量,即h(θ)中的
接下来由于我们要最小化损失函数,故按照每个参数的负梯度方向来更新每一个
在这里插入图片描述
这里的α表示每一步的步长 (步长适中,太小的话,可能导致迟迟走不到最低点,太大的话,会导致错过最低点)
优点:全局最优解;易于并行实现。
缺点:当样本数目很多时,训练过程会很慢,每次迭代需要耗费大量的时间,总体迭代次数多。
随机梯度下降SGD(样本多,但每次使用一个样本,准确度欠缺)
在这里插入图片描述
其中,
样本点在这里插入图片描述 的损失函数
然后得到每个梯度,最后更新下一个梯度。
优点:训练速度快,每次迭代计算量不大
缺点:准确度下降;不易于并行实现;总体迭代次数比较多。
算法收敛判断方法
参数ΘT的变化距离为0,或者说变化距离小于某一阈值(ΘT中每个参数的变化绝对值都小于一个阈值)。为减少计算复杂度,该方法更为推荐使用。
J(Θ)不再变化,或者说变化程度小于某一阈值。计算复杂度较高,但是如果为了精确程度,那么该方法更为推荐使用。
小批的梯度下降
这种方法把数据分为若干个批,按批来更新参数,这样,一个批中的一组数据共同决定了本次梯度的方向,下降起来就不容易跑偏,减少了随机性。另一方面因为批的样本数与整个数据集相比小了很多,计算量也不是很大。

梯度下降算法代码(借来的)

import numpy as np
import matplotlib.pyplot as plt
 
 
def create_sample_set():
    """
    生成样本数据集
    :return:
    """
    x = np.arange(0, 100, 1)
    y = x * 11.8 - np.random.standard_normal(100) * 100
    return x, y
 
 
def loss(weight, x, y):
    """
    损失函数使用均方误差
    :param weight:权重
    :param x:
    :param y:
    :return:
    """
    return (x * weight - y).T * (x * weight - y)
 
 
def gradient(weight, x, y):
    """
    基于损失函数求关于w的导数
    :param weight:
    :param x:
    :param y:
    :return:
    """
    return x.T * (x * weight - y)
 
 
def gradient_descent(x, y, max_iter=10, learning_rate=0.001):
    """
     梯度下降求解
    :param x:
    :param y:
    :param max_iter:
    :param learning_rate:
    :return:
    """
    m, n = np.shape(x)
    weight = np.mat(np.ones((n, 1)))
    loss_arr = []
    weight_arr = np.zeros((max_iter,n))
    for i in range(max_iter):
        g = gradient(weight, x, y)
        weight = weight - learning_rate * g
        error = loss(weight, x, y).T.tolist()[0][0]
        loss_arr.append(error)
        weight_arr[i, :] = weight.T
        print("迭代 {} 损失:{},weight参数:{}".format(i + 1, error, weight.T.tolist()))
 
    return weight,loss_arr,weight_arr
 
 
if __name__ == '__main__':
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
    features, labels = create_sample_set()
    X = np.ones((2, 100))
    X[1] = np.mat(features)
    X = X.T
    Y = labels.reshape(100, 1)
    weights,loss_array,weights_array = gradient_descent(X, Y, learning_rate=0.000001)
    # 绘制曲线
    fig = plt.figure()
 
    ax1 = fig.add_subplot(2, 2, 1)
    ax1.set_title("样本数据分布" )
    ax1.scatter(features, labels)
    ax2 = fig.add_subplot(2, 2, 2)
    ax2.set_title("梯度下降拟合效果" )
    ax2.scatter(features, labels)
    ax2.plot(features, (X * weights).T.tolist()[0])
    ax3 = fig.add_subplot(2, 2, 3)
    ax3.set_title("随着迭代次数增加loss走势")
    ax3.plot(range(len(loss_array)), loss_array)
    ax4 = fig.add_subplot(2, 2, 4)
    ax4.set_title("随着迭代数增加学习的参数逐渐稳定")
    ax4.plot(np.array(weights_array))
 
 
    plt.show()


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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值