调整matplotlib中协方差轮廓绘图示例时出现奇异矩阵错误
clf.fit(X)
为了评估数据,我想调整一下这个例子中的等高线图:这个例子。我有点搞不懂例子中的那些线是用来干嘛的:
X1 = 0.3 * np.random.randn(0.5 * n_inliers, 2) - offset
X2 = 0.3 * np.random.randn(0.5 * n_inliers, 2) + offset
为什么会有两列?还有为什么有两个X?我觉得之所以有两个X,是因为有偏移。我假设这两列各自代表一组数据:就像散点图一样,我想这可能意味着:第一列可能是电机的转速(MotorRpm),第二列可能是电机的电流(MotorCurrent),我想到了这个:(getSeries
是一个从数据框中提取某一列的函数)
ser1 = getSeries("MotorRpm") # type pandas.Series, kind of numpy.array
ser2 = getSeries("MotorCurrent")
blub = []
for i in range(len(ser1)):
blub.append([ser1.ix[i], ser2.ix[i]])
length = len(blub)
if length%2==1:
blub.pop(length-1) # make list even
X1 = blub[:length/2]
X2 = blub[length/2:]
但是这会抛出一个错误:ValueError: Singular covariance matrix. Please check that the covariance matrix corresponding to the dataset is full rank and that MinCovDet is used with Gaussian-distributed data (or at least data drawn from a unimodal, symmetric distribution.
在例子中的这一行。这种情况也发生在我想检查每个X的作用时,把随机数改成全是1。我知道什么是奇异矩阵,但不知道fit
内部是干什么的。如果这个例子在适应真实数据方面如此有限,那它除了看起来不错还有什么实际用途呢?
编辑:看来这个警告适用于我的情况(MinCovDet(EmpiricalCovariance)
):
The Minimum Covariance Determinant covariance estimator is to be applied
on Gaussian-distributed data, but could still be relevant on data
drawn from a unimodal, symmetric distribution. It is not meant to be used
with multi-modal data (the algorithm used to fit a MinCovDet object is
likely to fail in such a case).
One should consider projection pursuit methods to deal with multi-modal
datasets.
2 个回答
EllipticEnvelope 是一种用来估算数据的协方差并检测异常值的方法,它使用了一种叫做最小协方差确定(Minimum Covariance Determinate,简称 MinCovDet)的技术。不过,目前这个 MinCovDet(快速 MCD,FastMCD)的实现有个 bug。我查看了它的代码,发现它没有处理一种特殊情况,就是当协方差矩阵是奇异的(也就是无法逆的)。这种情况可能发生在你的数据中有一部分点都在同一条直线上(在二维情况下就是这样)。如果你的数据正好是这种情况,你可以尝试用另一种方法:告诉 EllipticEnvelope 不要使用 MinCovDet,而是用它提供的另一种算法。我没有检查过那种算法,不确定它是否也使用了快速 MCD,但你可以试试看是否有效——在 EllipticEnvelope 中添加一个选项 assume_centered=True,像这样:
EllipticEnvelope(contamination=.1, assume_centered=True)
下面是它的功能描述(来自 sklearn 文档):
assume_centered : Boolean
If True, the support of robust location and covariance estimates is computed, and a
covariance estimate is recomputed from it, without centering the data. Useful to work
with data whose mean is significantly equal to zero but is not exactly zero. If False,
the robust location and covariance are directly computed with the FastMCD algorithm
without additional treatment.
关于为什么会有两列的这个问题,答案在下面的示例代码中:
X1 = 0.3 * np.random.randn(0.5 * n_inliers, 2) - offset
X2 = 0.3 * np.random.randn(0.5 * n_inliers, 2) + offset
X = np.r_[X1, X2]
# Add outliers
X = np.r_[X, np.random.uniform(low=-6, high=6, size=(n_outliers, 2))]
这段代码的作用是通过使用 numpy.r_
将三个包含两列的数组垂直叠加在一起。数组的第一部分包含一些点,这些点相对于中心的位置要么是 (offset,offset)
,要么是 (-offset,-offset)
。数组的第三部分则包含完全偏离中心的点。
这意味着其实你在不同的列中有不同的轴。所以,你需要从自己的数据中构建一个 Nx2 的数组。如果你的 getSeries
返回的是 ndarray
或 pandas.Series
,那么可以用下面的代码:
X = np.column_stack((getSeries("MotorRPM"), getSeries("MotorCurrent")))
完成这个后,检查一下 X.shape
是否返回 (123,2)
(当然这里的 123
是其他的数字)。这样应该会让 clf.fit
更顺利一些。
如果你在代码上还有其他问题,请编辑你的提问,展示一下你做了哪些工作。