机器学习——需求预测+PCA+随机森林算法+shap可解释性分析+多模型性能对比

1 数据集介绍

  1. 自行车共享租赁过程与环境和季节设置高度相关。例如,天气状况、降水、星期几、季节、一天中的小时等都会影响租赁行为。
  2. 数据集特征
  • instant:记录索引

  • dteday:日期

  • season:季节(1:春季,2:夏季,3:秋季,4:冬季)

  • yr:年份(0:2011 年,1:2012 年)

  • mnth:月份(1 到 12)

  • hr:小时(0 到 23)

  • holiday:是否为假日(从 DC 政府假日安排 提取)

  • weekday:星期几

  • workingday:如果一天既不是周末也不是假日,则为 1,否则为 0

  • weathersit

    • 1:晴朗、少量云、部分多云

    • 2:雾 + 多云、雾 + 破碎云、雾 + 少量云、雾

    • 3:小雪、小雨 + 雷暴 + 散云、小雨 + 散云

    • 4:大雨 + 冰雹 + 雷暴 + 雾、雪 + 雾

  • temp:按摄氏度归一化的温度。值除以 41(最大值)

  • atemp:按摄氏度归一化的体感温度。值除以 50(最大值)

  • hum:按 100(最大值)归一化的湿度

  • windspeed:按 67(最大值)归一化的风速

  • casual:临时用户数量

  • registered:注册用户数量

  • cnt:包括临时用户和注册用户的总租赁自行车数量

2.整体思路

  • 数据清洗

    移除冗余字段,处理缺失值。

  • 特征工程

    对分类变量进行字符映射,增强可读性。

  • EDA

    通过可视化分析变量分布及关联性。

  • 预处理

    独热编码、数据拆分、归一化。

  • 降维

    使用 PCA 减少特征维度。

  • 模型训练

    应用多种回归模型,评估性能。

  • 模型解释

    通过 SHAP 值解析特征影响。


3. 代码解析

3.1. 库导入与数据加载
python 复制代码
# 基础数据处理与数学计算库
import numpy as np
import pandas as pd

# 数据可视化库
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(rc={'axes.facecolor':'#c5c6c7'})  # 设置图表背景色

# 机器学习工具库
from sklearn.model_selection import train_test_split  # 数据拆分
from sklearn.preprocessing import MinMaxScaler  # 数据归一化
from sklearn.decomposition import PCA, IncrementalPCA  # 主成分分析
from sklearn.metrics import r2_score  # 模型评估

# 忽略警告信息
import warnings
warnings.filterwarnings("ignore")

# 加载数据并展示前5行(带颜色渐变效果)
df = pd.read_csv(r"2025-2-24-公众号python机器学习ml-predicting-rider-count.csv")
df.head().style.background_gradient(cmap='bone')  # cmap指定渐变色谱

# 打印数据维度
df.shape  # 返回 (行数, 列数)

关键点说明

  • sns.set()

    统一调整 seaborn 图表样式,#c5c6c7 是十六进制灰色代码。

  • background_gradient

    通过颜色深浅直观显示数值大小。


3.2. 数据清洗
python 复制代码
# 删除冗余列
cols_to_drop = ['dteday','instant','casual','registered']  # 待删除列名列表
df.drop(columns=cols_to_drop, axis=1, inplace=True)  # axis=1表示按列删除

# 分类变量数值映射(增强可解释性)
mappings = {
    'season': {1:"Winter", 2:"Spring", 3:"Summer", 4:"Fall"},
    'weekday': {0:"Saturday", 1:"Sunday", 2:"Monday", 3:"Tuesday", 
                4:"Wednesday", 5:"Thursday", 6:"Friday"},
    'mnth': {1:"Jan",2:"Feb",3:"Mar",4:"Apr",5:"May",6:"Jun",
             7:"Jul",8:"Aug",9:"Sep",10:"Oct",11:"Nov",12:"Dec"},
    'weathersit': {1:"Clear",2:"Cloudy",3:"LightRain",4:"Snow_Thunderstorm"}
}

for col, map_dict in mappings.items():
    df[col] = df[col].map(map_dict)  # 将数字编码转为可读字符串

