稳健协方差估计与马氏距离的相关性

在统计学中,对于高斯分布的数据,可以通过计算马氏距离来衡量一个观测值与分布模式之间的距离。马氏距离的计算公式为:

d_{(\mu,\Sigma)}(x_i)^2 = (x_i - \mu)^T\Sigma^{-1}(x_i - \mu)

其中,\(\mu\) 和 \(\Sigma\) 分别代表数据的均值和协方差矩阵。在实际应用中,通常使用估计值来代替真实的 \(\mu\) 和 \(\Sigma\)。然而,标准的协方差最大似然估计(MLE)对数据集中的异常值非常敏感,这同样会影响基于MLE的马氏距离的准确性。因此,使用稳健的协方差估计方法,如最小协方差行列式(MCD)估计器,可以提高对数据集中错误观测的抵抗力,并更准确地反映观测的真实结构。

最小协方差行列式(MCD)估计器是一种稳健的协方差估计方法,它能够在高度污染的数据集中估计协方差矩阵,即使数据集中存在多达 \(\frac{n_{\text{samples}}-n_{\text{features}}-1}{2}\) 个异常值。MCD的核心思想是找到 \(\frac{n_{\text{samples}}+n_{\text{features}}+1}{2}\) 个观测值,使得它们的样本协方差行列式最小,从而得到一个“纯净”的观测子集,用于计算位置和协方差的标准化估计。MCD由P.J.Rousseuw首次提出。

本例展示了马氏距离如何受到异常数据的影响。当使用基于标准协方差MLE的马氏距离时,从污染分布中抽取的观测值与来自真实高斯分布的观测值无法区分。而使用基于MCD的马氏距离时,这两个群体变得可以区分。相关应用包括异常值检测、观测值排序和聚类。

数据生成

首先,生成了一个包含125个样本和2个特征的数据集。两个特征都是以0为均值的高斯分布,其中特征1的标准差为2,特征2的标准差为1。接下来,用标准差分别为1和7的高斯异常样本替换了25个样本。

import numpy as np # 为了一致的结果 np.random.seed(7) n_samples = 125 n_outliers = 25 n_features = 2 # 生成形状为(125, 2)的高斯数据 gen_cov = np.eye(n_features) gen_cov[0, 0] = 2.0 X = np.dot(np.random.randn(n_samples, n_features), gen_cov) # 添加一些异常值 outliers_cov = np.eye(n_features) outliers_cov[np.arange(1, n_features), np.arange(1, n_features)] = 7.0 X[-n_outliers:] = np.dot(np.random.randn(n_outliers, n_features), outliers_cov)

结果比较

接下来,对数据拟合了基于MCD和MLE的协方差估计器,并打印了估计的协方差矩阵。注意到,基于MLE的估计器估计的特征2的方差(7.5)比基于MCD的稳健估计器(1.2)高得多。这表明,基于MCD的稳健估计器对异常样本的抵抗力更强,这些异常样本被设计为在特征2上具有更大的方差。

import matplotlib.pyplot as plt from sklearn.covariance import EmpiricalCovariance, MinCovDet # 拟合数据的MCD稳健估计器 robust_cov = MinCovDet().fit(X) # 拟合数据的MLE估计器 emp_cov = EmpiricalCovariance().fit(X) print("估计的协方差矩阵:\nMCD (稳健):\n{}\nMLE:\n{}".format(robust_cov.covariance_, emp_cov.covariance_))

为了更直观地展示差异,绘制了两种方法计算的马氏距离的等高线图。注意,基于稳健MCD的马氏距离更贴合内部黑点,而基于MLE的距离更受异常红点的影响。

最后,强调了基于MCD的马氏距离在区分异常值方面的能力。取马氏距离的立方根,得到近似正态分布(如Wilson和Hilferty所建议),然后使用箱线图绘制内部样本和异常样本的值。对于基于稳健MCD的马氏距离,异常样本的分布与内部样本的分布更加分离。

# 计算样本的MLE马氏距离的立方根 emp_mahal = emp_cov.mahalanobis(X - np.mean(X, 0))**(1/3) # 绘制箱线图 plt.boxplot([emp_mahal[:-n_outliers], emp_mahal[-n_outliers:]], widths=0.25) # 绘制个别样本 plt.plot(np.full(n_samples-n_outliers, 1.26), emp_mahal[:-n_outliers], "+k", markeredgewidth=1) plt.plot(np.full(n_outliers, 2.26), emp_mahal[-n_outliers:], "+k", markeredgewidth=1) plt.show()
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485