梯度下降法的三种解释(BGD,SGD,MBGD).

本文详细介绍了机器学习中常用的三种梯度下降法:批量梯度下降法(BGD)、随机梯度下降法(SGD)及小批量梯度下降法(MBGD),并比较了它们各自的优缺点。
AI助手已提取文章相关产品:

      机器学习里面,梯度下降法可以说是随处可见,虽然它不是什么高大上的机器学习算法,但是它却是用来解决机器学习算法的良药。我们经常会用到梯度下降法来对机器学习算法进行训练。

   在很多介绍梯度下降的书籍里,我们看到这样的几个英文单词缩写,BGD,SGD,MBGD。也就是批量梯度下降法BGD,随机梯度下降法SGD,小批量梯度下降法MBGD。

   哦儿啦,举例说明,一般一个线性回归函数的假设函数可以写成:hθ=nj=0θjxj

   则损失函数为:


(1)批量梯度下降法

          批量梯度下降法的思路是更新每一个参数都会使用到所有的样本 更新的theta为

这种方法可以看出每次迭代都需要所有的样本,样本m很大会影响速度,该方法可以得到全局最优解。

(2)随机梯度下降法

          随机梯度下降法更新theta的公式是:

随机梯度下降是通过每个样本来迭代更新一次,如果样本量很大的情况,那么可能只用其中部分的样本,就已经将theta迭代到最优解了,对比上面的批量梯度下降,迭代一次需要用到十几万训练样本,一次迭代不可能最优,如果迭代10次的话就需要遍历训练样本10次。缺点是SGD的噪音较BGD要多,使得SGD并不是每次迭代都向着整体最优化方向。所以虽然训练速度快,但是准确度下降,并不是全局最优。


(3) 小批量梯度下降法

     小批量梯度下降法考虑以上两种方法的优缺点,做出改进。也就是在每次更新参数时候,使用固定a个样本。如总样本1000,取a=10

     


大致情况就是这样,说白了,第一种方法缺点就是每次更新参数都需要全部样本,即使迭代次数少,但是样本很大的情况下,速度也是很慢的,第二种情况就是虽然每次更新参数我不需要全部样本,我只需要一个样本,但是迭代次数会很多,而且往往求得不是最优解,所以第三种方法采用部分小样本进行,每次更新使用固定个样本量,从而达到好的效果。这三种方法没有谁最好最差,具体问题具体分析。




您可能感兴趣的与本文相关内容

