乳腺癌诊断数据集机器学习分类预测教程
一、教程概述
工具/软件介绍
- 核心工具:R 语言(统计计算与机器学习平台)及关键库
- 数据处理:
tidyverse
(包含dplyr
数据操作、ggplot2
可视化等) - 建模工具:
caret
(统一建模流程)、glmnet
(正则化逻辑回归)、ranger
(高效随机森林)、class
(KNN 基础算法支持) - 可视化工具:
corrplot
(相关性热图)、GGally
(多元数据可视化)
- 数据处理:
- 开发背景:基于威斯康辛乳腺癌诊断数据集(WDBC),完整演示二分类问题的机器学习全流程(从数据预处理到模型部署评价)。
学习目标
- 掌握医学数据集的标准化预处理流程(含冗余特征移除、高相关特征筛选、数据拆分与标准化)。
- 熟练构建正则化逻辑回归(glmnet)、随机森林(含 ranger 高效实现)、 KNN 三种经典分类模型,并理解其适用场景。
- 生成并解读特征相关性热图、主成分方差贡献图、模型性能对比图、特征重要性排序图等核心可视化结果。
- 明确乳腺癌诊断的关键特征(如
area_worst
、perimeter_worst
)及其临床意义。
二、一些前期准备(可以通过 openbayes 发布的教程中克隆)
核心文件说明
- 数据集:
data.csv
(569 条样本,30 个细胞核特征,标签为良性(B)/恶性(M),含id
(样本编号)、diagnosis
(诊断结果)及 30 个形态学特征)。 - 代码文件:包含数据加载→预处理→EDA→特征工程→建模→评价的完整 R 脚本(可直接运行,需替换数据路径)。
- 依赖库清单(安装命令):
install.packages(c("tidyverse", "caret", "ranger", "corrplot", "GGally", "glmnet"))
关键技术流程
- 数据预处理:加载数据→移除冗余列(如
X
、id
)→标签类型转换(因子化)→缺失值检查。 - 特征工程:计算特征相关性矩阵→筛选高相关特征(阈值 0.9)→主成分分析(PCA)降维与可视化。
- 建模流程:数据集拆分(8:2 训练集/测试集)→10 折交叉验证参数调优→三种模型并行训练→混淆矩阵与性能指标评估。
- 评价指标:准确率(Accuracy)、 ROC 曲线下面积(AUC)、灵敏度(Sensitivity,恶性检出率)、特异度(Specificity,良性检出率)。
三、实操运行步骤
环境搭建
数据加载与预处理
# 加载库 library(tidyverse) # 数据处理核心库 library(caret) # 建模与评价工具 加载数据(替换为实际路径) data <- read.csv("path/to/data.csv") 预处理:移除冗余列(X 为索引列,id 为样本编号,均非特征) data <- data %>% select(-X, -id) 标签转换:将 diagnosis(B/M)转为因子类型(分类模型要求) data$diagnosis <- as.factor(data$diagnosis) 查看数据结构(确认特征类型与样本量) str(data) 检查缺失值(该数据集无缺失,实际场景可补充插补步骤)
colSums(is.na(data))
探索性数据分析(EDA)
核心目标:了解特征分布与相关性,识别多重共线性问题。
library(corrplot) # 相关性热图工具 计算特征相关性矩阵(排除标签列) data_corr <- cor(data %>% select(-diagnosis)) 绘制聚类排序的相关性热图(便于识别高相关特征群)
corrplot(data_corr, order = "hclust", tl.cex = 0.6, addrect = 8)
结果解读:
- 半径(
radius
)、周长(perimeter
)、面积(area
)等特征间相关性>0.9,存在严重多重共线性,需通过特征筛选去除冗余。
主成分分析(PCA)
核心目标:通过降维简化数据结构,保留关键信息并可视化。
library(GGally) # 多元可视化工具 步骤 1:移除高相关特征(阈值 0.9) high_corr_indices <- findCorrelation(data_corr, cutoff = 0.9) # 筛选高相关特征索引
data2 <- data %>% select(-all_of(names(data)[high_corr_indices])) # 移除冗余特征 步骤 2:执行 PCA(需标准化与中心化) pca_data2 <- prcomp(data2, scale = TRUE, center = TRUE) 步骤 3:可视化方差贡献(确定核心主成分) explained_variance <- pca_data2$sdev^2 / sum(pca_data2$sdev^2) # 单个主成分方差占比
cumulative_variance <- cumsum(explained_variance) # 累积方差占比 variance_data <- data.frame(
PC = 1:length(explained_variance),
ExplainedVariance = explained_variance,
CumulativeVariance = cumulative_variance
)ggplot(variance_data, aes(x = PC)) +
geom_bar(aes(y = ExplainedVariance), stat = "identity", fill = "skyblue", alpha = 0.7) +
geom_line(aes(y = CumulativeVariance), color = "red", size = 1) +
geom_point(aes(y = CumulativeVariance), color = "red") +
labs(
title = "主成分方差贡献图",
x = "主成分",
y = "方差解释比例"
) +
scale_y_continuous(sec.axis = sec_axis(~., name = "累积方差解释比例")) +
theme_minimal()
结果解读:前 3 个主成分累积解释方差约 70%-80%,可用于简化模型。
步骤 4:主成分与诊断标签关联可视化
# 提取前 3 个主成分得分,关联诊断标签 pca_scores <- as.data.frame(pca_data2$x[, 1:3]) # 前 3 个主成分 pca_scores$diagnosis <- data$diagnosis # 加入诊断标签 绘制散点矩阵(含相关性、密度分布)
ggpairs(
pca_scores,
columns = 1:3,
mapping = aes(color = diagnosis, fill = diagnosis),
upper = list(continuous = wrap("cor", size = 3)), # 上三角:相关性
lower = list(continuous = "points"), # 下三角:散点图
diag = list(continuous = wrap("densityDiag")) # 对角线:密度分布
) +
theme_minimal() +
scale_color_manual(values = c("B" = "salmon", "M" = "cyan3")) +
scale_fill_manual(values = c("B" = "salmon", "M" = "cyan3"))
结果解读:恶性(M)与良性(B)样本在前 3 个主成分上分布差异明显,说明 PCA 有效保留了分类信息。
模型训练
数据集拆分(8:2)
set.seed(123) # 固定随机种子,保证结果可复现 组合标签与处理后特征(便于建模) data3 <- cbind(diagnosis = data$diagnosis, data2) 按标签分层抽样(维持训练集/测试集类别比例一致) data_sampling_index <- createDataPartition(data3$diagnosis, times = 1, p = 0.8, list = FALSE)
data_training <- data3[data_sampling_index, ] # 训练集(80%)
data_testing <- data3[-data_sampling_index, ] # 测试集(20%) 定义交叉验证策略(10 折交叉验证,计算分类概率与二分类指标)data_control <- trainControl(
method = "cv",
number = 10,
classProbs = TRUE,
summaryFunction = twoClassSummary # 输出 ROC 、灵敏度、特异度
)
1. 正则化逻辑回归(glmnet)
# 训练模型(带 L1/L2 正则化,自动调优参数)
model_glmnet <- train(
diagnosis ~ .,
data = data_training,
method = "glmnet", # 正则化逻辑回归
metric = "ROC", # 以 ROC 为优化目标
preProcess = c("scale", "center"), # 特征标准化
tuneLength = 20, # 20 组参数候选
trControl = data_control
)
2. 随机森林(两种实现方式)
方式 1:ranger
包(高效实现)
library(ranger) # 快速随机森林工具
model_rf_ranger <- ranger(
diagnosis ~ .,
data = data_training,
probability = TRUE, # 输出概率
importance = "impurity", # 计算特征重要性(不纯度)
num.trees = 500 # 500 棵决策树
)
方式 2:caret
包集成的 rf
(便于交叉验证)
model_rf_caret <- train(
diagnosis ~ .,
data = data_training,
method = "rf", # 传统随机森林
metric = "ROC",
trControl = data_control,
ntree = 500 # 500 棵决策树
)
3. KNN(K 近邻)
# 训练模型(优化邻居数 k) model_knn <- train( diagnosis ~ ., data = data_training, method = "knn", metric = "ROC", preProcess = c("scale", "center"), # KNN 对距离敏感,必须标准化 trControl = data_control, tuneLength = 31 # 测试 k= 1 到 31 的最优值 ) 可视化不同 k 值的 ROC 表现(确定最优 k)
plot(model_knn, main = "KNN 模型不同邻居数的 ROC 表现")
模型预测与评价
1. 预测结果与混淆矩阵
以逻辑回归为例:
# 测试集预测 prediction_glmnet <- predict(model_glmnet, data_testing) 生成混淆矩阵(评估分类准确性)
cm_glmnet <- confusionMatrix(prediction_glmnet, data_testing$diagnosis, positive = "M")
cm_glmnet # 输出准确率、灵敏度、特异度等指标
混淆矩阵可视化:
# 转换为数据框用于绘图 cm_table <- as.table(cm_glmnet$table) cm_df <- as.data.frame(cm_table) colnames(cm_df) <- c("实际标签", "预测标签", "频数")
ggplot(cm_df, aes(x = 实际标签, y = 预测标签, fill = 频数)) +
geom_tile(color = "white") +
scale_fill_gradient(low = "lightblue", high = "blue") +
geom_text(aes(label = 频数), color = "black", size = 6) +
labs(title = "逻辑回归混淆矩阵", x = "实际诊断", y = "预测诊断") +
theme_minimal()
2. 特征重要性分析
随机森林特征重要性:
# 提取前 10 个重要特征 importance_rf <- model_rf_ranger$variable.importance # ranger 模型结果 importance_df <- data.frame( 特征 = names(importance_rf), 重要性 = importance_rf ) %>% arrange(desc(重要性)) %>% slice(1:10) # 取前 10 可视化
ggplot(importance_df, aes(x = reorder(特征, 重要性), y = 重要性)) +
geom_bar(stat = "identity", fill = "skyblue") +
coord_flip() + # 横向条形图,便于阅读特征名
labs(title = "随机森林 Top10 重要特征", x = "特征", y = "重要性(不纯度下降)") +
theme_minimal()
关键发现:area_worst
(肿瘤最大面积)、 perimeter_worst
(肿瘤最大周长)是区分良恶性的核心特征,与临床认知一致。
四、模型对比与结果解读
多模型性能对比
# 汇总所有模型 model_list <- list( 逻辑回归 = model_glmnet, 随机森林 = model_rf_caret, KNN = model_knn ) 提取交叉验证结果 results <- resamples(model_list) 输出性能指标(ROC 、灵敏度、特异度)
summary(results)
可视化对比:
# 箱线图:展示各模型 ROC 分布 bwplot(results, metric = "ROC", main = "模型 ROC 性能对比(10 折交叉验证)") 点图:带 95% 置信区间的性能指标
dotplot(results, metric = c("ROC", "Sens", "Spec"), main = "模型性能指标对比")
结果解读:
- 逻辑回归表现最优(ROC=0.993,灵敏度=0.989),适合作为基准模型。
- 随机森林性能接近逻辑回归,但计算成本较高。
- KNN 特异度略低(0.888),对良性样本的误判率稍高。
五、进阶操作
参数优化
- 随机森林调优(优化
mtry
参数,即每次分裂的特征数量):
model_rf_tuned <- train(
diagnosis ~ .,
data = data_training,
method = "rf",
metric = "ROC",
trControl = data_control,
tuneGrid = expand.grid(mtry = seq(5, 15, 2)) # 测试 mtry=5,7,...,15
)
- 扩展模型:加入支持向量机(SVM)
model_svm <- train(
diagnosis ~ .,
data = data_training,
method = "svmRadial", # 径向核 SVM
metric = "ROC",
trControl = data_control
)
六、附录
常用代码速查表
功能 | 代码示例 |
---|---|
数据读取 | read.csv("data.csv") |
相关性热图 | corrplot(cor(data), order = "hclust") |
10 折交叉验证设置 | trainControl(method = "cv", number = 10) |
混淆矩阵计算 | confusionMatrix(pred, actual) |
PCA 降维 | prcomp(data, scale = TRUE) |
常见问题排查
- 报错
could not find function "corrplot"
→ 解决方案:安装corrplot
包(install.packages("corrplot")
)。 - 特征维度错误→ 检查是否遗漏
select(-id, -diagnosis)
步骤(需排除非特征列)。 - 模型训练缓慢→ 减少
ntree
(随机森林树数量)或tuneLength
(参数候选数)。
通过本教程,能掌握一点医学二分类问题的机器学习流程,重点理解特征筛选、模型调优与结果可视化的核心逻辑,为其他疾病诊断建模提供参考。