旋转PCA组件以均衡每个组件中的方差


9

我试图通过对数据集执行PCA并丢弃最后几台PC来降低数据集的维数和噪声。之后,我想在其余PC上使用一些机器学习算法,因此我想通过均衡PC的方差来标准化数据,以使算法更好地工作。

一种简单的方法是简单地将方差标准化为单位值。但是,第一台PC与原始数据集相比,包含的原始方差更多,而我仍然希望为其赋予更多的“权重”。因此,我想知道:是否有一种简单的方法可以拆分方差并与方差较小的PC共享?

另一种方法是将PC映射回原始特征空间,但是在那种情况下,维数也会增加到原始值。

我想最好使结果列保持正交,但这时没有必要。


1
不... varimax最大化荷载的平方方差之和,因此它试图使它们尽可能不相等。另外,为什么还要均衡分量?重点是在尽可能少的组件中捕获尽可能多的变化。

2
将组件分数标准化为单位方差不适合您吗?那为什么?您想要什么样的结果-除相等的方差外,结果列是否应不相关?
ttnphns

2
根据您的描述,它看起来非常像您想要简单地“封装”(降维的)数据。它通常是机器学习中的预处理步骤。为了实现它,您只需执行PCA,选择一些组件并对它们进行标准化。我猜有可能找到一个正交旋转(例如varimax),该旋转旋转标准化的分量,以使它们保持不相关,但解释的变异量完全相同。这是一个有趣的问题,我需要考虑一下。但是我从未见过这样做,绝对不是机器学习。
变形虫

2
顺便说一句,您希望在PCA之后应用“某些机器学习算法”吗?这可能是相关的。
变形虫2015年

1
请注意,如果您旋转标准PC,则距离根本不会改变!因此,对于任何后续的基于距离的算法,它实际上都没有关系。
变形虫2015年

Answers:


10

对我来说,还不是很清楚,您要问的是您真正需要的是什么:机器学习中一个常见的预处理步骤是降维+白化,这意味着进行PCA和标准化组件,仅此而已。但是,尽管如此,我还是将重点放在您的问题上,因为它更有趣。


