的确,K均值聚类和PCA似乎具有非常不同的目标,乍一看似乎没有关联。但是,正如Ding&He 2004年发表的论文《通过主成分分析的K-means聚类》中所述,它们之间存在着深厚的联系。
直觉是,PCA试图将所有数据向量表示为少量特征向量的线性组合,并且这样做是为了使均方重构误差最小。相反,K-手段旨在表示所有经由少数聚类中心的,即,数据向量来表示它们作为一个小数目群集的质心的向量,其中线性组合权重必须除单个全零的线性组合的。这样做也是为了最小化均方重构误差。Ñ 1nn1
因此,K均值可以看作是超稀疏PCA。
丁赫(Ding&He)论文的目的是使这种联系更加精确。
不幸的是,Ding&He论文(其中充其量)包含一些草率的表述,并且很容易被误解。例如,Ding&He似乎声称已证明K-means聚类解决方案的聚类质心位于维PCA子空间中:(K−1)
定理3.3。集群质心子空间被第一个主方向跨越
。K−1
对于这意味着在一个群集上PC1轴上的投影必然为负,而在另一个群集上PC1轴上的投影必然为正,即PC2轴将完美地分离群集。K=2
这要么是一个错误,要么是一些草率的写作。在任何情况下,从字面上看,该特定主张都是错误的。
让我们从2D中一些玩具示例开始。我使用相同的协方差矩阵但均值不同的两个正态分布生成了一些样本。然后,我同时运行K-means和PCA。下图显示了上面数据的散点图,并且根据下面的K-means解决方案对相同的数据进行了着色。我还将第一个主要方向显示为黑线和K均值带有黑色叉号的类质心。黑色虚线表示PC2轴。用随机种子重复K均值次,以确保收敛到全局最优。100K=2100
可以清楚地看到,即使类质心趋向于非常接近第一个PC方向,但它们并没有精确地落在该方向上。此外,即使PC2轴在子图1和图4中完美地分隔了群集,在子图2和3中它的另一侧也有一些点。
因此,K-means和PCA之间的协议相当不错,但是并不完全正确。
那么丁&他证明了什么?为简单起见,我将仅考虑情况。让分配给每个聚类的点数为和 ,点总数为。跟随Ding&He,让我们如下定义聚类指示符向量 :如果第个点属于聚类1,而如果它属于集群2)。集群指示符向量的单位长度为且“居中”,即其元素总和为零。n 1K=2n1 Ñ = Ñ 1 + Ñ 2 q ∈ [R Ñ q 我 = √n2n=n1+n2 q∈Rn我q我=-√qi=n2/nn1−−−−−−√iqi=−n1/nn2−−−−−−√Σ q 我 = 0∥q∥=1∑qi=0
Ding&He证明K均值损失函数(K-means算法最小化)可以等效地重写为,其中是所有点之间的标量积的克矩阵:,其中是数据矩阵,并且是居中的数据矩阵。∑k∑i(xi−μk)2−q⊤GqGn×nG=X⊤cXcXn×2Xc
(注意:我使用的符号和术语与他们的论文略有不同,但我觉得更清楚)。
因此,K-均值解是最大化的居中单位向量。很容易表明,第一个主成分(当归一化为具有单位平方和时)是Gram矩阵的前导特征向量,即它也是最大化的居中单位向量。唯一的区别是约束为仅具有两个不同的值,而没有此约束。qq⊤Gqpp⊤Gpqp
换句话说,K-means和PCA使相同的目标函数最大化,唯一的区别是K-means具有附加的“类别”约束。
可以认为,正如我们在上面的仿真中看到的那样,大多数情况下,K均值(约束)解决方案和PCA(无约束)解决方案非常接近彼此,但是我们不应该期望它们是相同的。取并将其所有负元素设置为等于并将其所有正元素设置为通常通常不会完全给出 。p−n1/nn2−−−−−−√n2/nn1−−−−−−√q
Ding&He似乎很了解这一点,因为他们将定理阐述如下:
定理2.2。对于K K均值聚类,聚类指示符向量的连续解是[第一]主成分K=2
注意单词“连续解”。在证明了该定理之后,他们还评论说PCA可用于初始化K-means迭代,这完全有意义,因为我们期望接近。但是仍然需要执行迭代,因为它们并不相同。qp
但是,Ding&He随后针对继续开发了更通用的处理方法,最终将定理3.3公式表示为K>2
定理3.3。集群质心子空间被第一个主方向跨越
。K−1
我没有经过第3节的数学运算,但是我相信这个定理实际上也指的是K-means的“连续解”,即其陈述应为“ K-means连续解的聚类质心空间为”。跨越[...]”。
但是,Ding&He没有取得这一重要资格,而且在摘要中写道:
在这里,我们证明主成分是K-均值聚类的离散聚类成员指标的连续解。等效地,我们表明,由簇质心跨越的子空间是由以项截断的数据协方差矩阵的谱扩展给出的。K−1
第一句话是绝对正确的,但第二句话则不是。我不清楚这是(非常)草率的文字还是真正的错误。我非常有礼貌地给两位作者发了电子邮件,要求澄清。(两个月后更新:我从未收到他们的回复。)
Matlab仿真代码
figure('Position', [100 100 1200 600])
n = 50;
Sigma = [2 1.8; 1.8 2];
for i=1:4
means = [0 0; i*2 0];
rng(42)
X = [bsxfun(@plus, means(1,:), randn(n,2) * chol(Sigma)); ...
bsxfun(@plus, means(2,:), randn(n,2) * chol(Sigma))];
X = bsxfun(@minus, X, mean(X));
[U,S,V] = svd(X,0);
[ind, centroids] = kmeans(X,2, 'Replicates', 100);
subplot(2,4,i)
scatter(X(:,1), X(:,2), [], [0 0 0])
subplot(2,4,i+4)
hold on
scatter(X(ind==1,1), X(ind==1,2), [], [1 0 0])
scatter(X(ind==2,1), X(ind==2,2), [], [0 0 1])
plot([-1 1]*10*V(1,1), [-1 1]*10*V(2,1), 'k', 'LineWidth', 2)
plot(centroids(1,1), centroids(1,2), 'w+', 'MarkerSize', 15, 'LineWidth', 4)
plot(centroids(1,1), centroids(1,2), 'k+', 'MarkerSize', 10, 'LineWidth', 2)
plot(centroids(2,1), centroids(2,2), 'w+', 'MarkerSize', 15, 'LineWidth', 4)
plot(centroids(2,1), centroids(2,2), 'k+', 'MarkerSize', 10, 'LineWidth', 2)
plot([-1 1]*5*V(1,2), [-1 1]*5*V(2,2), 'k--')
end
for i=1:8
subplot(2,4,i)
axis([-8 8 -8 8])
axis square
set(gca,'xtick',[],'ytick',[])
end