我想在 R 中执行加权非负最小二乘法(即所有拟合系数 >=0 的约束)。nnls
包中的函数似乎nnls
不支持权重。我是否正确,我可以通过将协变量矩阵和因变量乘以向量的平方根weights
来在函数内进行模拟,正如此处所示?或者有更好的方法来做到这一点吗?nnls
X
y
weights
1) nnls是的,它是等价的,因为加权最小二乘最小化:
sum( w * (Y - X %*% beta)^2 )
= sum_i( (sqrt(w[i]) * X[i, ] %*% beta - sqrt(w[i]) * Y[i])^2 )
Run Code Online (Sandbox Code Playgroud)
受约束,其中 sum_i 表示 i 上的总和。因此sqrt(w[i])
将 X 的第 i 行与 Y 的第 i 个元素相乘,相当于使用 sqrt(w) * X
和sqrt(w) * Y
。(请注意,它们也分别等于diag(sqrt(w)) %*% X
和c(diag(sqrt(w)) %*% Y)
。)
2)CVXR CVXR包可以直接做加权非负最小二乘。在其小插图中有一个执行非负最小二乘的示例。
vignette("cvxr_intro")
Run Code Online (Sandbox Code Playgroud)
只需更改代码中的目标即可添加权重:
objective <- Minimize(sum((w *(Y - X %*% betaHat)^2)))
Run Code Online (Sandbox Code Playgroud)
nls
3)如果你使用下界全为0的算法,R自带的nlsport
可以做非负加权最小二乘。(在下面的代码中,我们从零开始,通常从边界开始不是一个好主意但考虑到这里的线性,这实际上并不重要。)
zeros <- numeric(ncol(X))
nls(Y ~ X %*% b, start = list(b = zeros), weights = w, lower = zeros, alg = "port")
Run Code Online (Sandbox Code Playgroud)
运行所有三种方法来仔细检查答案。