问题与目标

颜色表示聚类编号,坐标是主成分而不是原始字段。二维分离程度只是高维结构的投影。
没有标签时,可以用聚类观察相似样本,用 PCA 把高维数据投影到少量主成分。但结果取决于特征、尺度和算法假设。
完成标准:标准化数据后运行 K-means,用轮廓系数比较聚类数量,并用 PCA 投影到二维。
核心概念
K-means 交替分配最近中心和更新中心,目标是降低簇内平方距离。它偏好近似球状、尺度相近的簇,对初始中心和异常值敏感。
PCA 寻找方差最大的正交方向,主成分是原特征的线性组合。降维会损失信息,解释方差比说明保留了多少方差;二维图上的分离不等于真实业务类别。
K-means 的迭代过程
- 初始化
k个中心。 - 把每个样本分给最近中心。
- 用每簇样本均值更新中心。
- 重复直到中心基本不变或达到迭代上限。
不同初始中心可能得到不同局部结果,因此使用多次初始化并固定随机种子。n_init 控制尝试次数,最终选择簇内平方和较小的结果。
怎样选择簇数量
簇内平方和随 k 增大一定下降,不能直接选最小值。肘部法寻找下降速度明显变缓的位置;轮廓系数同时比较簇内紧密和簇间分离,范围约为 -1 到 1。两个指标都只是统计辅助,还要检查簇规模、稳定性和业务可解释性。
K-means 对长条形、环形、不同密度簇和异常值表现有限。没有明显簇结构时,不应强行给样本命名。
PCA 的计算直觉
PCA 通常先中心化数据,再寻找方差最大的方向;第二主成分与第一主成分正交,并解释剩余方差。标准化是否必要取决于量纲是否可比,运行指标通常需要先标准化。
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
scaled = StandardScaler().fit_transform(X)
pca = PCA().fit(scaled)
print("explained:", pca.explained_variance_ratio_)
print("cumulative:", pca.explained_variance_ratio_.cumsum())
print("components shape:", pca.components_.shape)
解释方差累计值帮助选择维度;components_ 展示主成分由原特征怎样线性组合,但符号整体翻转不改变含义。
可运行实现
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
from sklearn.decomposition import PCA
from sklearn.metrics import silhouette_score
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
X, _ = make_blobs(
n_samples=500, centers=3, n_features=5,
cluster_std=1.2, random_state=42,
)
for cluster_count in (2, 3, 4):
pipeline = make_pipeline(
StandardScaler(),
KMeans(n_clusters=cluster_count, n_init=10, random_state=42),
)
labels = pipeline.fit_predict(X)
scaled = pipeline.named_steps["standardscaler"].transform(X)
print(cluster_count, round(silhouette_score(scaled, labels), 3))
scaled = StandardScaler().fit_transform(X)
projected = PCA(n_components=2, random_state=42).fit_transform(scaled)
print("projected shape:", projected.shape)
输入是五维自建簇状数据,输出是不同 k 的轮廓系数及二维数组形状。真实任务需要结合业务解释簇特征,而不是只选最高分。
验证时至少比较三个 k、记录随机种子、报告每簇样本数,并说明二维 PCA 图保留多少解释方差。不同随机种子下结果剧烈变化,说明结构不稳定。
为聚类结果做画像
聚类完成后不要立即给簇取“高价值”之类的名称。先将原始特征和簇编号组合,查看样本数、中心位置和分布范围:
import pandas as pd
clusterer = make_pipeline(
StandardScaler(),
KMeans(n_clusters=3, n_init=10, random_state=42),
)
cluster_labels = clusterer.fit_predict(X)
profile = pd.DataFrame(X, columns=[f"feature_{i}" for i in range(X.shape[1])])
profile["cluster"] = cluster_labels
print(profile.groupby("cluster").agg(["count", "mean", "median"]).round(2))
如果簇的主要差异来自一个不稳定或无业务意义的字段,聚类名称就不应被固化为结论。还应记录每簇样本数,防止把极小簇当作稳定群体。
检查聚类稳定性
簇编号本身可以置换,所以不能直接比较两次结果中的标签数字。调整兰德指数忽略标签编号,比较两种划分的一致性:
from sklearn.metrics import adjusted_rand_score
reference = KMeans(n_clusters=3, n_init=10, random_state=1).fit_predict(scaled)
for seed in (2, 3, 4, 5):
candidate = KMeans(n_clusters=3, n_init=10, random_state=seed).fit_predict(scaled)
print(seed, round(adjusted_rand_score(reference, candidate), 3))
在人造球状数据上,结果往往很稳定;在重叠、异常点多或没有明显结构的真实数据上,稳定性检查更有价值。
PCA 投影图怎样才不误导
import matplotlib.pyplot as plt
pca_2d = PCA(n_components=2)
projected = pca_2d.fit_transform(scaled)
figure, axis = plt.subplots(figsize=(6, 4))
axis.scatter(projected[:, 0], projected[:, 1], c=cluster_labels, s=16, alpha=0.7)
axis.set_title(
f"PCA projection, retained={pca_2d.explained_variance_ratio_.sum():.1%}"
)
axis.set_xlabel("PC1")
axis.set_ylabel("PC2")
figure.tight_layout()
figure.savefig("cluster_projection.png", dpi=150)
plt.close(figure)
图标题中保留解释方差比,可以避免读者把二维投影当作全部数据。投影上重叠不代表高维中一定不可分,投影上分开也不自动产生业务含义。
进一步验证
- 比较
k=2、3、4、5的轮廓系数、簇规模和稳定性。 - 输出每簇原始特征中位数,只用数据特征描述,不赋予价值判断。
- 保存 PCA 二维图,在图中写明解释方差比,并说明信息损失边界。
常见问题与排查
- 未标准化直接按距离聚类:大量纲特征会主导结果。
- 把簇编号解释为等级:编号只是算法标签,没有大小顺序。
- 用带标签指标偷偷选择无监督模型:先明确实际使用场景和可用信息。
- PCA 后特征含义消失:查看载荷和解释方差,不把主成分当原字段。
小结
聚类用于提出结构假设,PCA 用于压缩和观察。两者都是探索工具,结论必须回到特征含义、稳定性和业务验证。
许可协议:CC BY-NC 4.0
更新于 1 小时前
觉得文章有帮助?点个赞吧!
0 条评论


