13.梯度下降法的代码实战——举足轻重的模型优化算法

引言

通过12.梯度下降法的具体解析------举足轻重的模型优化算法-CSDN博客的学习,我们已经了解到了梯度下降法的整体流程与不同分类。归根结底,我们最终是要使用代码实现梯度下降法。

通过阅读本篇博客,你可以:

1.知晓轮次和批次的定义

2.使用代码实现不同的梯度下降法

一、轮次和批次

1.轮次的定义

**轮次(epoch)**指的是整个训练数据集被完整使用一次的过程。一个轮次就是指所有的训练样本训练模型一次。在这里就表明了我们使用梯度下降法中模型遍历整个训练样本的次数。

2.轮次在梯度下降法中的应用

通常情况下,一个训练过程会设置多个轮次。例如,如果我们设定进行10个轮次,模型就会遍历整个训练集10次,每次都尝试优化参数以降低损失函数。

3.批次的定义

**批次(batch)**是指在一次参数更新中使用的样本数量。在训练过程中,批次可以根据数据集的大小和内存的限制进行调整。一个批次通常只包括训练集的一部分。

4.批次在梯度下降法中的应用

在梯度下降法中,批次指我们已有的训练集数据较多的时候,一轮要学习太多的数据,那就把一轮此的数据分成多个批次,一批一批的学习。

二、全量梯度下降的代码实现

1.创建数据集

python 复制代码
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]

我们导入numpy模块,使用其中的 random 方法创建数据集 ,由于 的存在,我们需要拼接一列全为1的数据到矩阵上去,最后就形成了数据集 X_b 。(代码中 , )

2.设置超参数

python 复制代码
# 创建超参数
learning_rate = 0.0001
n_iterations = 10000

我们通常将学习率设置为0.001,0.0001等较为小的数字。通过较大的迭代次数保证函数能够收敛。

3.初始化theta

python 复制代码
#初始化theta,W0,...Wn,标准正太分布创建W
theta = np.random.randn(2, 1)

由于数据集中只有 一个维度,再算上截距项 。我们就可以使用 random 方法随机创建一个两行一列的 作为梯度下降的参数。

4.进行参数更新迭代

python 复制代码
#进行迭代
for _ in range(n_iterations):
    # 求梯度,计算gradient
    gradients = X_b.T.dot(X_b.dot(theta) - y)
    # 应用梯度下降法的公式调整theta值 theta_t+1 = theta_t - η * gradient
    theta = theta - learning_rate * gradients

我们开始进行参数更新的迭代,每次迭代中,我们要计算梯度的大小和更新参数。由梯度计算公式 可以得出代码中梯度计算的实现(由于同行同列的矩阵运算不能直接相乘,所以我们使用 X_b 的转置相乘)。由梯度下降法公式 可以得出代码中的参数更新的实现。(公式的原理请参考12.梯度下降法的具体解析------举足轻重的模型优化算法-CSDN博客)

5.整体代码

python 复制代码
import numpy as np

# 创建数据集X,y
X = 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_iterations = 10000
# 初始化theta,W0,...Wn,标准正太分布创建W
theta = np.random.randn(2, 1)
print(theta)
# 判断是否收敛,一般不会设定阈值,而是直接采用设置相对大的迭代次数保证收敛
for _ in range(n_iterations):
    # 求梯度,计算gradient
    gradients = X_b.T.dot(X_b.dot(theta) - y)
    # 应用梯度下降法的公式调整theta值 theta_t+1 = theta_t - η * gradient
    theta = theta - learning_rate * gradients
print(theta)

三、随机梯度下降的代码实现

1.创建数据集

python 复制代码
import numpy as np

# 创建数据集X,y
X = 2 * np.random.rand(100, 1)
y = 5 + 3 * X + np.random.randn(100, 1)
X_b = np.c_[np.ones((100, 1)), X]

创建数据集这边的代码实现原理与全量梯度下降一模一样。

2.设置超参数

python 复制代码
# 设置超参数
n_epochs = 10000
m = 100
learning_rate = 0.001

同样地,我们仍将轮次设置为10000。不同地是,随机梯度下降每个批次只使用一个随机的样本,所以我们要使用 来代表总样本数100,以代表每个轮次下批次的总数。

3.初始化theta

python 复制代码
theta = np.random.randn(2, 1)

与全量梯度下降一致。

4.进行参数更新迭代

python 复制代码
# 每一个轮次
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)
        theta = theta - learning_rate * gradients