# 检查数据基本信息
df.info()  # 显示各列的非空计数、数据类型,快速定位缺失值

代码优化说明

  • 使用字典 mappings 统一管理映射关系,提高代码可维护性。

  • df.info()

    可快速发现数据缺失情况(若输出显示某列非空计数小于总行数,则存在缺失值)。


3.3. 探索性分析 (EDA)

分类变量条形图

python 复制代码
# 提取数值型与字符型列名
num_cols = list(df.select_dtypes(["int64","float64"]))  # 数值列
cat_cols = list(df.select_dtypes("object"))  # 分类列

# 分类变量可视化
fig, axes = plt.subplots(nrows=4, figsize=(16,28))  # 创建4个子图

colors = ('#17252a', '#2b7a78','#3aafa9','#def2f1','#feffff')  # 自定义颜色序列

for idx, col inenumerate(['season','mnth','weekday','weathersit']):
    ax = axes[idx]
    sns.barplot(
        x=df[col], 
        y=df['cnt'], 
        ax=ax, 
        palette=colors, 
        edgecolor="#c5c6c7", 
        ci=95# 显示95%置信区间
    )
    ax.set_ylabel(col, fontsize=16)  # 设置y轴标签为分类变量名
    ax.tick_params(left=False, labelleft=False)  # 隐藏左侧刻度
    ax.bar_label(ax.containers[0], fmt='%.0f', size=12)  # 在柱子上显示均值

plt.tight_layout()  # 自动调整子图间距
plt.show()

数值变量回归图

python 复制代码
plt.figure(figsize=(16,12))

# 绘制四个子图:temp, atemp, hum, windspeed 与 cnt 的关系
features = ['temp', 'atemp', 'hum', 'windspeed']
colors = ["#00008B", "#006400", "#800080", "#8B4513"]  # 海军蓝、深绿、紫色、棕色

for i, (feat, color) inenumerate(zip(features, colors)):
    plt.subplot(2,2,i+1)
    sns.regplot(
        x=feat, 
        y='cnt', 
        data=df, 
        color=color,
        scatter_kws={'alpha':0.3},  # 散点透明度
        line_kws={'lw':2}  # 回归线粗细
    )
    plt.xlabel(feat.capitalize())

plt.tight_layout()
plt.show()

热力图分析相关性

python 复制代码
plt.figure(figsize=(16,8))
sns.heatmap(
    df.corr(), 
    cmap="viridis",  # 颜色映射
    annot=True,  # 显示数值
    fmt=".2f",  # 数值格式化为两位小数
    annot_kws={'size':12}  # 数值标签字号
)
plt.xticks(size=14)
plt.yticks(size=14, rotation=0)  # 保持y轴标签水平
plt.title("Feature Correlation Matrix", pad=20, fontsize=18)
plt.show()

关键分析点

  • 高相关性特征(如 tempatemp)可能需合并或剔除,避免多重共线性。

  • 通过回归图斜率判断特征与目标变量的正/负相关关系。


3.4. 数据预处理

独热编码

python 复制代码
# 对每个分类变量生成哑变量(drop_first=True 避免多重共线性)
for col in cat_cols:
    dummies = pd.get_dummies(df[col], prefix=col, drop_first=True)
    df = pd.concat([df, dummies], axis=1)
    df.drop(col, axis=1, inplace=True)  # 删除原始分类列

数据集拆分

python 复制代码
y = df.pop('cnt')  # 提取目标变量
X = df  # 特征矩阵
X_train, X_test, y_train, y_test = train_test_split(
    X, y, 
    train_size=0.7,  # 70%训练集
    random_state=69  # 固定随机种子保证可复现性
)

归一化处理

python 复制代码
scaler = MinMaxScaler()  # 初始化归一化器
X_train_scaled = scaler.fit_transform(X_train)  # 训练集拟合并转换
X_test_scaled = scaler.transform(X_test)  # 测试集仅转换(避免数据泄露)

3.5. 主成分分析 (PCA)

累计方差图确定主成分数

python 复制代码
pca = PCA(random_state=69)
pca.fit(X_train_scaled)

