R语言k-means预测结果簇ID如何转换为真实分类标签
问题根因
- 报错
Error:dataandreferenceshould be factors with the same levels.的中文含义为:错误:预测数据和参照标签必须是含有相同层级的因子 - 你当前的
pre_model输出的是1-9的簇ID,共有9个层级,而测试集标签testdata$Class只有0、1两个层级,二者层级不匹配因此无法计算混淆矩阵 - 额外隐藏问题:你调用
cl_predict时直接输入了未标准化的测试集,而k-means模型是基于标准化后的训练数据训练的,会导致聚类预测结果完全失真
解决步骤
核心逻辑是:基于训练集的真实标签,给每个簇映射对应的0/1分类标签——如果某个簇内欺诈样本(Class=1)的占比更高,该簇就映射为1(欺诈),否则映射为0(非欺诈)
- 统计训练集每个簇的标签分布,生成映射规则
- 用训练集的标准化参数处理测试集特征,保证数据分布一致
- 将预测得到的簇ID按规则转换为0/1标签,对齐测试集标签的因子层级
- 调用混淆矩阵进行评估
修正后完整代码
library(caret) library(clue) # 数据读取与拆分 data = read.csv("creditcard.csv") data$Class <- as.factor(data$Class) data_split <- createDataPartition(data$Class, times=1, p=0.8, list=F) train_data <- data[data_split ,] testdata <- data[-data_split ,] # 标准化训练集特征,保存标准化参数用于测试集处理 train_features <- train_data[-c(31)] scaler <- preProcess(train_features, method = c("center", "scale")) scaled_train <- predict(scaler, train_features) scaled_train <- as.matrix(scaled_train) # 训练k-means模型 clust <- kmeans(scaled_train, centers = 9, nstart = 25) # -------------------------- 新增:生成簇到0/1的映射规则 -------------------------- # 给训练集样本关联对应簇标签 train_data$cluster <- as.factor(clust$cluster) # 统计每个簇中Class=1的占比,生成映射规则 cluster_label <- aggregate(Class ~ cluster, data = train_data, FUN = function(x) { # 阈值可按需调整,比如要降低欺诈漏判率可以把阈值调低为0.3 ifelse(mean(as.integer(as.character(x))) > 0.5, "1", "0") }) # 生成命名映射向量方便后续快速替换 map_vec <- setNames(cluster_label$Class, cluster_label$cluster) # ------------------------------------------------------------------------------- # 标准化测试集特征 scaled_test <- predict(scaler, testdata[-c(31)]) # 预测测试集样本对应的簇ID pre_cluster <- cl_predict(clust, scaled_test) # 将簇ID按规则转换为0/1标签,转换为和测试集标签一致的因子类型 pre_model <- as.factor(map_vec[as.character(pre_cluster)]) # 可正常调用混淆矩阵评估 confusionMatrix(testdata$Class, pre_model, positive='1')
注意事项
k-means属于无监督算法,本身没有分类标签学习能力,该方案的精度上限会低于逻辑回归、XGBoost等监督学习模型,仅做无监督场景下的思路参考。
内容的提问来源于stack exchange,提问作者WILLIAM
相关产品推荐
相关产品推荐

