多元线性回归梯度下降法

本文涉及的产品
实时计算 Flink 版,5000CU*H 3个月
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
简介: 梯度下降法是一种通用的优化算法,尤其适用于机器学习中找到最优解。与解析解法不同,它不局限于特定情况,能在数据规模较大时依然有效。该方法通过迭代逐步接近最优解,每次迭代利用损失函数的梯度信息调整参数。学习率是控制参数更新幅度的关键因素,太大会导致发散,太小则收敛慢。全量梯度下降每次使用所有样本更新,收敛稳定但速度慢;随机梯度下降每次仅用一个样本,速度快但可能产生较大波动;小批量梯度下降取两者之间,以一定的样本批量进行更新,兼顾速度和稳定性。

梯度下降法(Gradient Descent)是一个算法,但不同于解析解法一般局限,相反,他是一个非常通用的优化算法来帮助一些机器学习求出最优解。

 解析解可以成功的原因是MSE损失函数是凸函数,即Hessian矩阵半正定,但假使损失函数非凸,解析解就比较局限。而且解析解的运算较为复杂,时间复杂度达到 。所以解析解法在涉及数据较大时并不好用。

梯度下降法是一点点逼近最优解的方法

image.gif 编辑

梯度下降公式

这里梯度下降公式仅仅只是一个指导计算机迭代过程中如何去调整θ变化的式子,不需要推导和证明。其中 为学习率(learning rate)。学习率一般为正数。在最优解左侧,梯度小于0,学习率大于0,Wj递增,靠近最优解。同理,在最优解右侧,梯度大于0,学习率大于0,Wj递减,同样会靠近最优解。

学习率设置

image.gif 编辑

如上图所示,小学习率比较稳定,但是迭代次数会比较大,如果遇到鞍面会停留很长时间。

适中的学习率迭代次数更少而且可以跳出局部最优解去寻找更好的解,但是可能会出现达不到最优解的情况。大学习率会发散,损失函数会越来越大。这种是不可取的学习率。最后是最优学习率(一般不考虑),即一步直接到最优解。

image.gif 编辑

我们可以设置学习率随着迭代次数减小,这样既可以跳出局部最优解,同时也保证可以收敛到最优解。这个过程我们称为学习速率调整(又称学习速率调度):一般使用某种事先设定好的策略或者在每次迭代中衰减一个减小的阈值。

梯度下降的流程(附代码)

Step 1. 随机θ参数

我们先创建一组随机的θ参数作为起始点

import numpy as np
theta = np.random.randn(2,1)#创建一组服从正态分布的参数

image.gif

这里,我们创建一个两行一列的参数矩阵。

Step 2. 求解梯度

简而言之,假设X(mxn),W(nx1)某个维度j的梯度gradient(j) = ε(mx1)乘上X的第j列,这显然不符合矩阵相乘,所以真实情况是需要将Xj转置。

import numpy as np
gradients = X_b.T.dot((X_b.dot(theta) - y))

image.gif

Step 3. 调整θ参数

判断收敛时使用g= 0并不合理,因为当损失函数时非凸函数的话,g = 0只是一个驻点,还可能是最大值,这不能说明什么。其实判断loss下降收益更加合理,当收益不再变化就可以认为达到局部最优解。即

theta = theta - learning_rate * gradients

image.gif

梯度下降的分类

区别:三种梯度下降的区别仅在于第二步求解梯度所用到的X数据集的样本数量不同,每次学习(更新模型参数)使用的样本数目,每次使用不同的样本会导致每次学习的准确性和学习时间不同。

全量梯度下降(Batch Gradient Descent)

在全量梯度下降中,对于θ的更新,所有样本都有贡献,也就是参与调整θ。其计算得到的是一个标准梯度。因而理论上来说一次更新的幅度是比较大的。如果样本不多的情况下,这样的收敛速度会更快,优点在于每次更新都会朝着正确的方向进行,最终收敛于极值点,缺点就是时间比较长。

import numpy as np
#全量梯度下降
X = np.random.rand(100,1)
y = 4+3*X + np.random.randn(100,1)
X_b = np.c_[np.ones((100,1)),X]
#创建超参数
n_iterations = 10000
t0,t1 = 5, 500
#定义一个函数来动态调整学习率
def learning_rate_schedule(t):
    return t0/(t+t1)
#初始化theta
theta = np.random.randn(2,1)
truth =np.array([[4],[3]])
#判断是否收敛,一般不设置阈值,而是采用相对大的迭代次数保证收敛
for i in range(n_iterations):
    # 求梯度,计算gradient
    gradients = X_b.T.dot((X_b.dot(theta) - y))  # 一个含有g0和g1的列向量
    # 应用梯度下降法的公式去调整theta值
    learning_rate = learning_rate_schedule(i)
    theta = theta - learning_rate * gradients
