Julia最小二乘问题:LSMR解与闭式解为何均偏离真实β?
嘿,这事儿其实特别好理解!咱们来掰扯清楚为啥会出现这个情况:
核心原因:最小二乘解是「带噪声数据的最优估计」,不是「真实β的复刻」
你生成的y是真实的Xβ加上了高斯噪声的,而最小二乘的目标是找到一个β̂,让||Xβ̂ - y||²最小——这个目标是拟合带噪声的观测值,而不是还原你一开始设定的真实β。噪声的存在必然会让估计值和真实值之间产生偏差,这是统计估计的正常现象,不管用闭式解还是LSMR迭代算法,都会存在这个偏差。
你的验证方式太严格了
Julia里的≈运算符默认使用的相对容差是√eps()(大概1e-8级别),但因为噪声的影响,你的估计值和真实β的差异会远大于这个阈值,所以直接用≈判断自然会返回false。
正确的验证姿势
咱们可以换几种方式来验证结果是否合理:
验证闭式解和LSMR解是否一致
LSMR就是用来求解最小二乘问题的迭代算法,理论上它的结果应该和闭式解几乎完全一致(除了迭代精度的微小差异)。你需要注意的是,lsmr(X,y)返回的是一个元组,第一个元素才是解,所以要提取出来:lsmr_solution, = lsmr(X, y)。计算估计值和真实β的误差幅度
不用严格的相等判断,而是计算两者的均方误差或者范数误差,看看这个误差是否和你加入的噪声水平匹配(你加的噪声是Normal(0,0.1),误差应该在合理的统计范围内)。无噪声测试
如果把y改成完全无噪声的X*β,这时候估计值应该和真实β几乎完全一致,≈也会返回true,可以用来验证算法本身没问题。
修改后的验证代码示例
using Distributions: Normal using IterativeSolvers: lsmr using LinearAlgebra: norm # Settings n = 500 k = 50 # Generate data X = rand(Normal(0.0, 0.1), (n, k)) + rand(Normal(0.0, 0.2), (n, k)) β = randn(k) y = X * β + rand(Normal(0.0, 0.1), n) # Solutions closed_form_solution = (X'X) \ (X'y) lsmr_solution, = lsmr(X, y) # 提取迭代解 # 验证两个解是否一致(应该为true) println("闭式解和LSMR解是否接近? ", closed_form_solution ≈ lsmr_solution) # 计算误差幅度 println("真实β与闭式解的均方误差: ", mean((closed_form_solution - β).^2)) println("真实β与LSMR解的均方误差: ", mean((lsmr_solution - β).^2)) # 无噪声对照测试 y_no_noise = X * β closed_form_no_noise = (X'X) \ (X'y_no_noise) lsmr_no_noise, = lsmr(X, y_no_noise) println("\n无噪声时,真实β与闭式解是否一致? ", β ≈ closed_form_no_noise) println("无噪声时,真实β与LSMR解是否一致? ", β ≈ lsmr_no_noise)
运行这段代码你会发现:
- 有噪声时,两个估计解几乎完全一致,且误差在合理范围;
- 无噪声时,估计解和真实
β完美匹配,≈返回true。
额外补充:样本量和特征数的影响
你的设置里n=500,k=50,属于样本量远大于特征数的情况,这时候估计的偏差会相对较小。如果n和k接近甚至k>n,偏差会更大,但这都是统计估计的正常表现,不是算法的问题哦。
内容的提问来源于stack exchange,提问作者Physics_Student

