Scikit-Learn 对糖尿病数据集(回归任务)进行全面分析

文章目录

背景

糖尿病数据集,442个样本,10个特征(年龄、血压等),目标为疾病进展值

该数据集为回归问题,需要使用回归分析方法进行分析

数据集速览

python 复制代码
import pandas as pd
from sklearn.datasets import load_diabetes

diabetes = load_diabetes()

# 将数据转换为 Pandas DataFrame 以便更好地查看
# features(特征)
df_features = pd.DataFrame(diabetes.data, columns=diabetes.feature_names)

# target(目标变量)
df_target = pd.DataFrame(diabetes.target, columns=['target'])

# 合并特征和目标变量为一个 DataFrame
df_diabetes = pd.concat([df_features, df_target], axis=1)

print("--- 数据集简要概览 ---")
print(f"数据形状 (行, 列): {df_diabetes.shape}")
print("\n数据集特征名称:")
print(diabetes.feature_names)
print("\n目标变量描述:")
print(diabetes.DESCR.split('\n')[-3]) # 提取目标变量的简要描述

print("\n--- 数据前5行预览 ---")
print(df_diabetes.head())

print("\n--- 数据信息 (类型和非空值) ---")
print(df_diabetes.info())
复制代码
--- 数据集简要概览 ---
数据形状 (行, 列): (442, 11)

数据集特征名称:
['age', 'sex', 'bmi', 'bp', 's1', 's2', 's3', 's4', 's5', 's6']

目标变量描述:
Bradley Efron, Trevor Hastie, Iain Johnstone and Robert Tibshirani (2004) "Least Angle Regression," Annals of Statistics (with discussion), 407-499.

--- 数据前5行预览 ---
        age       sex       bmi        bp        s1        s2        s3  \
0  0.038076  0.050680  0.061696  0.021872 -0.044223 -0.034821 -0.043401   
1 -0.001882 -0.044642 -0.051474 -0.026328 -0.008449 -0.019163  0.074412   
2  0.085299  0.050680  0.044451 -0.005670 -0.045599 -0.034194 -0.032356   
3 -0.089063 -0.044642 -0.011595 -0.036656  0.012191  0.024991 -0.036038   
4  0.005383 -0.044642 -0.036385  0.021872  0.003935  0.015596  0.008142   

         s4        s5        s6  target  
0 -0.002592  0.019907 -0.017646   151.0  
1 -0.039493 -0.068332 -0.092204    75.0  
2 -0.002592  0.002861 -0.025930   141.0  
3  0.034309  0.022688 -0.009362   206.0  
4 -0.002592 -0.031988 -0.046641   135.0  

