PCA 结合 KMeans 时一定要使用 train_test_split 吗?
不一定。PCA 和 KMeans 都可以直接在全部数据上拟合。是否需要使用 train_test_split,取决于你是想探索现有数据,还是评估模型处理未见数据的能力。X 有 100 列、3000 多行,这一点本身不能决定是否需要划分数据。
哪些情况可以使用全部数据?
如果目的是观察这批数据的结构、绘制 PCA 散点图,或给现有样本分组,可以在全部 X 上进行预处理、PCA 和 KMeans。
分析结果反映的是当前数据的情况,不能据此认定模型对未来数据也有同样的表现。不同示例是否划分数据,往往取决于分析目标。
哪些情况应该划分数据?
如果以后需要给新样本分配簇,或比较不同处理方案在未见数据上的表现,就应该留出验证集或测试集。
数据划分要在拟合预处理步骤之前完成。StandardScaler 的均值和标准差、PCA 的主成分方向以及 KMeans 的簇中心,都应只从训练集学习。测试集使用已经拟合好的转换和模型。
即使 PCA 不使用 y,如果先在全部 X 上拟合、再划分数据,测试集信息也会参与主成分的计算,影响评估的独立性。
如何组织代码?
下面假设 X 只包含数值特征,且缺失值已经妥善处理。示例使用 StandardScaler,使各特征按标准差缩放。实际是否需要缩放,应结合特征单位和距离的业务含义判断。
先定义处理流程:
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
model = Pipeline([
("scaler", StandardScaler()),
("pca", PCA(n_components=0.95, svd_solver="full")),
("kmeans", KMeans(
n_clusters=3, # 演示值,需要根据实际问题选择
n_init=10,
random_state=42
))
])
如果只是分析当前数据:
cluster_labels = model.fit_predict(X)
如果需要留出未见样本进行评估:
from sklearn.model_selection import train_test_split
X_train, X_test = train_test_split(
X,
test_size=0.2,
random_state=42
)
model.fit(X_train)
test_cluster_labels = model.predict(X_test)
这里的 test_size=0.2 是示例比例。随机划分适合样本之间可以近似视为独立的情况。如果数据有时间顺序或同一对象的重复记录,需要采用相应的时间划分或分组划分。
PCA 的 n_components=0.95 表示按累计解释方差比例选择保留的主成分,并不保证聚类效果最好。PCA 优先保留方差较大的方向,而有利于区分簇的信息未必都在这些方向上,因此也值得比较直接聚类和降维后聚类的效果。
y 的数量会影响选择吗?
PCA 和 KMeans 在常规用法中都只需要 X,不要求提供 y。原问题中“y 有 10 多个变量”的含义还不明确,需要区分两种情况:
- 如果指一个标签列中有 10 多种类别,这是类别数量,不是目标变量数量。它不会决定 PCA 是否需要划分数据,也不要求 KMeans 的 n_clusters 必须等于这个数量。
- 如果指 y 确实有 10 多个目标列,这是多输出数据,也不会改变 PCA 和 KMeans 通常只对 X 拟合的方式。
如果 y 是已有的真实类别标签,可以用它辅助评价聚类结果,例如计算 Adjusted Rand Index。不要为了让分组更贴近标签而直接把 y 拼进 X,除非你的分析目标明确要求将它作为输入特征。
划分后怎样判断效果?
仅调用 predict 得到测试集的簇编号,还不算完成效果评估。没有真实标签时,可以结合轮廓系数、不同抽样或初始化下的聚类稳定性,以及各簇特征是否具有可解释性来判断。轮廓系数也有适用条件:例如,被评估样本中必须存在至少两个簇,且簇数少于样本数。
如果反复根据留出数据选择主成分数量或簇数,这部分数据实际上就承担了验证集的作用。需要独立报告最终泛化表现时,应再保留未参与调参的测试集。
备注:内容仅供参考。