<think> 我们参考上述引用内容,特别是引用[1][2][3]中关于BGDSGDMBGD的定义和特点,来回答如何绘制它们的收敛曲线。 收敛曲线通常是指在迭代过程中损失函数值随迭代次数的变化曲线。绘制收敛曲线的步骤大致如下: 1. 在训练过程中,记录每次迭代(或每个epoch)的损失值(loss)。 2. 将迭代次数作为横坐标,损失值作为纵坐标,绘制曲线。 由于BGDSGDMBGD在每次迭代中使用的样本数量不同,因此在记录损失值时需要注意: - 对于BGD批量梯度下降):每次迭代使用所有样本,因此每次迭代计算一次损失(通常在整个训练集上计算损失),记录该损失值。 - 对于SGD(随机梯度下降):每次迭代使用一个样本,因此每次迭代计算的是该样本的损失。但为了反映整体收敛情况,我们通常会在每次迭代后在整个训练集或验证集上计算一次损失(这样计算开销大,但能反映整体情况),或者每隔一定迭代次数计算一次整体损失。 - 对于MBGD(小批量梯度下降):每次迭代使用一个小批量(batch)的样本,每次迭代计算该小批量上的损失。同样,为了观察整体收敛,通常会在每个epoch结束后或每隔一定迭代次数在完整训练集上计算一次损失。 因此,绘制收敛曲线的通用方法: 步骤1:在训练循环中,定期(如每次迭代、每个batch后、或每个epoch)记录损失值。 步骤2:对于SGDMBGD,由于每次迭代的损失可能只基于少量样本,波动较大,通常我们会采用滑动平均来平滑曲线,或者使用整个训练集的平均损失来记录(但这样计算成本高,所以通常每个epoch记录一次)。 具体到三种方法: 1. BGD:每次迭代后,损失值是基于整个训练集计算得到的,所以每次迭代记录一次损失值。 2. SGD:由于每次迭代只用一个样本,迭代速度快,但单个样本的损失波动很大。因此,通常有两种记录方式: a) 记录每次迭代的单个样本的损失(不常用,因为噪声太大) b) 记录每个epoch结束后在整个训练集上的平均损失(常用,这样曲线更平滑,反映整体趋势)。 3. MBGD:每次迭代使用一个小批量,可以记录每次迭代的该批次的平均损失(但同样有噪声),也可以记录每个epoch的整个训练集的平均损失。 通常,在比较三种方法的收敛曲线时,我们会以epoch作为横坐标(这样比较公平,因为一个epoch代表遍历整个训练集一次),然后记录每个epoch结束时的损失值(在整个训练集上计算)。 下面我们给出一个示例代码框架,展示如何在训练过程中记录损失并绘制收敛曲线(以线性回归为例,使用均方误差MSE作为损失函数): 注意:为了简化,我们假设使用整个训练集计算的损失函数为`compute_loss(X, y, theta)`,其中`X`是特征矩阵,`y`是标签,`theta`是模型参数。 我们将分别模拟BGDSGDMBGD的训练过程,并记录每个epoch后的损失。 步骤: 1. 初始化参数theta 2. 设置学习率、迭代次数(epochs)等超参数 3. 对于每个epoch: - BGD:使用整个训练集计算梯度和更新参数,然后记录整个训练集的损失。 - SGD:打乱训练集,然后对每个样本进行迭代(每个样本一次梯度更新),在每个epoch结束后记录整个训练集的损失。 - MBGD:将训练集分成多个小批量,对每个小批量进行梯度更新,在每个epoch结束后记录整个训练集的损失。 然后,我们将每个epoch的损失值保存起来,最后绘制曲线。 示例代码(Python): 注意:这里仅展示训练循环和记录损失的部分,不包含数据生成和具体的梯度计算。 首先,我们定义一个计算损失函数(整个训练集)的函数: ```python def compute_loss(X, y, theta): m = len(y) predictions = X.dot(theta) loss = (1/(2*m)) * np.sum((predictions - y)**2) return loss ``` 然后,我们分别实现三种梯度下降: 1. BGD收敛曲线绘制 ```python def bgd(X, y, theta, learning_rate, epochs): m = len(y) losses = [] for i in range(epochs): # 计算梯度 gradient = (1/m) * X.T.dot(X.dot(theta) - y) # 更新参数 theta = theta - learning_rate * gradient # 计算当前参数在整个训练集上的损失 loss = compute_loss(X, y, theta) losses.append(loss) return losses, theta ``` 2. SGD收敛曲线绘制 注意:SGD每次用一个样本更新参数,一个epoch有m次更新(m为样本数)。但我们在每个epoch结束后记录一次损失。 ```python def sgd(X, y, theta, learning_rate, epochs): m = len(y) losses = [] for i in range(epochs): # 打乱数据 permutation = np.random.permutation(m) X_shuffled = X[permutation] y_shuffled = y[permutation] # 遍历每个样本 for j in range(m): # 随机选取一个样本(这里因为已经打乱,所以按顺序取) x_j = X_shuffled[j:j+1] # 保持维度 y_j = y_shuffled[j] # 计算该样本的梯度 gradient = x_j.T.dot(x_j.dot(theta) - y_j) # 更新参数 theta = theta - learning_rate * gradient # 整个epoch结束后,计算整个训练集的损失 loss = compute_loss(X, y, theta) losses.append(loss) return losses, theta ``` 3. MBGD收敛曲线绘制 假设batch_size设为64,则每个epoch有 (m + batch_size - 1) // batch_size 个batch。 ```python def mbgd(X, y, theta, learning_rate, epochs, batch_size=64): m = len(y) num_batches = int(np.ceil(m / batch_size)) losses = [] for i in range(epochs): # 打乱数据 permutation = np.random.permutation(m) X_shuffled = X[permutation] y_shuffled = y[permutation] # 遍历每个batch for j in range(num_batches): start = j * batch_size end = min(start + batch_size, m) X_batch = X_shuffled[start:end] y_batch = y_shuffled[start:end] # 计算梯度 gradient = (1/(end-start)) * X_batch.T.dot(X_batch.dot(theta) - y_batch) # 更新参数 theta = theta - learning_rate * gradient # 整个epoch结束后,计算整个训练集的损失 loss = compute_loss(X, y, theta) losses.append(loss) return losses, theta ``` 绘制收敛曲线: 在分别运行上述三个函数后,我们可以得到三个损失列表(每个epoch一个损失值)。然后使用matplotlib绘制曲线: ```python import matplotlib.pyplot as plt # 假设已经运行了三种方法,得到了三个损失列表:losses_bgd, losses_sgd, losses_mbgd epochs = range(1, len(losses_bgd)+1) plt.plot(epochs, losses_bgd, 'b-', label='BGD') plt.plot(epochs, losses_sgd, 'r-', label='SGD') plt.plot(epochs, losses_mbgd, 'g-', label='MBGD') plt.xlabel('Epochs') plt.ylabel('Loss') plt.title('Convergence Curves') plt.legend() plt.show() ``` 注意:在实际运行中,由于SGD的更新噪声较大,可能需要更多的epoch才能收敛,且其曲线可能波动较大。而BGD的曲线则较为平滑。MBGD介于两者之间。 另外,我们也可以记录每次迭代的损失(而不仅仅是每个epoch),尤其是对于MBGD,我们可以记录每个batch后的损失(但这样数据点会很多,且曲线波动大)。但为了公平比较,通常以epoch为单位。 总结:绘制收敛曲线的关键在于定期记录损失值(通常每个epoch记录一次在整个训练集上的损失),然后绘制损失随epoch变化的曲线。 §§相关问题§§ 1. 为什么SGD的收敛曲线通常比BGD的波动大? 2. 在绘制收敛曲线时,除了使用训练集损失,还可以使用验证集损失吗? 3. 如何通过收敛曲线判断模型是否过拟合? </think> ### 梯度下降算法收敛曲线绘制方法 要绘制BGDSGDMBGD的收敛曲线,需在训练过程中记录损失函数值随迭代次数的变化。以下是具体步骤和方法: #### 基本步骤 1. **初始化参数** - 随机初始化模型参数 $\theta$ - 设置学习率 $\eta$、迭代次数 $T$(BGD)或 epoch 数(SGD/MBGD) - 对于MBGD,还需设置批大小 $k$(如64、128) 2. **训练循环中记录损失值** ```python # 伪代码示例 losses = [] # 存储每次迭代的损失值 for epoch in range(epochs): # BGD: 整个数据集计算损失 loss = compute_loss(X, y, theta) losses.append(loss) gradient = compute_gradient(X, y, theta) theta = theta - eta * gradient # SGD: 每个样本记录一次损失(可选) for i in range(m): loss_i = compute_loss(X[i], y[i], theta) losses.append(loss_i) # 记录每个样本损失 # 参数更新... # MBGD: 每个batch记录一次损失 for batch in batches: loss_batch = compute_loss(X_batch, y_batch, theta) losses.append(loss_batch) # 记录批次损失 # 参数更新... ``` 3. **绘制曲线** ```python import matplotlib.pyplot as plt plt.plot(losses, label='Loss Curve') plt.xlabel('Iterations/Epochs') plt.ylabel('Loss Value') plt.title('Convergence Curve') plt.legend() plt.show() ``` #### 三种方法的绘制要点 1. **BGD批量梯度下降)** - 横轴:迭代次数(每次迭代用全量数据) - 纵轴:全量数据计算的损失值 - 特点:曲线平滑但下降缓慢 - 代码特点:每迭代一次记录一个损失值 2. **SGD(随机梯度下降)** - 横轴:迭代次数(每次迭代用单个样本) - 纵轴: - 方案1:记录单个样本损失(噪声大) - 方案2:每完整遍历一次数据(epoch)后计算全量损失(推荐) - 特点:曲线波动剧烈但收敛快 - 代码调整: ```python epoch_losses = [] for epoch in range(epochs): # 遍历所有样本 for i in range(m): # 参数更新使用单个样本... # 记录整个epoch的损失 total_loss = compute_loss(X, y, theta) epoch_losses.append(total_loss) # 用于绘图 ``` 3. **MBGD(小批量梯度下降)** - 横轴: - 选项1:批次数(每次batch更新记录) - 选项2:epoch数(推荐,便于对比) - 纵轴:全量数据集损失值(每epoch结束时计算) - 特点:曲线介于BGDSGD之间 - 代码调整: ```python batch_size = 64 epoch_losses = [] for epoch in range(epochs): for batch in range(0, m, batch_size): # 参数更新使用小批量... epoch_loss = compute_loss(X, y, theta) # 全量损失 epoch_losses.append(epoch_loss) ``` #### 关键注意事项 1. **损失计算一致性**: - 对比曲线时,纵轴必须使用**相同数据集**(推荐全量训练集)计算的损失[^1][^2] - 避免混合使用批次损失和全量损失 2. **噪声处理**: - 对SGD/MBGD可使用移动平均平滑曲线 ```python # 窗口大小为10的移动平均 smoothed_losses = np.convolve(losses, np.ones(10)/10, mode='valid') ``` 3. **收敛判定标记**: - 在图中标注收敛点(如损失变化<0.001时) ```python convergence_iter = np.where(np.abs(np.diff(losses)) < 1e-5)[0][0] plt.axvline(x=convergence_iter, color='r', linestyle='--') ``` 4. **多算法对比**: - 使用相同坐标尺度 - 标注关键差异点(如SGD的震荡幅度) #### 示例输出效果 横坐标为迭代次数(BGD)或epoch数(SGD/MBGD),纵坐标为损失值: - BGD曲线:平滑递减的指数曲线 - SGD曲线:高频震荡但整体下降的锯齿线 - MBGD曲线:低频震荡的阶梯状下降曲线 > 收敛曲线直观揭示了算法的稳定性与效率:BGD最稳定但计算成本高,SGD高效但波动大,MBGD是实用折中方案[^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值