CKD数据集解析:从医学数据到机器学习实战指南

1次阅读
没有评论

共计 2645 个字符,预计需要花费 7 分钟才能阅读完成。

image.webp

1. 背景与痛点

慢性肾病(CKD)是一种全球性的健康问题,早期诊断对治疗至关重要。CKD 数据集包含了患者的临床指标(如血压、血糖、红细胞计数等)和最终的诊断结果,是机器学习在医疗领域应用的经典案例。

CKD 数据集解析:从医学数据到机器学习实战指南

处理这类数据时,我们常遇到以下挑战:

  • 数据不均衡:健康样本远多于患病样本,导致模型偏向多数类
  • 高维度与特征相关性:临床指标间存在强相关性(如血压与肾功能指标)
  • 缺失值普遍:医疗记录常有不完整字段
  • 类别特征处理:如尿液蛋白检测结果(trace, +, ++ 等)需要合理编码

2. 数据探索

首先加载数据并观察其结构:

import pandas as pd
import matplotlib.pyplot as plt

# 加载数据
df = pd.read_csv('ckd.csv')
print(f'数据集形状:{df.shape}')
print('\n 前 5 行样本:')
display(df.head())

# 基本统计信息
print('\n 数值特征统计:')
display(df.describe())

# 目标变量分布
plt.figure(figsize=(6,4))
df['classification'].value_counts().plot(kind='bar')
plt.title('类别分布')
plt.show()

关键观察点:

  1. 数据包含 400 条记录,25 个特征(24 个特征 + 1 个目标变量)
  2. 目标变量 classification 显示约 150 例 CKD 患者,250 例健康人
  3. 特征中包含数值型(如 bp 血压)和分类型(如 rbc 红细胞计数)

3. 预处理方案

3.1 缺失值处理

医疗数据常见缺失值处理策略对比:

# 检查缺失值
missing = df.isnull().sum()
print(f'缺失值统计:\n{missing[missing > 0]}')

# 方案 1:删除缺失率高的特征
df_clean = df.drop(columns=['id'])  # 本例中 id 列无意义

# 方案 2:数值特征用中位数填充
num_cols = ['age', 'bp', 'sg', 'al']
df_clean[num_cols] = df_clean[num_cols].fillna(df_clean[num_cols].median())

# 方案 3:类别特征用众数填充
cat_cols = ['rbc', 'pc']
df_clean[cat_cols] = df_clean[cat_cols].fillna(df_clean[cat_cols].mode().iloc[0])

3.2 类别特征编码

医疗类别特征的特殊性处理:

from sklearn.preprocessing import OrdinalEncoder

# 有序类别(如尿蛋白等级)ordinal_features = ['al', 'su']
ordinal_map = {'al': ['notpresent', 'trace', '1', '2', '3', '4', '5'],
    'su': ['notpresent', 'trace', '1', '2', '3', '4', '5']
}

encoder = OrdinalEncoder(categories=[ordinal_map['al'], ordinal_map['su']])
df_clean[ordinal_features] = encoder.fit_transform(df_clean[ordinal_features])

# 无序类别(如红细胞形态)用 One-Hot
nominal_features = ['rbc', 'pc']
df_clean = pd.get_dummies(df_clean, columns=nominal_features)

3.3 处理数据不平衡

from imblearn.over_sampling import SMOTE

X = df_clean.drop('classification', axis=1)
y = df_clean['classification'].map({'ckd':1, 'notckd':0})

# 使用 SMOTE 过采样
smote = SMOTE(random_state=42)
X_res, y_res = smote.fit_resample(X, y)
print(f'过采样后类别分布:\n{y_res.value_counts()}')

4. 建模示例

构建完整的建模 pipeline:

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split

# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(X_res, y_res, test_size=0.2, random_state=42)

# 构建 pipeline
pipe = Pipeline([('scaler', StandardScaler()),
    ('clf', RandomForestClassifier(
        n_estimators=100,
        class_weight='balanced',
        random_state=42
    ))
])

# 训练与评估
pipe.fit(X_train, y_train)
print(f'测试集准确率:{pipe.score(X_test, y_test):.2f}')

5. 避坑指南

处理医疗数据时需要特别注意:

  1. 特征泄露:确保预处理步骤(如填充缺失值)只在训练集上计算统计量
  2. 评估指标选择:准确率可能误导,优先考虑召回率、AUC-ROC
  3. 特征解释性:医疗模型需要可解释性,优先选择 SHAP 值等解释方法
  4. 数据标准化:不同检验指标量纲差异大,必须进行标准化

6. 延伸与练习

延伸阅读

  • 《医疗机器学习实战》第 4 章 数据预处理
  • SMOTE 算法原始论文
  • scikit-learn 文档中的 Pipeline 使用指南

实操练习

  1. 尝试不同的采样策略(如 ADASYN)比较效果
  2. 用 GridSearchCV 优化随机森林参数
  3. 添加特征选择步骤,观察模型性能变化

结语

通过本文的完整流程,我们实现了从原始医疗数据到可部署模型的转化。医疗数据处理需要格外谨慎,希望这些实践经验能帮助你在类似项目中少走弯路。记住,好的数据预处理往往比复杂的模型更能提升最终效果。

正文完
 0
评论(没有评论)