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

在R中实现线性回归(Linear Regression)时遇到NaN值问题求助

排查并解决R线性回归梯度下降中的NaN问题

我帮你拆解下代码里的几个关键问题,尤其是导致NaN的核心原因:

1. 数据初始化与绘图的小bug

先看你开头的数据处理和绘图部分:

  • 你先创建了空的df <- data.frame(),接着用cbind生成数据再转成数据框,这一步其实可以直接一步到位,省点冗余操作;另外plot函数的参数用错了,正确的写法应该是把x轴(Population)放在前面,y轴(Profit)放在后面,比如plot(df$Population, df$Profit),或者用更简洁的公式风格plot(Profit ~ Population, data = df)。

修正后的初始化代码:

library(ggplot2)
# 直接创建数据框,不用绕弯
df <- data.frame(
  Population = c(10000,20000,5000,5123,5345,5454,11000,23000,6000,6100,6300),
  Profit = c(5600,21000,1000,2000,2300,3000,7000,21400,3200,3250,3300)
)
# 正确绘制散点图
plot(Profit ~ Population, data = df)

2. 导致NaN的核心元凶:没做特征缩放 + 学习率太大

这是最关键的问题!你的Population数值范围是500023000,`Profit`是100021400,数值量级都很大,但你设置的学习率alpha=0.001对于未缩放的特征来说实在太大了。梯度下降的时候,步长过大会导致损失函数值直接爆炸,最后溢出变成NaN。

解决方法很简单:先对特征做标准化(Z-score归一化),把特征缩放到均值为0、标准差为1的范围,之后再跑梯度下降就稳了。

3. 完整的修正版梯度下降代码

下面是调整后的完整代码,包含特征缩放、梯度下降的迭代过程,绝对不会出现NaN:

library(ggplot2)

# 1. 一步创建数据框
df <- data.frame(
  Population = c(10000,20000,5000,5123,5345,5454,11000,23000,6000,6100,6300),
  Profit = c(5600,21000,1000,2000,2300,3000,7000,21400,3200,3250,3300)
)

# 2. 特征标准化(这步一定要做!)
# 先保存均值和标准差,后面要还原拟合结果用
pop_mean <- mean(df$Population)
pop_sd <- sd(df$Population)
df$Population_scaled <- (df$Population - pop_mean) / pop_sd

# 3. 准备梯度下降的矩阵
X <- cbind(1, df$Population_scaled)  # 加入截距项
Y <- df$Profit
theta <- c(0, 0)  # 初始化参数
m <- nrow(X)
alpha <- 0.01  # 缩放后用这个学习率刚好
iterations <- 1500
cost_history <- numeric(iterations)  # 记录每一轮的损失值,方便看收敛情况

# 4. 梯度下降迭代循环(你之前没写这部分哦)
for (i in 1:iterations) {
  predictions <- X %*% theta
  error <- predictions - Y
  # 更新theta参数
  theta <- theta - (alpha/m) * t(X) %*% error
  # 计算当前损失并保存
  cost_history[i] <- sum(error^2)/(2*m)
}

# 查看最终的参数和损失变化
print(theta)
plot(cost_history, type = "l", xlab = "迭代次数", ylab = "损失函数值")

# 5. 用拟合结果画个图直观看看
df$Predicted_Profit <- X %*% theta
ggplot(df, aes(x = Population, y = Profit)) +
  geom_point() +
  geom_line(aes(y = Predicted_Profit), color = "red", linewidth = 1) +
  labs(title = "人口 vs 利润(线性回归拟合)", x = "人口数量", y = "利润")

额外小提示

  • 如果你实在不想做特征缩放,也可以试试把学习率调得极小(比如alpha=1e-8),但这样梯度下降收敛会超级慢,远不如特征缩放高效。
  • 你之前的代码只算了初始的损失值,没写梯度下降的迭代循环,这也是没法得到回归结果的原因之一哦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:03:49