机器学习与数据加载实验报告
一、实验目的
- 掌握使用 scikit-learn 进行数据加载、预处理和划分的方法
- 熟悉 scikit-learn 中机器学习的基本流程和核心组件
- 学习使用 scikit-learn 处理结构化数据的基本技巧
二、实验环境
- Python 3.8+
- 主要库:pandas, numpy, scikit-learn, matplotlib, seaborn
三、scikit-learn 核心组件介绍
1. scikit-learn 模块结构
scikit-learn 提供了统一的API接口,主要包含以下核心模块:
# 数据预处理
from sklearn.preprocessing import StandardScaler, MinMaxScaler, LabelEncoder
# 模型选择
from sklearn.model_selection import train_test_split, cross_val_score, GridSearchCV
# 线性模型
from sklearn.linear_model import LinearRegression, LogisticRegression
# 树模型
from sklearn.tree import DecisionTreeRegressor, DecisionTreeClassifier
# 集成方法
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
# 聚类算法
from sklearn.cluster import KMeans, DBSCAN
# 模型评估
from sklearn.metrics import mean_squared_error, r2_score, accuracy_score, classification_report
2. scikit-learn 统一API设计
所有scikit-learn estimator都遵循统一的接口设计:
- fit(): 训练模型
- predict(): 进行预测
- score(): 评估模型
- transform(): 数据转换(预处理器)
四、数据加载与探索
1. 加载网约车司机数据集
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error, r2_score
# 加载数据
df = pd.read_excel("网约车司机单日工作情况.xlsx")
# 数据基本信息探索
print("数据集形状:", df.shape)
print("\n数据基本信息:")
print(df.info())
print("\n数据描述性统计:")
print(df.describe())
print("\n缺失值检查:")
print(df.isnull().sum())

2. 数据可视化分析
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 创建可视化图表
fig, axes = plt.subplots(2, 3, figsize=(15, 10))
# 车费收入分布
axes[0,0].hist(df['车费收入'], bins=30, alpha=0.7, color='skyblue')
axes[0,0].set_title('车费收入分布')
axes[0,0].set_xlabel('收入')
axes[0,0].set_ylabel('频数')
# 在线时长分布
axes[0,1].hist(df['在线时长'], bins=30, alpha=0.7, color='lightgreen')
axes[0,1].set_title('在线时长分布')
axes[0,1].set_xlabel('时长(小时)')
# 完成订单数分布
axes[0,2].hist(df['完成订单数'], bins=30, alpha=0.7, color='orange')
axes[0,2].set_title('完成订单数分布')
axes[0,2].set_xlabel('订单数')
# 收入与在线时长关系
axes[1,0].scatter(df['在线时长'], df['车费收入'], alpha=0.5)
axes[1,0].set_title('收入 vs 在线时长')
axes[1,0].set_xlabel('在线时长(小时)')
axes[1,0].set_ylabel('收入')
# 收入与订单数关系
axes[1,1].scatter(df['完成订单数'], df['车费收入'], alpha=0.5)
axes[1,1].set_title('收入 vs 完成订单数')
axes[1,1].set_xlabel('完成订单数')
axes[1,1].set_ylabel('收入')
# 相关性热力图
corr_matrix = df[['平均星级', '在线时长', '完成订单数', '订单实际总公里数', '车费收入']].corr()
sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', ax=axes[1,2])
axes[1,2].set_title('特征相关性热力图')
plt.tight_layout()
plt.show()

五、数据预处理与特征工程
1. 特征选择与数据划分
# 特征选择 - 排除司机编号(ID类特征)
features = ['平均星级', '在线时长', '完成订单数', '订单实际总公里数']
target = '车费收入'
X = df[features]
y = df[target]
print("特征矩阵形状:", X.shape)
print("目标变量形状:", y.shape)
# 数据划分 - 训练集80%,测试集20%
X_train, X_test, y_train, y_test = train_test_split(
X, y,
test_size=0.2,
random_state=42,
shuffle=True
)
print(f"训练集样本数: {X_train.shape[0]}")
print(f"测试集样本数: {X_test.shape[0]}")

2. 数据标准化
# 使用StandardScaler进行数据标准化
scaler = StandardScaler()
# 只在训练集上拟合scaler,然后转换训练集和测试集
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
print("标准化后的训练集统计:")
print(f"均值: {X_train_scaled.mean(axis=0)}")
print(f"标准差: {X_train_scaled.std(axis=0)}")

六、模型训练与评估
1. 线性回归模型
# 初始化线性回归模型
lr_model = LinearRegression()
# 训练模型
lr_model.fit(X_train_scaled, y_train)
# 预测
y_pred_lr = lr_model.predict(X_test_scaled)
# 评估模型
lr_mse = mean_squared_error(y_test, y_pred_lr)
lr_r2 = r2_score(y_test, y_pred_lr)
print("=== 线性回归模型表现 ===")
print(f"均方误差(MSE): {lr_mse:.2f}")
print(f"R² 分数: {lr_r2:.4f}")
# 特征重要性(系数)
feature_importance = pd.DataFrame({
'特征': features,
'系数': lr_model.coef_
}).sort_values('系数', key=abs, ascending=False)
print("\n特征系数:")
print(feature_importance)