# 计算累计方差贡献率
explained_variance = pca.explained_variance_ratio_ * 100
cumulative_variance = np.cumsum(explained_variance)

plt.figure(figsize=(10,6))
plt.plot(range(1, len(cumulative_variance)+1), cumulative_variance, 
         marker='o', color='#9B1D20', markersize=8)
plt.axvline(17, color='red', linestyle='--', label='17 Components')
plt.axhline(92, color='blue', linestyle='--', label='92% Variance')
plt.xlabel("Number of Principal Components", fontsize=12)
plt.ylabel("Cumulative Explained Variance (%)", fontsize=12)
plt.legend()
plt.grid(axis='y')
plt.show()

降维处理

python 复制代码
# 使用增量PCA(适合大数据集)
pca_final = IncrementalPCA(n_components=17)
X_train_pca = pca_final.fit_transform(X_train_scaled)
X_test_pca = pca_final.transform(X_test_scaled)

3.6. 模型训练与评估
python 复制代码
# 定义评估函数
defevaluate_model(model, X_train, y_train, X_test, y_test):
    model.fit(X_train, y_train)
    y_pred = model.predict(X_test)
    return {
        'MSE': mean_squared_error(y_test, y_pred),
        'MAE': mean_absolute_error(y_test, y_pred),
        'R²': r2_score(y_test, y_pred)
    }

# 初始化模型
models = {
    "Linear Regression": LinearRegression(),
    "Support Vector Regression": SVR(kernel='rbf'),
    "Random Forest": RandomForestRegressor(n_estimators=100, random_state=123),
    "XGBoost": XGBRegressor(n_estimators=100, random_state=123)
}

# 训练并评估模型
results = {}
for name, model in models.items():
    results[name] = evaluate_model(model, X_train_pca, y_train, X_test_pca, y_test)

# 结果转DataFrame并打印
results_df = pd.DataFrame(results).T
print(results_df.round(3))  # 保留3位小数

# 绘制评估指标对比图
results_df.plot(kind='bar', subplots=True, layout=(1,3), 
                figsize=(18,6), legend=False, edgecolor='black')
plt.suptitle("Model Performance Comparison", y=1.02)
plt.tight_layout()
plt.show()

关键点说明

  • evaluate_model

    函数封装了训练和评估流程,提升代码复用性。

  • XGBoost

    需注意参数 n_estimators(树的数量)对性能的影响。


3.7. 模型解释 (SHAP)
复制代码
python 复制代码
# 初始化随机森林解释器
rf_model = models["Random Forest"]
explainer = shap.TreeExplainer(rf_model)

# 计算SHAP值(使用降维后的测试数据)
shap_values = explainer.shap_values(X_test_pca)

# 特征重要性总览(需传递原始特征名)
shap.summary_plot(
    shap_values, 
    features=X_test_pca, 
    feature_names=X.columns,  # 原始特征名
    plot_type='bar'
)

# 具体特征依赖图(示例:temp)
shap.dependence_plot(
    "temp", 
    shap_values, 
    X_test_pca, 
    feature_names=X.columns,
    interaction_index=None# 不显示交互效应
)
相关推荐
Hello.Reader1 小时前
Rust 并发编程:使用消息传递进行线程间数据共享
c++·算法·rust
大脑经常闹风暴@小猿1 小时前
leetcode 题目解析 第3题 无重复字符的最长子串
linux·算法·leetcode
bee-y3 小时前
力扣hot100刷题——11~20
算法·leetcode
Smile灬凉城6664 小时前
排序算法适合的场景
算法
悄悄敲敲敲5 小时前
C++:dfs,bfs各两则
算法·深度优先
88号技师5 小时前
2025年2月最新SCI-中华穿山甲优化算法Chinese Pangolin Optimizer-附Matlab免费代码
开发语言·算法·matlab·优化算法
Vacant Seat5 小时前
矩阵-旋转图像
java·数据结构·算法·矩阵
柃歌5 小时前
【UCB CS 61B SP24】Lecture 14 - Data Structures 1: Disjoint Sets学习笔记
java·数据结构·笔记·学习·算法