手动用For循环实现逻辑回归SGD是否正确?附绘图疑问
逻辑回归SGD实现问题解答
问题1:lambda_min是否为损失值?
你的lambda_min设计意图是记录迭代过程中最小的损失值,但代码存在两处错误导致它无法正确反映真实损失:
- 变量名
lambda是Python关键字,不能用作变量名,建议改为loss; - 损失函数计算错误:公式中
(1+yy)应为(1-yy),否则逻辑完全颠倒,且你用了全局张量x而非当前batch的xx,导致维度不匹配、计算结果错误。
修正后,lambda_min(建议重命名为min_loss)可以作为迭代过程中出现的最小损失值,但它不是当前batch的实时损失,只是一个记录用的变量。
问题2:参数更新方式是否正确?
完全错误,核心问题如下:
- 没有计算损失对参数的梯度:SGD需要的是损失的梯度
∇λ,而非损失值本身; - 参数更新时直接赋值
w2 = w1 - ...会破坏PyTorch的梯度追踪机制,导致后续无法计算梯度; - 未清空梯度:每次反向传播后梯度会累积,必须手动清空;
- 损失函数符号错误:负对数似然损失需要取负才能作为最小化目标(原公式的求和结果为负数,取负后转为正数,符合损失越小越好的直观逻辑)。
修正后的核心代码片段
import torch # 数据准备(修正split后的变量名,保留原始数据用于后续绘图) some_data = torch.rand(1000, 2) x = some_data[:, 0] y = (x + 0.4 * some_data[:, 1] > 0.5).to(torch.int) x_batches = torch.split(x, 3) y_batches = torch.split(y, 3) # 初始化参数,保留梯度追踪 w1 = torch.autograd.Variable(torch.tensor([0.1]), requires_grad=True) w2 = torch.autograd.Variable(torch.tensor([0.1]), requires_grad=True) alpha = 0.01 # 学习率 min_loss = float('inf') # 初始化为无穷大,记录最小损失 for epoch in range(10): total_loss = 0.0 for xx, yy in zip(x_batches, y_batches): # 使用当前batch的xx计算预测概率 p_x = 1 / (1 + torch.exp(-w1 - w2 * xx)) # 修正负对数似然损失计算 loss = -torch.sum(yy.float() * torch.log(p_x) + (1 - yy.float()) * torch.log(1 - p_x)) # 反向传播计算梯度 loss.backward() # 在无梯度上下文更新参数,避免破坏梯度追踪 with torch.no_grad(): w1 -= alpha * w1.grad w2 -= alpha * w2.grad # 清空梯度,避免累积 w1.grad.zero_() w2.grad.zero_() total_loss += loss.item() # 更新最小损失记录 if loss.item() < min_loss: min_loss = loss.item() print(f"Epoch {epoch+1}, Average Loss: {total_loss/len(x_batches):.4f}, Min Loss: {min_loss:.4f}")
问题3:绘制包含0/1样本点的逻辑回归曲线
使用matplotlib即可实现,需要将PyTorch张量转换为NumPy数组,步骤如下:
import matplotlib.pyplot as plt # 获取原始数据的NumPy格式 x_np = x.numpy() y_np = y.numpy() # 生成用于绘制曲线的x值范围(覆盖数据分布区间) x_plot = torch.linspace(0, 1, 100) # 用训练好的参数计算对应的预测概率 with torch.no_grad(): p_plot = 1 / (1 + torch.exp(-w1 - w2 * x_plot)) # 转换为NumPy数组用于绘图 x_plot_np = x_plot.numpy() p_plot_np = p_plot.numpy() # 绘制样本点(区分0/1类) plt.scatter(x_np[y_np == 0], y_np[y_np == 0], label='类别0', alpha=0.5, s=10) plt.scatter(x_np[y_np == 1], y_np[y_np == 1], label='类别1', alpha=0.5, s=10) # 绘制逻辑回归拟合曲线 plt.plot(x_plot_np, p_plot_np, 'r-', label='逻辑回归拟合') plt.xlabel('x') plt.ylabel('预测概率p(x)') plt.legend() plt.show()
内容的提问来源于stack exchange,提问作者user10443249
相关产品推荐
相关产品推荐