2. 随机森林回归模型
# 初始化随机森林模型
rf_model = RandomForestRegressor(
n_estimators=100,
max_depth=10,
random_state=42
)
# 训练模型
rf_model.fit(X_train, y_train) # 树模型通常不需要标准化
# 预测
y_pred_rf = rf_model.predict(X_test)
# 评估模型
rf_mse = mean_squared_error(y_test, y_pred_rf)
rf_r2 = r2_score(y_test, y_pred_rf)
print("=== 随机森林模型表现 ===")
print(f"均方误差(MSE): {rf_mse:.2f}")
print(f"R² 分数: {rf_r2:.4f}")
# 特征重要性
rf_feature_importance = pd.DataFrame({
'特征': features,
'重要性': rf_model.feature_importances_
}).sort_values('重要性', ascending=False)
print("\n随机森林特征重要性:")
print(rf_feature_importance)

3. 模型对比可视化
# 模型对比
models_comparison = pd.DataFrame({
'模型': ['线性回归', '随机森林'],
'MSE': [lr_mse, rf_mse],
'R²': [lr_r2, rf_r2]
})
print("=== 模型性能对比 ===")
print(models_comparison)
# 预测结果可视化
plt.figure(figsize=(12, 5))
# 实际值 vs 预测值散点图
plt.subplot(1, 2, 1)
plt.scatter(y_test, y_pred_lr, alpha=0.5, label='线性回归')
plt.scatter(y_test, y_pred_rf, alpha=0.5, label='随机森林')
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'k--', lw=2)
plt.xlabel('实际值')
plt.ylabel('预测值')
plt.title('实际值 vs 预测值')
plt.legend()
# 残差图
plt.subplot(1, 2, 2)
residuals_lr = y_test - y_pred_lr
residuals_rf = y_test - y_pred_rf
plt.scatter(y_pred_lr, residuals_lr, alpha=0.5, label='线性回归残差')
plt.scatter(y_pred_rf, residuals_rf, alpha=0.5, label='随机森林残差')
plt.axhline(y=0, color='black', linestyle='--')
plt.xlabel('预测值')
plt.ylabel('残差')
plt.title('残差分析')
plt.legend()
plt.tight_layout()
plt.show()

七、scikit-learn 高级功能
1. 交叉验证
from sklearn.model_selection import cross_val_score
# 使用5折交叉验证评估模型
cv_scores_lr = cross_val_score(lr_model, X_train_scaled, y_train,
cv=5, scoring='r2')
cv_scores_rf = cross_val_score(rf_model, X_train, y_train,
cv=5, scoring='r2')
print("=== 交叉验证结果 ===")
print(f"线性回归交叉验证R²: {cv_scores_lr.mean():.4f} (+/- {cv_scores_lr.std() * 2:.4f})")
print(f"随机森林交叉验证R²: {cv_scores_rf.mean():.4f} (+/- {cv_scores_rf.std() * 2:.4f})")

2. 超参数调优
由于中文路径,设置指定目录
import os
import tempfile
from joblib import parallel_backend
# 设置一个纯英文路径的临时文件夹(例如 D:/temp_joblib)
# 确保该文件夹已存在,若不存在可先创建
os.environ["JOBLIB_TEMP_FOLDER"] = "D:/temp_joblib" # 替换为你的纯英文路径
# 可选:验证临时目录是否生效
print("临时文件夹路径:", os.environ.get("JOBLIB_TEMP_FOLDER"))
![]()
开始调优
from sklearn.model_selection import GridSearchCV
# 随机森林超参数搜索
param_grid = {
'n_estimators': [50, 100, 200],
'max_depth': [5, 10, 15, None],
'min_samples_split': [2, 5, 10]
}
grid_search = GridSearchCV(
RandomForestRegressor(random_state=42),
param_grid,
cv=5,
scoring='r2',
n_jobs=-1
)
grid_search.fit(X_train, y_train)
print("=== 最佳参数 ===")
print(grid_search.best_params_)
print(f"最佳交叉验证分数: {grid_search.best_score_:.4f}")
# 使用最佳参数重新训练
best_rf_model = grid_search.best_estimator_
y_pred_best_rf = best_rf_model.predict(X_test)
best_rf_r2 = r2_score(y_test, y_pred_best_rf)
print(f"调优后测试集R²: {best_rf_r2:.4f}")

八、实验总结与业务洞察
1. 技术总结
通过本实验,我们掌握了以下scikit-learn核心技能:
- 数据加载与探索:使用pandas加载数据,进行基本统计分析
- 数据预处理:使用StandardScaler进行特征标准化
- 模型训练:使用LinearRegression和RandomForestRegressor
- 模型评估:使用MSE和R²评估回归模型性能
- 高级功能:交叉验证、网格搜索超参数调优
2. 业务洞察
基于模型分析,我们发现:
- 关键影响因素:在线时长和完成订单数是影响司机收入的主要因素
- 模型选择:随机森林在该数据集上表现优于线性回归
- 优化建议:
- 提高司机在线时长的利用率
- 优化订单分配策略提高完成订单数
- 关注行驶里程的效率(单位里程收入)
3. 后续工作建议
- 特征工程:尝试创建新特征,如"每小时订单数"、"每公里收入"
- 模型扩展:尝试其他回归算法(梯度提升、支持向量机等)
- 聚类分析:使用无监督学习对司机进行分类
- 异常检测:识别异常工作模式的司机
附录:关键代码片段汇总
本实验所有关键代码已在上文中完整展示,可直接复制使用。建议在实际环境中逐步运行并理解每个步骤的作用。
更多推荐
所有评论(0)