print(theta)
print("Error(%):")
print("W0=",((abs(theta-truth)[0,:]/abs(truth)[0,:])*100)[0],"%")
print("W1=",((abs(theta-truth)[1,:]/abs(truth)[1,:])*100)[0],"%")

image.gif

image.gif

随机梯度下降(Stochastic Gradient Descent)

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

优点:学习非常迅速,可能会选择更好的局部最优解。

缺点:每次更新可能并不会按照正确方向进行,因此带来优化波动,迭代次数增加。

import numpy as np
X = np.random.rand(100,1)
y = 4 + 3*X + np.random.randn(100,1)
X_b = np.c_[np.ones((100,1)),X]
n_epochs = 10000
m = 100
truth =np.array([[4],[3]])
t0,t1 = 5, 500
def learning_rate_schedule(t):
    return t0/(t+t1)
theta = np.random.randn(2,1)
for epoch in range(n_epochs):
    #每个轮次开始前打乱顺序
    arr = np.arange(len(X_b))
    np.random.shuffle(arr)
    X_b = X_b[arr]
    y = y[arr]
    for i in range(m):
        xi = X_b[i:i+1]#左闭右开
        yi = y[i:i+1]
        gradients = xi.T.dot((xi.dot(theta) - yi))
        learning_rate = learning_rate_schedule(epoch*m + i)
        theta = theta - learning_rate*gradients
print(theta)
print("Error(%):")
print("W0=",((abs(theta-truth)[0,:]/abs(truth)[0,:])*100)[0],"%")
print("W1=",((abs(theta-truth)[1,:]/abs(truth)[1,:])*100)[0],"%")

image.gif

image.gif 编辑

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

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

import numpy as np
X = 2*np.random.rand(100,1)
y = 4+3*X + np.random.randn(100,1)
X_b = np.c_[np.ones((100,1)),X]
learning_rate = 0.0001
n_epochs = 10000
m = 100
batch_size = 10
num_batches = int(m/batch_size)
theta = np.random.randn(2,1)
truth =np.array([[4],[3]])
for epoch in range(n_epochs):
    arr = np.arange(len(X_b))
    np.random.shuffle(arr)
    X_b = X_b[arr]
    y = y[arr]
    for i in range(num_batches):
        selected_index = np.random.randint(m)
        x_batch = X_b[i:i+batch_size]
        y_batch = y[i:i+batch_size]
        gradients = x_batch.T.dot((x_batch.dot(theta) - y_batch))
        theta = theta - learning_rate * gradients
print(theta)
print("Error(%):")
print("W0=",((abs(theta-truth)[0,:]/abs(truth)[0,:])*100)[0],"%")
print("W1=",((abs(theta-truth)[1,:]/abs(truth)[1,:])*100)[0],"%")

image.gif

image.gif 编辑

目录
相关文章
MATALB运用——最小二乘法拟合
MATALB运用——最小二乘法拟合
138 0
|
机器学习/深度学习 数据可视化 Python
逻辑回归那些事—使用牛顿法解决实际问题
逻辑回归是机器学习中的重要章节,本文将带你从公式推导到算法实现详细讲述这部分内容,想学习这个高大上的技能么,快来看吧!!!
5486 0
|
5月前
|
机器学习/深度学习 数据可视化 Python
Logistic回归(一)
这篇内容是一个关于逻辑回归的教程概览
|
5月前
|
机器学习/深度学习 算法
Logistic回归(二)
Logistic回归,又称对数几率回归,是用于分类问题的监督学习算法。它基于对数几率(log-odds),通过对数转换几率来确保预测值在0到1之间,适合于二分类任务。模型通过Sigmoid函数(S型曲线)将线性预测转化为概率。逻辑回归损失函数常采用交叉熵,衡量模型预测概率分布与真实标签分布的差异。熵和相对熵(KL散度)是评估分布相似性的度量,低熵表示分布更集中,低交叉熵表示模型预测与真实情况更接近。
|
6月前
|
算法 Python
梯度下降法
梯度下降法
69 0
|
机器学习/深度学习 Web App开发 算法
四、多元线性回归
四、多元线性回归
四、多元线性回归
|
数据库
R 多元线性回归
R 多元线性回归
183 0
R 多元线性回归
|
算法
简单的梯度下降算法,你真的懂了吗?
简单的梯度下降算法,你真的懂了吗?
205 0
简单的梯度下降算法,你真的懂了吗?