--- 数据信息 (类型和非空值) ---
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 442 entries, 0 to 441
Data columns (total 11 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   age     442 non-null    float64
 1   sex     442 non-null    float64
 2   bmi     442 non-null    float64
 3   bp      442 non-null    float64
 4   s1      442 non-null    float64
 5   s2      442 non-null    float64
 6   s3      442 non-null    float64
 7   s4      442 non-null    float64
 8   s5      442 non-null    float64
 9   s6      442 non-null    float64
 10  target  442 non-null    float64
dtypes: float64(11)
memory usage: 38.1 KB
None

这份数据集共有 10 个特征
它们都是经过预处理和标准化的浮点数值,具体含义如下:
1. age: 年龄(years)
2. sex: 性别
3. bmi: 身体质量指数(body mass index)
4. bp: 平均血压(average blood pressure)
5. s1: T-细胞(T-cells)
6. s2: 低密度脂蛋白(LDL)
7. s3: 高密度脂蛋白(HDL)
8. s4: 甲状腺刺激素(TSH)
9. s5: 血糖(blood sugar)
10. s6: 淋巴细胞(lymphocytes)

分析方法

  • 线性回归
  • K近邻(KNN)
  • 决策树
  • 支持向量机
  • 随机森林
  • 多层感知器(MLP)
  • Lasso 回归
  • Ridge 回归
  • 梯度提升回归
  • AdaBoost 回归
  • Huber 回归

分析步骤

  1. 加载数据集
  2. 拆分训练集、测试集
  3. 数据预处理(标准化)
  4. 选择模型
  5. 模型训练(拟合)
  6. 测试模型效果
  7. 评估模型

分析结果

不同模型的预测值 vs 真实值效果对比

残差图

特征重要性

预测值分布

不同模型评估明细

复制代码
--- 数据集概览 ---
数据形状: (442, 10)
特征名称: ['age', 'sex', 'bmi', 'bp', 's1', 's2', 's3', 's4', 's5', 's6']
目标变量名称: 糖尿病病程进展

--- 数据划分结果 ---
训练集形状: (309, 10)
测试集形状: (133, 10)

--- 正在对数据进行标准化处理 ---

--- 模型训练与评估 ---

--- 正在训练 线性回归 模型 ---
线性回归 模型的均方误差 (MSE): 2821.7510
线性回归 模型的 R^2 得分: 0.4773

--- 正在训练 K近邻 (K-NN) 模型 ---
K近邻 (K-NN) 模型的均方误差 (MSE): 3277.7368
K近邻 (K-NN) 模型的 R^2 得分: 0.3928

--- 正在训练 决策树 模型 ---
决策树 模型的均方误差 (MSE): 5686.6015
决策树 模型的 R^2 得分: -0.0534

--- 正在训练 支持向量机 (SVR) 模型 ---
支持向量机 (SVR) 模型的均方误差 (MSE): 2822.7007
支持向量机 (SVR) 模型的 R^2 得分: 0.4771

--- 正在训练 随机森林 模型 ---
随机森林 模型的均方误差 (MSE): 2859.3911
随机森林 模型的 R^2 得分: 0.4703

--- 正在训练 多层感知器 (MLP) 模型 ---
/opt/anaconda3/lib/python3.13/site-packages/sklearn/neural_network/_multilayer_perceptron.py:691: ConvergenceWarning: Stochastic Optimizer: Maximum iterations (20000) reached and the optimization hasn't converged yet.
  warnings.warn(
多层感知器 (MLP) 模型的均方误差 (MSE): 4791.4414
多层感知器 (MLP) 模型的 R^2 得分: 0.1124

--- 正在训练 Lasso 回归 模型 ---
Lasso 回归 模型的均方误差 (MSE): 2817.0876
Lasso 回归 模型的 R^2 得分: 0.4782

--- 正在训练 Ridge 回归 模型 ---
Ridge 回归 模型的均方误差 (MSE): 2819.9820
Ridge 回归 模型的 R^2 得分: 0.4776

--- 正在训练 梯度提升回归 模型 ---
梯度提升回归 模型的均方误差 (MSE): 3083.3332
梯度提升回归 模型的 R^2 得分: 0.4288

--- 正在训练 AdaBoost 回归 模型 ---
AdaBoost 回归 模型的均方误差 (MSE): 2874.6206
AdaBoost 回归 模型的 R^2 得分: 0.4675

--- 正在训练 Huber 回归 模型 ---
Huber 回归 模型的均方误差 (MSE): 2828.7736
Huber 回归 模型的 R^2 得分: 0.4760

所有模型的分析已完成。

代码

python 复制代码
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsRegressor
from sklearn.tree import DecisionTreeRegressor
from sklearn.svm import SVR
from sklearn.linear_model import LinearRegression, Lasso, Ridge, HuberRegressor
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor, AdaBoostRegressor
from sklearn.neural_network import MLPRegressor
from sklearn.metrics import mean_squared_error, r2_score
import numpy as np
import matplotlib.pyplot as plt

# 设置 Matplotlib 字体以正确显示中文
plt.rcParams['font.sans-serif'] = ['SimHei', 'WenQuanYi Zen Hei', 'STHeiti', 'Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False 

def perform_diabetes_analysis():
    """
    使用 scikit-learn 对糖尿病数据集进行全面的分析。
    该函数包含数据加载、预处理、模型训练、评估和结果可视化。
    """
    print("--- 正在加载糖尿病数据集 ---")
    diabetes = load_diabetes()
    
    X = diabetes.data
    y = diabetes.target
    feature_names = list(diabetes.feature_names)

    print("\n--- 数据集概览 ---")
    print(f"数据形状: {X.shape}")
    print(f"特征名称: {feature_names}")
    print(f"目标变量名称: {'糖尿病病程进展'}")

    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

    print("\n--- 数据划分结果 ---")
    print(f"训练集形状: {X_train.shape}")
    print(f"测试集形状: {X_test.shape}")
    
    print("\n--- 正在对数据进行标准化处理 ---")
    scaler = StandardScaler()
    X_train_scaled = scaler.fit_transform(X_train)
    X_test_scaled = scaler.transform(X_test)
    
    models = {
        "线性回归": LinearRegression(),
        "K近邻 (K-NN)": KNeighborsRegressor(n_neighbors=5),
        "决策树": DecisionTreeRegressor(random_state=42),
        "支持向量机 (SVR)": SVR(kernel='rbf', C=100),
        "随机森林": RandomForestRegressor(random_state=42),
        "多层感知器 (MLP)": MLPRegressor(random_state=42, max_iter=20000),
        "Lasso 回归": Lasso(alpha=0.1, max_iter=10000),
        "Ridge 回归": Ridge(alpha=1.0, max_iter=10000),
        "梯度提升回归": GradientBoostingRegressor(random_state=42),
        "AdaBoost 回归": AdaBoostRegressor(random_state=42),
        "Huber 回归": HuberRegressor(max_iter=10000)
    }

    predictions = {}
    feature_importances = {}

    print("\n--- 模型训练与评估 ---")
    for name, model in models.items():
        print(f"\n--- 正在训练 {name} 模型 ---")
        model.fit(X_train_scaled, y_train)
        y_pred = model.predict(X_test_scaled)
        
        mse = mean_squared_error(y_test, y_pred)
        r2 = r2_score(y_test, y_pred)
        
        print(f"{name} 模型的均方误差 (MSE): {mse:.4f}")
        print(f"{name} 模型的 R^2 得分: {r2:.4f}")
        
        predictions[name] = y_pred

        if hasattr(model, 'feature_importances_'):
            feature_importances[name] = model.feature_importances_
        
    print("\n所有模型的分析已完成。")

    # --- 预测值 vs. 实际值可视化 ---
    print("\n--- 预测值 vs. 实际值散点图 ---")
    num_models = len(models)
    cols = 3
    rows = (num_models + cols - 1) // cols
    fig, axes = plt.subplots(rows, cols, figsize=(18, 6 * rows))
    axes = axes.flatten()

    for i, name in enumerate(models.keys()):
        ax = axes[i]
        y_pred = predictions[name]
        
        ax.scatter(y_test, y_pred, alpha=0.6, label='预测值')
        lims = [
            np.min([ax.get_xlim(), ax.get_ylim()]),
            np.max([ax.get_xlim(), ax.get_ylim()]),
        ]
        ax.plot(lims, lims, 'k--', alpha=0.75, zorder=0, label='理想预测')
        
        ax.set_title(f'{name} - 预测值 vs. 实际值', fontsize=14)
        ax.set_xlabel('实际病程进展', fontsize=12)
        ax.set_ylabel('预测病程进展', fontsize=12)
        ax.legend()
        ax.grid(True)
    
    for j in range(num_models, len(axes)):
        axes[j].axis('off')

    plt.tight_layout()
    plt.show()

    # --- 残差图可视化 ---
    print("\n--- 残差图可视化 ---")
    fig, axes = plt.subplots(rows, cols, figsize=(18, 6 * rows))
    axes = axes.flatten()
    
    for i, name in enumerate(models.keys()):
        ax = axes[i]
        y_pred = predictions[name]
        residuals = y_test - y_pred
        
        ax.scatter(y_pred, residuals, alpha=0.6)
        ax.axhline(y=0, color='r', linestyle='--', linewidth=2)
        
        ax.set_title(f'{name} - 残差图', fontsize=14)
        ax.set_xlabel('预测值', fontsize=12)
        ax.set_ylabel('残差 (实际值 - 预测值)', fontsize=12)
        ax.grid(True)
    
    for j in range(num_models, len(axes)):
        axes[j].axis('off')

    plt.tight_layout()
    plt.show()

    # --- 特征重要性可视化 (仅限树模型) ---
    if feature_importances:
        print("\n--- 特征重要性可视化 ---")
        num_tree_models = len(feature_importances)
        rows_tree = (num_tree_models + cols - 1) // cols
        fig, axes = plt.subplots(rows_tree, cols, figsize=(18, 6 * rows_tree))
        axes = axes.flatten()

        for i, (name, importances) in enumerate(feature_importances.items()):
            ax = axes[i]
            sorted_indices = np.argsort(importances)[::-1]
            sorted_importances = importances[sorted_indices]
            sorted_feature_names = [feature_names[j] for j in sorted_indices]

            ax.barh(sorted_feature_names, sorted_importances, color='skyblue')
            ax.set_title(f'{name} - 特征重要性', fontsize=14)
            ax.set_xlabel('重要性', fontsize=12)
            ax.set_ylabel('特征', fontsize=12)
            ax.grid(axis='x')
        
        for j in range(num_tree_models, len(axes)):
            axes[j].axis('off')
            
        plt.tight_layout()
        plt.show()

    # --- 预测值分布图可视化 ---
    print("\n--- 预测值分布图 ---")
    fig, axes = plt.subplots(rows, cols, figsize=(18, 6 * rows))
    axes = axes.flatten()
    
    all_values = np.concatenate([y_test] + list(predictions.values()))
    bins = np.linspace(min(all_values), max(all_values), 50)

    for i, name in enumerate(models.keys()):
        ax = axes[i]
        y_pred = predictions[name]
        
        ax.hist(y_test, bins=bins, alpha=0.6, label='实际值', color='b', edgecolor='k')
        ax.hist(y_pred, bins=bins, alpha=0.6, label='预测值', color='r', edgecolor='k')
        
        ax.set_title(f'{name} - 分布图', fontsize=14)
        ax.set_xlabel('病程进展', fontsize=12)
        ax.set_ylabel('频率', fontsize=12)
        ax.legend()
        ax.grid(True)
    
    for j in range(num_models, len(axes)):
        axes[j].axis('off')

    plt.tight_layout()
    plt.show()

if __name__ == "__main__":
    perform_diabetes_analysis()
相关推荐
xchenhao2 小时前
Scikit-learn 对加州房价数据集(回归任务)进行全面分析
python·决策树·机器学习·回归·数据集·scikit-learn·knn
这里有鱼汤2 小时前
发现一个高性能回测框架,Python + Rust,比 backtrader 快 250 倍?小团队必备!
后端·python
☼←安于亥时→❦2 小时前
数据分析之Pandas入门小结
python·pandas
deephub2 小时前
机器人逆运动学进阶:李代数、矩阵指数与旋转流形计算
人工智能·机器学习·矩阵·机器人·李群李代数
带娃的IT创业者2 小时前
《Python Web部署应知应会》No3:Flask网站的性能优化和实时监测深度实战
前端·python·flask
赴3352 小时前
图像拼接案例,抠图案例
人工智能·python·计算机视觉
明月照山海-2 小时前
机器学习周报十三
人工智能·机器学习·概率论
从零开始学习人工智能2 小时前
机器学习模型可信度与交叉验证:通俗讲解
人工智能·机器学习
TwoAI2 小时前
Scikit-learn 机器学习:构建、训练与评估预测模型
python·机器学习·scikit-learn