基于y=x²函数的随机梯度下降(SGD)与梯度下降(GD)差异咨询
针对y=x²示例下GD与SGD差异的疑问解答
问题1:现有GD实现中的「全量数据点」具体指什么
你给出的gradient_descent是通用的无约束数值优化实现,和机器学习场景下基于数据集优化损失函数的GD可以对应理解:
- 常规机器学习场景中,损失函数是所有训练样本损失的平均值,经典GD计算梯度时会用到全部训练样本,这里的「全量数据点」就是所有参与训练的样本
- 回到你用的y=x²极简示例:这个场景下的梯度表达式
2x本身已经是全量信息聚合后的结果,如果要对应到带数据集的场景,有两种等价的理解:- 你的训练集只有1个样本,全量数据就是这个唯一的样本,计算梯度自然不需要额外遍历
- 你已经提前把所有样本的梯度做了平均,最终合并出了
2x这个统一的梯度计算式,此时「全量数据点」就是计算这个平均梯度时用到的全部样本
另外提一个小笔误:你给出的调用代码里lambda入参是v,梯度表达式应该写lambda v: 2 * v,否则会报变量x未定义的错误。
问题2:如何改造现有函数实现SGD
你现有的GD实现里没有预留数据集输入、单样本梯度计算的逻辑,所以找不到对应「单个数据点」的位置:原函数的gradient参数直接返回的是全量梯度,没有和单样本做绑定。
改造思路
- 给函数增加训练集(特征数组X、标签数组y)作为入参
- 把原
gradient参数调整为单样本梯度计算函数,接收当前参数值、单样本特征、单样本标签三个入参 - 每次迭代时随机抽取1个训练样本,用这个样本的梯度更新参数,替换原有的全量梯度计算逻辑
改造后的SGD代码示例
import numpy as np def stochastic_gradient_descent( sample_gradient, X, y, start, learn_rate, n_iter=50, tolerance=1e-06 ): vector = start n_samples = len(X) for _ in range(n_iter): # 随机抽取单个样本 random_idx = np.random.randint(0, n_samples) x_i, y_i = X[random_idx], y[random_idx] # 用单样本计算梯度 diff = -learn_rate * sample_gradient(vector, x_i, y_i) if np.all(np.abs(diff) <= tolerance): break vector += diff return vector
调用示例(贴合你的y=x²场景)
我们模拟一个简单的训练任务:拟合函数y = w * x,训练集的标签满足y_i = x_i²,最终优化得到的w会接近真实值2,和你原示例的优化目标对齐:
# 构造训练集,y_i = x_i² X = np.array([1, 2, 3, 4, 5]) y = np.array([1, 4, 9, 16, 25]) # 单样本梯度计算:MSE损失对w的梯度为 2*(w*x_i - y_i)*x_i sample_grad = lambda w, x, y: 2 * (w * x - y) * x # 调用SGD函数 print(stochastic_gradient_descent(sample_grad, X, y, start=10.0, learn_rate=0.01, n_iter=1000))
内容的提问来源于stack exchange,提问作者nuclear_engineer
相关产品推荐
相关产品推荐