为中心的n × d数据矩阵,其中数据点在行中,变量在列中。PCA达奇异值分解X = û 小号V听,说:ü ķ 小号 ķ V ķ其中执行所述维数降低我们只保留ķ组件。这些组件中的一个正交“旋转因子”意味着选择一个正交ķ × ķ矩阵[R ,并将其插入到分解:Xù ķ 小号 ķ VXñ×d

X=ü小号Vüķ小号ķVķ
ķķ×ķ[R这里
XUkSkVk=UkRRSkVk=n1UkRRotatedstandardized scoresRSkVk/n1Rotated loadings.
是旋转的标准化分量,第二项表示转置的旋转载荷。旋转后每个分量的方差由相应的载荷矢量的平方和得出。在旋转之前,它只是s 2 i /n-1。旋转后,还有其他事情。n1UkRsi2/(n1)

现在我们准备用数学术语来表达这个问题:给定非旋转载荷,求出旋转矩阵R,使旋转的载荷LR在每一列中具有相等的平方和。L=VkSk/n1RLR

让我们解决它。旋转后平方列总和等于的对角元素这是有道理的:根据该公式,旋转只是简单地重新分配了组件之间的方差,这些方差最初由s 2 i /n1给出。我们需要重新分配它们,以使它们都等于其平均值μ

(LR)L[R=[R小号2n-1个[R
s一世2/ñ-1个μ

我认为没有封闭的解决方案,实际上有许多不同的解决方案。但是,可以按顺序轻松地构建解决方案:

  1. 取第一个分量和第个分量。所述第一个具有方差σ 最大 > μ和最后一个具有方差σ 分钟 < μķσmax>μσ<μ
  2. 仅旋转这两个,以使第一个的方差等于。2D旋转矩阵仅取决于一个参数θ,因此很容易写下等式并计算必要的θ。事实上,- [R 2D = COS θ θ - θ COS θ和变换后的第一PC将获得方差COS 2 θ &CenterDot;&σ 最大 + 2 θ &CenterDot;&σ 分钟 = COS 2 θ &CenterDot;&σμθθ
    [R2D=cosθθ-θcosθ
    从中我们立即获得 COS 2 θ = μ - σ 分钟
    cos2θσmax+sin2θσmin=cos2θσmax+(1cos2θ)σmin=μ,
    cos2θ=μσminσmaxσmin.
  3. 现在完成第一个分量,它具有方差μ
  4. 继续进行下一对,选择方差最大的组件和方差最小的组件。转到#2。

(k1)R


S2/(n1)

(10000060000300001).
5
  1. 51+(105)=6

  2. 53+(65)=4

  3. 54+(61)=5

  4. 做完了

我编写了实现此算法的Matlab脚本(请参见下文)。对于此输入矩阵,旋转角度的顺序为:

48.1897   35.2644   45.0000

每个步骤后的组件差异(以行为单位):

10     6     3     1
 5     6     3     6
 5     5     4     6
 5     5     5     5

最终旋转矩阵(三个2D旋转矩阵的乘积):

 0.6667         0    0.5270    0.5270
      0    0.8165    0.4082   -0.4082
      0   -0.5774    0.5774   -0.5774
-0.7454         0    0.4714    0.4714

(LR)LR

5.0000         0    3.1623    3.1623
     0    5.0000    1.0000   -1.0000
3.1623    1.0000    5.0000    1.0000
3.1623   -1.0000    1.0000    5.0000

这是代码:

S = diag([10 6 3 1]);
mu = mean(diag(S));
R = eye(size(S));

vars(1,:) = diag(S);
Supdated = S;

for i = 1:size(S,1)-1
    [~, maxV] = max(diag(Supdated));
    [~, minV] = min(diag(Supdated));

    w = (mu-Supdated(minV,minV))/(Supdated(maxV,maxV)-Supdated(minV,minV));
    cosTheta = sqrt(w);
    sinTheta = sqrt(1-w);

    R2d = eye(size(S));
    R2d([maxV minV], [maxV minV]) = [cosTheta sinTheta; -sinTheta cosTheta];
    R = R * R2d;

    Supdated = transpose(R2d) * Supdated * R2d;    

    vars(i+1,:) = diag(Supdated);
    angles(i) = acosd(cosTheta);
end

angles                %// sequence of 2d rotation angles
round(vars)           %// component variances on each step
R                     %// final rotation matrix
transpose(R)*S*R      %// final S matrix

这是@feilong提供的Python代码:

def amoeba_rotation(s2):
    """
    Parameters
    ----------
    s2 : array
        The diagonal of the matrix S^2.

    Returns
    -------
    R : array
        The rotation matrix R.

    Examples
    --------
    >>> amoeba_rotation(np.array([10, 6, 3, 1]))
    [[ 0.66666667  0.          0.52704628  0.52704628]
     [ 0.          0.81649658  0.40824829 -0.40824829]
     [ 0.         -0.57735027  0.57735027 -0.57735027]
     [-0.74535599  0.          0.47140452  0.47140452]]

    http://stats.stackexchange.com/a/177555/87414
    """
    n = len(s2)
    mu = s2.mean()
    R = np.eye(n)
    for i in range(n-1):
        max_v, min_v = np.argmax(s2), np.argmin(s2)
        w = (mu - s2[min_v]) / (s2[max_v] - s2[min_v])
        cos_theta, sin_theta = np.sqrt(w), np.sqrt(1-w)
        R[:, [max_v, min_v]] = np.dot(
            R[:, [max_v, min_v]],
            np.array([[cos_theta, sin_theta], [-sin_theta, cos_theta]]))
        s2[[max_v, min_v]] = [mu, s2[max_v] + s2[min_v] - mu]
    return R

kσi2k


我猜想,对于任意两对组件(它们的分数),旋转角度将为45度,以使它们的方差相等。但是,我无法想象如何成对地使用3个以上的组件完成整个任务。
ttnphns

1
@feilong,我认为一次均衡一对组件的方差是一个非常次优的算法。我建议的是选择旋转,以使一个分量的方差变得恰好等于全局平均方差。然后,此组件“完成”,剩下的就可以解决。这样可以保证以有限的步长均衡所有方差。有关示例,请参见我之前的评论。
变形虫

1
@amoeba是的,这是一个更好的解决方案,应该以n-1个步骤结束。
feilong

1
@amoeba我添加了使用Python的最小实现。我修改了将整个矩阵相乘的部分,因为这对于大型矩阵可能会很费时。
飞龙2015年

1
@amoeba专门针对原理性组件,可以通过删除搜索最大值和最小值的零件来节省更多时间。我们可以简单地旋转第一个和第二个分量(以使第一个分量具有平均方差),然后旋转第二个和第三个分量,依此类推。我们只需要确保每对的总方差大于即可mu
feilong

2

XYσmax2σmin2Xμ2Yσmax2+σmin2μ2

cosθ

μ2=cos2θ(σmax2)+sin2θ(σmin2)

但尚未证明该方程式的来源;可能认为这是显而易见的,无需解释。不论是否显而易见,我认为值得澄清。我的回答提出了一种方法。

XYθXxx

旋转的插图

x Xx=xcosθXXX-Xÿÿθ

X=X-X-X=Xcosθ-ÿθ

μ2X

μ2=x2=(xcosθysinθ)2=(x2cos2θ+y2sin2θ2xycosθsinθ)=cos2θx2+sin2θy22cosθsinθxy=0 (X and Y are uncorrelated)=cos2θ(σmax2)+sin2θ(σmin2)

cosθ


2
(cosθsinθsinθcosθ)(σmax200σmin2)(cosθsinθsinθcosθ),
变形虫

而且我确实认为,您的几何解释和“直接”计算(不包括矩阵)更容易理解,并且对建立正确的直觉非常有帮助。
变形虫

0

如果我正确地解释事物,则意味着第一个主成分(特征值)解释了数据中的大部分差异。当您的压缩方法是线性的时,可能会发生这种情况。但是,要素空间中可能存在非线性依赖性。

TL / DR:PCA是线性方法。使用自动编码器(非线性pca)以减少尺寸。如果机器学习部分是有监督的学习,则只需在调整自动编码器的(超)参数的同时监视损耗函数即可。这样,您最终将获得更好的原始数据压缩版本。

这是一个scikit示例,他们在其中进行网格搜索以找到要使用PCA保留的最佳主成分(超参数)数量。最后,他们在较低维度的空间上应用Logistic回归:http : //scikit-learn.org/stable/auto_examples/plot_digits_pipe.html#example-plot-digits-pipe-py

提示:自动编码器没有封闭形式的解决方案(afaik),因此,如果您的上下文正在传输数据,这意味着您可以不断更新自动编码器(压缩表示),从而可以补偿概念漂移之类的问题。使用pca,您必须不时地重新训练批处理模式,因为会收到新数据。

至于给某些功能更多的“权重”,请参见正则化(我将从规范https://en.wikipedia.org/wiki/Norm_(mathematics)开始)。您可能还会感到惊讶,与感知器的逻辑回归相似。


我不知道这如何回答OP的问题;您的答案似乎与问题完全无关。
变形虫

因此,我想知道:是否有一种简单的方法可以拆分方差并与方差较小的PC共享?OP希望进行降维。我提供了一种解决他的问题的替代方法,因为除非衡量性能,否则OP最终希望的结果无法保证会带来更好的性能。在希尔伯特空间/范数空间中工作并不能保证获得更好的结果。测量性能可获得更好的结果。
shuriken x blue
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.