6. 结果分析与解读

在本部分,我们将深入分析癌症生存率数据集 的模型预测结果,并总结其意义~

6.1 关键指标回顾

图片[1]-6. 结果分析与解读-大赛人网
图片[2]-6. 结果分析与解读-大赛人网

6.2 特征重要性分析

哪些因素对癌症预测影响最大?

图片[3]-6. 结果分析与解读-大赛人网

6.3 预测概率分析

我们绘制了 预测概率分布直方图,结果如下:

  • 预测值 接近 0(良性) 的样本较多,说明良性肿瘤分类稳定。
  • 预测值 接近 1(恶性) 的样本也较多,说明恶性分类可靠。
  • 但有部分样本概率接近 0.5,表示模型对某些病例不太确定。

解读:

  • 绝大多数样本的预测结果具有高置信度(接近 0 或 1),说明模型的决策边界清晰。
  • 少部分样本接近 0.5,可能是病理学上的边界病例(benign/malignant borderline cases),需要进一步医学诊断。

指导意义:

  1. 医学应用:对于模型不确定的病例(概率接近 0.5),建议医生结合更多检测手段(如活检)进一步检查。
  2. 模型优化方向:可以引入更多数据增强技术,增强对边界病例的识别能力。

6.4 ROC 曲线分析

我们绘制的 ROC 曲线 结果如下:

  • AUC = 0.98,说明模型的分类能力非常强!
  • False Positive Rate(误判率)较低,说明模型很少误判良性为恶性。
  • True Positive Rate(召回率)较高,说明模型能成功检测出大部分恶性病例。

解读:

  • AUC 越接近 1,模型性能越好,本模型达到 0.98,说明分类能力接近理想状态。
  • ROC 曲线在 (0,1) 角附近陡峭,说明模型能够在低误判率的情况下保持高召回率。

指导意义:

  1. 模型可用于临床癌症筛查,但仍需结合医生判断,避免误诊。
  2. 可以调整阈值,在不同场景(如高风险患者筛查)中优化 Precision 或 Recall。

6.5 关键结论 & 指导意义

🔹 模型表现优异,适合用于癌症早期筛查

  • 召回率高,能够成功检测出大部分恶性病例
  • AUC 高(0.98),能有效区分良性和恶性

🔹 影响癌症分类的关键因素

  • 肿瘤半径(radius_mean) 最重要,肿瘤越大,恶性概率越高
  • 肿瘤边缘凹陷度(concavity_worst) 影响显著
  • 肿瘤纹理(texture_mean) 也有一定影响

🔹 模型局限性

  • 对某些边界病例(概率接近 0.5)不够确定,仍需医生进一步检查
  • 数据集可能有偏差,未来可增加更多样本提升模型泛化能力

医学应用建议

  1. 高风险患者筛查:可用于乳腺癌早期检测,提高筛查效率。
  2. 联合医生诊断:在高置信度预测时可辅助医生判断,低置信度时需进一步检查。
  3. 动态调整阈值:在不同应用场景(如医院 vs. 体检中心)调整 Precision 和 Recall 之间的权衡。

6.6 小结

XGBoost 是一个强大的乳腺癌分类模型,在高召回率、可解释性、计算效率 等方面表现优越,可用于癌症早期筛查。

肿瘤半径、边缘凹陷度、纹理等特征最具决定性,未来可进一步优化特征工程。

模型不确定的病例(预测概率接近 0.5)仍需医生介入,可结合生物标记物、基因检测等进行综合判断。

7. 完整代码

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from sklearn.feature_selection import SelectKBest, f_classif
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
from xgboost import XGBClassifier

# 设置Seaborn风格
sns.set(style="whitegrid", palette="pastel")

# 读取数据
file_path = "./dataset/007/data.csv"
df = pd.read_csv(file_path)

# 显示数据基本信息
print("数据基本信息:")
print(df.info())  # 查看数据类型、缺失值情况等

# 显示数据前5行
print("\n数据预览:")
print(df.head())

# 统计描述
print("\n数值特征统计信息:")
print(df.describe())

# 删除无关列
df.drop(columns=["id", "Unnamed: 32"], inplace=True)

# 检查缺失值
missing_values = df.isnull().sum()
print("\n缺失值情况:")
print(missing_values[missing_values > 0])  # 只显示有缺失值的列

# 由于"Unnamed: 32"列已删除,数据集实际上没有缺失值

# 检查重复行
print("\n重复数据条数:", df.duplicated().sum())

# 删除重复值(如果有的话)
df.drop_duplicates(inplace=True)

numeric_df = df.select_dtypes(include=[np.number])

# 计算异常值范围(1.5倍IQR原则)
Q1 = numeric_df.quantile(0.25)
Q3 = numeric_df.quantile(0.75)
IQR = Q3 - Q1

