sklearn.MinCovDet与numpy.cov协方差估计不一致原因探究
问题
我原本认为,从二元高斯总体抽取大样本时,sklearn.covariance.MinCovDet的协方差估计应与numpy.cov的结果一致。但通过以下代码测试后,发现MinCovDet的方差估计始终偏小,请问这是为什么?
测试代码:
import numpy import sklearn import sklearn.covariance from random import gauss N = 10000 print(f'\n{"MinCovDet":>12}|{"MLE":>12}') print(f'{"s_x":>6}{"s_y":>6}|{"s_x":>6}{"s_y":>6}\n') for ___ in range(16): X = numpy.array([[gauss() for _ in range(N)] for __ in range(2)]).T RC = sklearn.covariance.MinCovDet(assume_centered = True).fit(X).covariance_ C = numpy.cov(X.T) print(f'{RC[0,0]**.5:6.2f}{RC[1,1]**.5:6.2f}|{C[0,0]**.5:6.2f}{C[1,1]**.5:6.2f}') print(f'\n[using sklearn v{sklearn.__version__}]')
代码输出:
MinCovDet| MLE s_x s_y| s_x s_y 0.98 0.94| 1.02 0.99 0.95 0.94| 1.00 0.99 0.95 0.95| 1.00 0.99 0.94 0.96| 0.99 1.00 0.95 0.95| 0.99 0.99 0.96 0.95| 1.01 1.00 0.94 0.96| 1.00 1.00 0.96 0.95| 1.01 1.00 0.94 0.95| 0.99 1.01 0.95 0.93| 1.00 1.00 0.94 0.96| 0.99 1.00 0.95 0.97| 1.00 1.01 0.95 0.95| 1.00 0.99 0.96 0.95| 1.00 1.00 0.95 0.95| 1.00 1.00 0.96 0.94| 0.99 1.00 [using sklearn v1.5.0]
原因分析
这是因为MinCovDet的核心设计目标是鲁棒性——它专门用于在存在异常值的场景下,估计出不受异常值干扰的协方差矩阵。为了实现鲁棒性,它会执行以下关键步骤:
- 从样本中筛选出一个子集(默认是约50%的样本,由
support_fraction参数控制,默认值为0.5),这个子集被判定为最可能来自真实高斯分布的"干净"样本。 - 仅基于这个子集计算协方差矩阵,同时应用校正因子补偿子集估计的偏差,但这个校正因子是针对含异常值的场景优化的,并非为纯高斯分布设计。
而numpy.cov计算的是**最大似然估计(MLE)**的协方差,它会用到所有样本数据,在纯高斯分布的大样本下,MLE是无偏的,会收敛到真实协方差值。
你的测试中虽然是纯高斯样本,但MinCovDet依然遵循鲁棒流程,只使用部分样本计算协方差,再加上校正因子的特性,最终导致方差估计值系统性略小于MLE结果。
如果想让MinCovDet在纯高斯样本下接近MLE结果,可以将support_fraction参数设为1.0,这样它会使用全部样本计算,此时估计结果会和numpy.cov基本一致(但这样就失去了鲁棒性)。
内容的提问来源于stack exchange,提问作者Mathieu
相关产品推荐
相关产品推荐

