Scikit-learn 对加州房价数据集(回归任务)进行全面分析

背景

加利福尼亚房价数据集 fetch_california_housing,20640个样本,8个特征(人口、收入等),目标为房价中位数

该数据集是一个回归问题,需要运用回归任务的分析方法进行分析

分析方法

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

分析步骤

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

分析结果

不同模型的预测值 vs 真实值

残差图

特征重要性对比

预测值分布

不同模型评估明细

复制代码
--- 正在加载加州房价数据集 ---

--- 数据集概览 ---
数据形状: (20640, 8)
特征名称: ['MedInc', 'HouseAge', 'AveRooms', 'AveBedrms', 'Population', 'AveOccup', 'Latitude', 'Longitude']
目标变量名称: MedHouseVal

--- 数据划分结果 ---
训练集形状: (14448, 8)
测试集形状: (6192, 8)

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

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

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

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

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

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

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

--- 正在训练 多层感知器 (MLP) 模型 ---
多层感知器 (MLP) 模型的均方误差 (MSE): 0.2897
多层感知器 (MLP) 模型的 R^2 得分: 0.7793

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

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

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

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

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

所有模型的分析已完成。

代码

注:如果遇到下载数据集失败(HTTP 403),可参考此博文 https://blog.csdn.net/xchenhao/article/details/151373379

python 复制代码
from sklearn.datasets import fetch_california_housing

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
from sklearn.ensemble import RandomForestRegressor
from sklearn.neural_network import MLPRegressor
from sklearn.linear_model import Lasso, Ridge
from sklearn.ensemble import GradientBoostingRegressor, AdaBoostRegressor
from sklearn.linear_model import HuberRegressor

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_housing_analysis():
    """
    使用 scikit-learn 对加州房价数据集进行全面的分析。
    该函数包含数据加载、预处理、模型训练、评估和结果可视化。
    """
    print("--- 正在加载加州房价数据集 ---")
    # 加载加州房价数据集
    housing = fetch_california_housing(as_frame=True)
    
    # 获取数据特征和目标标签
    X = housing.data
    y = housing.target
    feature_names = list(X.columns)

    print("\n--- 数据集概览 ---")
    print(f"数据形状: {X.shape}")
    print(f"特征名称: {feature_names}")
    print(f"目标变量名称: {housing.target.name}")

    # 将数据集划分为训练集和测试集
    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=10000),
        "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()
    
    # 找到所有预测值和实际值的全局范围,以便所有子图的X轴一致
    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_housing_analysis()
相关推荐
这里有鱼汤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
max5006003 小时前
OpenSTL PredRNNv2 模型复现与自定义数据集训练
开发语言·人工智能·python·深度学习·算法