# 设定异常值范围
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR

# 统计异常值情况
outliers = ((numeric_df < lower_bound) | (numeric_df > upper_bound)).sum()
print("\n各列异常值数量:")
print(outliers[outliers > 0])

# 直接删除异常值(仅适用于异常值极端的情况)
df = df[~((numeric_df < lower_bound) | (numeric_df > upper_bound)).any(axis=1)]

# 统计良性(B)和恶性(M)样本数量
plt.figure(figsize=(6, 4))
sns.countplot(x=df["diagnosis"], palette=["#FF9999", "#66B2FF"])

# 设置标题和标签
plt.title("Distribution of Diagnosis", fontsize=14)
plt.xlabel("Diagnosis", fontsize=12)
plt.ylabel("Count", fontsize=12)
plt.show()

# 选取部分关键变量
features = ["radius_mean", "texture_mean", "area_mean"]
plt.figure(figsize=(12, 4))

for i, feature in enumerate(features):
    plt.subplot(1, 3, i + 1)
    sns.histplot(df[feature], kde=True, bins=30, color=np.random.rand(3, ))
    plt.title(f"Distribution of {feature}")

plt.tight_layout()
plt.show()

# 只选择数值型特征进行相关性计算
numeric_df = df.select_dtypes(include=['number'])

# 计算特征相关性矩阵
corr_matrix = numeric_df.corr()

# 绘制热力图
plt.figure(figsize=(12, 10))
sns.heatmap(corr_matrix, cmap="coolwarm", annot=False, linewidths=0.5)

# 设置标题
plt.title("Feature Correlation Heatmap", fontsize=14)
plt.show()

# 将 'diagnosis' 转换为二进制变量(M=1,B=0)
df['diagnosis'] = df['diagnosis'].map({'M': 1, 'B': 0})

# 确保转换成功
print(df['diagnosis'].value_counts())

# 计算相关性矩阵
corr_matrix = df.corr().abs()

# 设定阈值(如 0.9),高于该阈值的特征将被移除
threshold = 0.9

# 找到相关性高的特征对
high_corr_features = set()
for i in range(len(corr_matrix.columns)):
    for j in range(i):
        if corr_matrix.iloc[i, j] > threshold:
            feature_name = corr_matrix.columns[i]
            high_corr_features.add(feature_name)

print("高相关特征(将被移除):", high_corr_features)

# 删除高相关特征
df.drop(columns=high_corr_features, inplace=True)

# 选择前 10 个最重要的特征
X = df.drop(columns=['diagnosis'])  # 特征
y = df['diagnosis']  # 目标变量

selector = SelectKBest(score_func=f_classif, k=10)
X_selected = selector.fit_transform(X, y)

# 获取被选中的特征名称
selected_features = X.columns[selector.get_support()]
print("被选中的 10 个关键特征:", selected_features)

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

# 若 X_selected 是 ndarray,则转为 DataFrame
if not isinstance(X_selected, pd.DataFrame):
    X_selected = pd.DataFrame(X_selected, columns=selected_features)

# 1. 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
    X_selected, y, test_size=0.2, random_state=42, stratify=y
)

# 2. 标准化(只在训练集上 fit)
scaler = StandardScaler()
X_train_array = scaler.fit_transform(X_train)
X_test_array = scaler.transform(X_test)

# 3. 转换为 DataFrame,保留列名和索引
X_train_scaled = pd.DataFrame(X_train_array, columns=X_train.columns, index=X_train.index)
X_test_scaled = pd.DataFrame(X_test_array, columns=X_test.columns, index=X_test.index)

# 4. 打印数据形状
print("训练集大小:", X_train_scaled.shape)
print("测试集大小:", X_test_scaled.shape)

# 初始化 XGBoost 分类器(初始参数)
model = XGBClassifier(
    n_estimators=100,  # 决策树数量
    learning_rate=0.1,  # 学习率
    max_depth=4,  # 树的最大深度
    subsample=0.8,  # 采样比例
    colsample_bytree=0.8,  # 列采样
    random_state=42
)

# 训练模型
model.fit(X_train_scaled, y_train)

# 预测测试集
y_pred = model.predict(X_test_scaled)

# 计算评估指标
accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred, average="binary")
recall = recall_score(y_test, y_pred, average="binary")
f1 = f1_score(y_test, y_pred, average="binary")

# 打印结果
print(f"XGBoost Accuracy: {accuracy:.4f}")
print(f"Precision: {precision:.4f}")
© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享
评论 抢沙发
头像-大赛人网
欢迎您留下宝贵的见解!
提交
头像-大赛人网

昵称

取消
昵称

    请登录后查看评论内容