随机梯度下降除了每个轮次需要遍历,还要对每个批次进行遍历。那么这里就会产生一个值得思考的问题:"我们有什么方法在每一个轮次遍历到所有样本的情况下还保持随机性呢?"。在提出这个问题之后,我想到了一种解决方案,就是在批次遍历之前,使用 random.shuffle方法将数组的索引进行随机打乱,在每个批次遍历的时候按照打乱索引的顺序进行遍历。这样就可以取巧的解决这个问题。

5.整体代码

python 复制代码
import numpy as np

# 创建数据集X,y
X = 2 * np.random.rand(100, 1)
y = 5 + 3 * X + np.random.randn(100, 1)
X_b = np.c_[np.ones((100, 1)), X]
# 设置超参数
n_epochs = 10000
m = 100
learning_rate = 0.001
# 初始化theta
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)
        theta = theta - learning_rate * gradients
print(theta)

四、小批量梯度下降的代码实现

1.创建数据集

python 复制代码
import numpy as np

# 设置数据集X,y
X = 3 * np.random.rand(100, 1)
y = 10 + 4 * X + np.random.randn(100, 1)
X_b = np.c_[np.ones((100, 1)), X]

大同小异,不再赘述。

2.设置超参数

python 复制代码
# 设置超参数
n_epochs = 10000
m = 100
batch_size = 10
num_batches = int(m / batch_size)
learning_rate = 0.001

小批量梯度下降要设置每个批次中批量的大小,这里我们将其设置为 。那么每个轮次中需要批次遍历的次数就是 。使用 的原因是如果无法正好整除,那么我们可以舍弃掉一些多余的样本。这样处理减少了一个多余批次的消耗,并且少量样本的减少并不会对结果产生影响。

3.初始化theta

python 复制代码
# 初始化theta
theta = np.random.randn(2, 1)

4.进行参数更新迭代

python 复制代码
# 每个轮次
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):
        x_batch = X_b[i*batch_size:i*batch_size + batch_size]
        y_batch = y[i*batch_size:i*batch_size + batch_size]
        # 求梯度
        gradients = x_batch.T.dot(x_batch.dot(theta) - y_batch)
        theta = theta - learning_rate * gradients

小批量梯度下降中的参数更新迭代其实与随机梯度下降很类似。改变的只有批次遍历数量和每个批次中数据量的大小与索引。

5.整体代码

python 复制代码
import numpy as np

# 设置数据集X,y
X = 3 * np.random.rand(100, 1)
y = 10 + 4 * X + np.random.randn(100, 1)
X_b = np.c_[np.ones((100, 1)), X]
# 设置超参数
n_epochs = 10000
m = 100
batch_size = 10
num_batches = int(m / batch_size)
learning_rate = 0.001
# 初始化theta
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(num_batches):
        x_batch = X_b[i*batch_size:i*batch_size + batch_size]
        y_batch = y[i*batch_size:i*batch_size + batch_size]
        # 求梯度
        gradients = x_batch.T.dot(x_batch.dot(theta) - y_batch)
        theta = theta - learning_rate * gradients
print(theta)

总结

本篇博客重点讲解了三种梯度下降法的不同代码实现。希望可以对大家起到作用,谢谢。


关注我,内容持续更新(后续内容在作者专栏《从零基础到AI算法工程师》)!!!

相关推荐
课堂剪切板13 分钟前
ch03 部分题目思路
算法
空中湖14 分钟前
tensorflow武林志第二卷第九章:玄功九转
人工智能·python·tensorflow
lishaoan7720 分钟前
使用tensorflow的线性回归的例子(七)
人工智能·tensorflow·线性回归
山登绝顶我为峰 3(^v^)31 小时前
如何录制带备注的演示文稿(LaTex Beamer + Pympress)
c++·线性代数·算法·计算机·密码学·音视频·latex
Two_brushes.2 小时前
【算法】宽度优先遍历BFS
算法·leetcode·哈希算法·宽度优先
千宇宙航3 小时前
闲庭信步使用SV搭建图像测试平台:第三十一课——基于神经网络的手写数字识别
图像处理·人工智能·深度学习·神经网络·计算机视觉·fpga开发
IT古董3 小时前
【第二章:机器学习与神经网络概述】04.回归算法理论与实践 -(4)模型评价与调整(Model Evaluation & Tuning)
神经网络·机器学习·回归
onceco4 小时前
领域LLM九讲——第5讲 为什么选择OpenManus而不是QwenAgent(附LLM免费api邀请码)
人工智能·python·深度学习·语言模型·自然语言处理·自动化
森焱森4 小时前
水下航行器外形分类详解
c语言·单片机·算法·架构·无人机
天水幼麟4 小时前
动手学深度学习-学习笔记(总)
笔记·深度学习·学习