当前位置: 首页 > news >正文

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

引言

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

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

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

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

一、轮次和批次

1.轮次的定义

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

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

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

3.批次的定义

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

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

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

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

1.创建数据集

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 方法创建数据集 X 和 y ,由于 \omega_{0} 的存在,我们需要拼接一列全为1的数据到矩阵上去,最后就形成了数据集 X_b 。(代码中 \omega_{0} = 4 , \omega _{1} = 3 )

2.设置超参数

# 创建超参数
learning_rate = 0.0001
n_iterations = 10000

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

3.初始化theta

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

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

4.进行参数更新迭代

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

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

5.整体代码

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):# 求梯度,计算gradientgradients = X_b.T.dot(X_b.dot(theta) - y)# 应用梯度下降法的公式调整theta值 theta_t+1 = theta_t - η * gradienttheta = theta - learning_rate * gradients
print(theta)

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

1.创建数据集

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.设置超参数

# 设置超参数
n_epochs = 10000
m = 100
learning_rate = 0.001

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

3.初始化theta

theta = np.random.randn(2, 1)

与全量梯度下降一致。 

4.进行参数更新迭代

# 每一个轮次
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.整体代码

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.创建数据集

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.设置超参数

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

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

3.初始化theta

# 初始化theta
theta = np.random.randn(2, 1)

4.进行参数更新迭代

# 每个轮次
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.整体代码

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算法工程师》)!!!


http://www.mrgr.cn/news/49495.html

相关文章:

  • 【JavaScript】JavaScript开篇基础(3)
  • Mac 备忘录妙用
  • TensorRT-LLM七日谈 Day2
  • 数据结构(线性表)
  • 在深圳宝安石岩路过一座关帝宫
  • HTML+CSS+JS实现多张图片点击放大查看的功能
  • 使用docker搭建lnmp运行WordPress
  • 【Linux】Linux下进程Vs线程
  • 【conda】创建、激活、删除虚拟环境
  • 【数据结构】关于环形队列库的改进办法
  • MySQL数据库管理
  • SQL基础练习题一
  • 【踩坑随笔】Failed to build pycocotools
  • k8s-资源管理、实战入门
  • 大数据治理:构建数据驱动的智能决策体系
  • 后端参数校验方式
  • vue的动态组件 keep-alive
  • Informer: Beyond Efficient Transformer for Long SequenceTime-Series Forecasting
  • Java中的Iterator接口,以及HashSet和TreeSet
  • 蓝桥备战国奖题后总结(2)