使用nls函数进行正系数约束回归时遇错误的求助
问题原因与解决方案
错误原因分析
- 第一个错误:
nls不支持lm风格的.自动展开自变量。它需要显式定义每个待拟合的参数与变量的关系,否则无法识别需要估计的参数,导致起始值匹配失败。 - 第二个错误:你的数据中x1-x5完全共线(均为
seq(10)),导致模型矩阵奇异,触发QR分解的维度错误;同时用nls拟合线性约束回归并非最优选择,更适合用专门的非负最小二乘工具。
解决方案
方法一:用nnls包做非负最小二乘(推荐,高效直接)
对于线性回归且要求系数非负的场景,nnls包是专门的解决方案,比nls更高效稳定:
library(nnls) library(magrittr) # 构造非共线数据(避免完全共线导致的错误) X <- data.frame( x1 = seq(10), x2 = seq(10) + rnorm(10), x3 = seq(10) + rnorm(10), x4 = seq(10) + rnorm(10), x5 = seq(10) + rnorm(10), y = seq(10) + rnorm(10) ) # 转换为模型矩阵和响应向量 X_mat <- X %>% dplyr::select(-y) %>% as.matrix() y_vec <- X$y # 拟合非负最小二乘 fit_nnls <- nnls(X_mat, y_vec) # 查看结果 fit_nnls$x # 非负系数 sum((y_vec - X_mat %*% fit_nnls$x)^2) # 残差平方和
方法二:修正nls的用法(适合非线性场景,线性场景不推荐)
如果一定要用nls,需要显式定义参数并避免数据共线:
library(magrittr) # 构造非共线数据 X <- data.frame( x1 = seq(10), x2 = seq(10) + rnorm(10), x3 = seq(10) + rnorm(10), x4 = seq(10) + rnorm(10), x5 = seq(10) + rnorm(10), y = seq(10) + rnorm(10) ) # 生成带显式参数的公式(如a1*x1 + a2*x2...) var_names <- X %>% dplyr::select(-y) %>% names param_names <- paste0("a", seq_along(var_names)) formula_str <- paste("y ~", paste(paste(param_names, var_names, sep="*"), collapse=" + "), "-1") f <- as.formula(formula_str) # 设置起始值、上下界(需与参数名一一对应) start <- setNames(rep(0, length(var_names)), param_names) lower <- start upper <- setNames(rep(Inf, length(var_names)), param_names) # 拟合nls fit_nls <- nls(formula = f, data = X, start = start, lower = lower, upper = upper, algorithm = "port" ) # 查看结果 summary(fit_nls)
内容的提问来源于stack exchange,提问作者Frank
相关产品推荐
相关产品推荐

