【机器学习】案例2.4——优化后的随机梯度下降,确保所有样本都被随机遍历
·
# 导入numpy库,用于数值计算(矩阵操作、随机数生成、索引打乱等)
import numpy as np
# ===================== 1. 构造模拟数据集 =====================
# 生成特征矩阵X:100个样本,每个样本1个特征,取值为[0,2)的均匀随机数
X = 2 * np.random.rand(100, 1)
# 构造标签y:模拟真实线性关系 y = 4(截距) + 3*X(特征系数) + 标准正态分布噪声
# 噪声让数据更贴近真实场景,避免完全线性的理想情况
y = 4 + 3 * X + np.random.randn(100, 1)
# 给特征矩阵拼接偏置项(对应模型截距w0):每一行前加1,形状变为(100,2),方便计算 w0*1 + w1*X
X_b = np.c_[np.ones((100, 1)), X]
# ===================== 2. 设置SGD的超参数 =====================
n_epochs = 10000 # 训练轮数(epoch):每轮会“完整遍历一次所有样本”
m = 100 # 总样本数量
learning_rate = 0.001 # 学习率:控制参数更新的步长
# ===================== 3. 初始化模型参数 =====================
# 初始化参数theta:包含2个值(w0:截距,w1:X的系数),用标准正态分布随机生成初始值
theta = np.random.randn(2, 1)
# ===================== 4. 优化版SGD核心迭代(确保所有样本被随机遍历) =====================
for epoch in range(n_epochs): # 遍历每一轮训练
# ---------------- 优化点:每轮开始前打乱样本索引,保证样本随机遍历 ----------------
# 生成X_b的索引数组(0~99,对应100个样本的原始顺序)
arr = np.arange(len(X_b))
# 打乱索引数组:让样本顺序随机化(核心优化!解决原始SGD重复/遗漏样本的问题)
np.random.shuffle(arr)
# 按照打乱后的索引,重新排列特征矩阵X_b(保证特征顺序和标签对应)
X_b = X_b[arr]
# 按照同样的打乱索引,重新排列标签y(特征与标签的对应关系不被破坏)
y = y[arr]
# 遍历当前轮的所有样本(因为索引已打乱,所以是“随机顺序遍历所有样本”)
for i in range(m):
# 取出当前(随机顺序的)第i个样本的特征(形状:(1,2))
xi = X_b[i:i+1]
# 取出当前样本对应的标签(形状:(1,1))
yi = y[i:i+1]
# 计算“当前单个样本”对应的损失函数梯度(SGD的梯度是单样本梯度)
gradients = xi.T.dot(xi.dot(theta) - yi)
# 用单样本梯度更新参数theta:向梯度反方向移动(最小化损失)
theta = theta - learning_rate * gradients
# 打印最终学习到的参数theta
# 由于每轮都随机遍历了所有样本,结果会比原始SGD更稳定,更接近真实值[4,3]
print(theta)
更多推荐
所有评论(0)