You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实现逻辑回归随机梯度下降时theta值异常问题排查

你的逻辑回归SGD为啥theta没更新?

看起来你遇到的问题是theta完全没变化,和初始值一致——这说明你的梯度更新步骤根本没生效,大概率是实现细节出了问题,我帮你梳理几个最常见的坑:

1. 梯度计算逻辑错了

逻辑回归的SGD,单个样本的梯度公式是:gradient = (h(x_i) - y_i) * x_i,其中h(x_i)是sigmoid函数的输出(1/(1+exp(-theta%*%x_i)))。如果这里漏乘了x_i,或者sigmoid实现错误(比如符号写错、函数表达式出错),会导致梯度为0或者无效,theta自然不动。

2. 特征没做归一化,学习率又太小

SGD对特征尺度特别敏感,如果你的特征数值范围差异很大(比如一个特征是0-1,另一个是1000-2000),再加上你用的alpha=0.0009这么小的学习率,梯度更新的幅度会小到可以忽略,看起来theta就没变化。先试试把所有特征做标准化(比如(x - mean(x))/sd(x)),再调大学习率(比如0.01、0.1)试试。

3. 迭代循环的逻辑有问题

你贴的代码没写完(theta <- seq(from = 0, to = 1, len...),但很可能是循环里的坑:

  • 是不是每次循环都重新初始化了theta?比如把theta <- seq(...)放在循环里面,那每次迭代都会重置回初始值,等于白算
  • 有没有真正遍历每个样本,并且在每个样本后执行theta = theta - alpha * gradient的更新?
  • 有没有给数据加截距项?逻辑回归需要截距项(X的第一列全1),不然拟合会有偏差

给你一个可参考的正确实现

# 先实现sigmoid函数
sigmoid <- function(z) {
  1 / (1 + exp(-z))
}

train <- function(data, labels, alpha = 0.01, num_epochs = 100) {
  # 给数据添加截距项(必须!)
  X <- cbind(rep(1, nrow(data)), data)
  m <- nrow(X)  # 样本数
  n <- ncol(X)  # 特征数(含截距)
  
  # 初始化theta,用全0或者小随机数都行
  theta <- rep(0, n)
  
  for (epoch in 1:num_epochs) {
    # SGD的关键:每次迭代前打乱样本顺序,避免顺序影响
    shuffle_idx <- sample(1:m, m)
    X_shuffled <- X[shuffle_idx, ]
    y_shuffled <- labels[shuffle_idx]
    
    # 遍历每个样本更新theta
    for (i in 1:m) {
      x_i <- X_shuffled[i, ]
      y_i <- y_shuffled[i]
      # 计算当前样本的预测值
      h_i <- sigmoid(t(theta) %*% x_i)
      # 计算梯度
      grad <- (h_i - y_i) * x_i
      # 更新theta
      theta <- theta - alpha * grad
    }
  }
  return(theta)
}

你可以对照这个代码检查自己的实现:

  • 有没有加截距项?
  • sigmoid函数是不是正确?
  • 梯度计算和theta更新的步骤是不是对应?
  • 是不是在每个样本迭代后都更新了theta?

如果还是搞不定,把完整的代码贴出来,我帮你揪出具体问题~

内容的提问来源于stack exchange,提问作者Jatt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:25:29