【问题标题】:Calculating error in PCAPCA 中的计算误差
【发布时间】:2017-03-30 18:58:20
【问题描述】:

我有一个关于我在做 PCA 时没有预料到的结果的问题。

我已经使用参考数据成功计算了主成分,然后作为检查以确保正在发生的事情是我认为正在发生的事情,我将参考数据投影到其特征函数的整个基础上(保留所有组件)然后转换回来,(这是在 python 中,所以它是 pca.fit(ref_data) 后跟 ref_data_transform =pca.transform.(ref_data) 后跟 pca.inverse_transform(ref_data_transform) 我得到完全相同的数据。这不是一个惊喜。

同样不足为奇的是,随着我选择的主成分越来越少,原始数据与已投影到较小基础上然后再投影回来的数据之间的点对点差异会增加。也就是说,如果您绘制原始数据和“过滤”数据,它看起来会有所不同,随着您减少要投影的子空间的大小,差异会增加。我可以在一个向量中捕获每个数据点之间的差异,例如,difference_vec。

令我感到惊讶的是(至少对我而言)是,当我对任何一列 difference_vec 求和时,它总是等于零。也就是说,当我投影到越来越小的子空间时,任何原始数据点与被一些主成分过滤的相应数据点之间的实际差异会变大,但总误差始终为零。

如果我在这里犯了一些错误,我非常感谢我的任何见解,如果没有,为什么这个以前的“投影引发的错误”指标不起作用。

谢谢。

【问题讨论】:

  • 非常巧妙的问题,我不确定为什么 sum(ref_data - inv_data) 的结果为零——可能是 math.stackexchange.com 的问题。在比较这样的矩阵时,我使用矩阵范数,即numpy.linalg.norm(它将选择 Frobenius 范数)。在这种情况下,norm(ref_data - inv_data) 肯定不会为零。但为什么sum 为零仍然是一个有趣的问题。

标签: linear-algebra pca


【解决方案1】:

发生这种情况是因为 ref_data 和我将称之为 inv_data = pca.inverse_transform(pca.transform(ref_data)) 的均值相同(沿第二维计算,即对样本进行平均)。

要查看此内容,请查看transform 的代码:

transform = lambda X: dot(X - mu, V.T)

inverse_transform 可以定义为:

inverse_transform = lambda X: dot(X, V) + mu

其中muref_data 的平均值,Vcovariance(ref_data) 的第一个N 特征向量。

因此,如果您遵循数据链及其均值:

  1. ref_data 与平均 mu;
  2. transform(ref_data) 的平均值为 0(参见上面的等效定义:X-mu 的平均值为零,然后将结果线性投影到某个坐标参考上只会旋转/剪切/翻转那些零均值点,不会改变它们的平均值;李>
  3. 最后,inv_data = inverse_transform(transform(ref_data)) 添加了mu,所以它有mu-mean;

你看到ref_datainv_data都意味着mu

最后,sum(ref_data - inv_data) 可以看作sum(mean(ref_data - inv_data) * num_samples),通过线性简化为sum(mu - mu),即为 0。

这是很多话,对不起,但现在我看到了这个想法,真的很简单。正如我在评论中提到的,在这种情况下,您想使用矩阵范数(如 Frobenius 范数)来测量两个矩阵之间的距离,而不仅仅是sum(A - B)?!


示例代码:

import numpy as np
from sklearn.decomposition import PCA

ref_data = np.random.randn(20, 3)
pca = PCA(n_components=1)
pca.fit(ref_data)
trans_data = pca.transform(ref_data)
inv_data = pca.inverse_transform(trans_data)

np.mean(inv_data, 0)   # array([ 0.03664149,  0.51348007,  0.0360179 ])
np.mean(ref_data, 0)   # array([ 0.03664149,  0.51348007,  0.0360179 ])
np.mean(trans_data, 0) # array([ -2.49800181e-17]) meanwhile ...
np.sum(inv_data - ref_data) # -1.3877787807814457e-15 !

【讨论】:

  • 啊,我明白了!非常感谢您的洞察力!我假设随着我保留的组件越来越少,Frobenius 范数会越来越大,对吗?这是否使它成为使用 PCA 测量偏差(例如,异常检测)的有用方法?也就是说,我可以使用 (Ref_data-projecteced_test_data) 的规范来确定测试数据离 PC 有多“远”?再次感谢您的建议。
  • “随着我保留的组件越来越少,Frobenius 范数会变得越来越大”——我的说法略有不同:范数不应该随着你使用更少的组件而减少。它可能会趋于平稳,也就是说,如果您有低秩数据,那么奇异值将逐渐减小到 0,因此范数也可能停止增长。 (我在这里使用了很多行话,如果这令人困惑,请告诉我,我可以通过代码示例进行澄清。)
  • 是的,您可以尝试使用 PCA 进行异常检测。 PCA/ICA/等的问题。是它们只能捕获线性特征,因此您的测试数据中的遮挡、异常值等问题确实会出现问题。所以人们开发了“robust PCA” (see references therein)——计算量更大,但对异常检测更有用。不过,也许您的数据是线性的,值得一试?。
  • 对于白化的 PC,Frobenius 范数是否可以用作异常检测的指标?它似乎提供了有关投影参考矩阵和投影测试矩阵之间差异的总体信息,但是有更具体的吗?即,如果我将投影测试数据的每一列的分量相加,这个和是否代表 PC 空间中的测试向量与超球体中心的距离?这听起来像是一种确定哪些投影特征态异常(给定距离阈值)而不是整个批次的方法。
  • 我猜 Frobenius 范数给出了测试数据中被主向量捕获的变异性的度量。我不确定是否有任何方法可以告诉哪个主向量被某些测试数据“违反”了,但它可能值得一试。
猜你喜欢
  • 1970-01-01
  • 2012-01-23
  • 2016-07-19
  • 1970-01-01
  • 2012-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-04
相关资源
最近更新 更多