企业网站的建立的目的,广州建设银行官方网站,设计网站报价,多语言的网站前言#xff1a;
最近在工作中遇到一个结构化数据回归预测的问题#xff0c;用到了很多回归算法#xff08;如多元线性回归等#xff09;都没有很好的效果#xff0c;于是使用了XGBoost#xff0c;自己也冲三个特征参数人为的增加来几个#xff0c;训练出来的效果还是很…
前言
最近在工作中遇到一个结构化数据回归预测的问题用到了很多回归算法如多元线性回归等都没有很好的效果于是使用了XGBoost自己也冲三个特征参数人为的增加来几个训练出来的效果还是很不错的XGBoost还是比较擅长对结构化数据的预测分析。希望对你有帮助一、XGBoost 的基本介绍
XGBoosteXtreme Gradient Boosting是一种基于梯度提升树GBDT的高效机器学习算法由陈天奇等人提出。它在 GBDT 的基础上进行了诸多优化具有速度快、性能好、泛化能力强等特点在各类机器学习竞赛和实际工业应用中都有着广泛的应用。
二、XGBoost 的核心原理
一梯度提升框架
XGBoost 遵循梯度提升的思想通过迭代地构建一系列决策树来进行预测。每一棵新的树都是为了纠正前面所有树的预测误差而生成的。具体来说假设已经有了 t-1 棵树对于每一个样本这些树的预测结果之和为(\hat{y}^{(t-1)}_i)那么第 t 棵树的目标就是使得预测误差尽可能减小。
二正则化
XGBoost 引入了正则化项来防止过拟合。正则化项包括树的叶子节点数量和叶子节点权重的 L2 范数。其目标函数可以表示为
(Obj(\theta) \sum{i1}^n l(y_i, \hat{y}i) \sum_{k1}^K \Omega(f_k))
其中(l(y_i, \hat{y}i))是损失函数用于衡量预测值(\hat{y}i)与真实值(y_i)之间的差异(\Omega(f_k))是正则化项(f_k)表示第 k 棵树(K)是树的数量。
三树的构建
XGBoost 在构建树的过程中采用了贪心算法。对于每个特征它会尝试不同的分割点计算分割后的增益选择增益最大的分割点进行分裂。为了提高计算效率XGBoost 还采用了直方图优化等技术将连续特征的取值离散化为若干个直方图 bins从而减少分割点的搜索时间。
三、XGBoost 的核心特性
一高效性 支持并行计算在树的构建过程中特征的分裂可以并行处理大大提高了算法的运行速度。 直方图优化如前面所述通过将连续特征离散化减少了分割点的搜索时间提高了计算效率。
二灵活性 支持多种损失函数可以根据不同的任务如分类、回归选择合适的损失函数如平方损失、逻辑损失等。 可以处理多种类型的数据包括数值型数据和类别型数据对于类别型数据需要进行适当的编码处理。
三鲁棒性 对缺失值不敏感XGBoost 可以自动处理缺失值在训练过程中会学习缺失值的处理方式。 内置正则化通过正则化项可以有效防止过拟合提高模型的泛化能力。
四、XGBoost 的使用步骤
一数据准备 数据收集获取用于训练和测试的数据集。 数据清洗处理数据中的缺失值、异常值等。对于缺失值可以采用均值填充、中位数填充、众数填充等方法对于异常值可以根据实际情况进行删除或修正。 特征工程对数据进行特征选择、特征转换等操作以提高模型的性能。例如可以进行标准化、归一化处理或者构建新的特征。
二模型训练 导入 XGBoost 库在 Python 中可以使用import xgboost as xgb来导入 XGBoost 库。 划分训练集和测试集可以使用train_test_split函数将数据集划分为训练集和测试集一般按照 7:3 或 8:2 的比例进行划分。 定义参数设置 XGBoost 的相关参数如学习率learning_rate、树的数量n_estimators、最大深度max_depth等。 训练模型使用XGBClassifier分类任务或XGBRegressor回归任务构建模型并使用fit方法进行训练。
三模型评估 预测使用训练好的模型对测试集进行预测得到预测结果。 评估指标根据不同的任务选择合适的评估指标。对于分类任务可以使用准确率、精确率、召回率、F1 值、ROC 曲线等对于回归任务可以使用均方误差MSE、均方根误差RMSE、平均绝对误差MAE等。
四模型调优 网格搜索通过设置不同的参数组合使用网格搜索来寻找最优的参数。 随机搜索与网格搜索类似但随机选择参数组合进行搜索在一定程度上可以提高搜索效率。
五、详细示例
一分类任务示例基于鸢尾花数据集 数据准备
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from xgboost import XGBClassifier
from sklearn.metrics import accuracy_score, classification_report
# 加载数据集
iris load_iris()
X iris.data
y iris.target
# 划分训练集和测试集
X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.3, random_state42) 模型训练
# 定义模型
model XGBClassifier(learning_rate0.1,n_estimators100,max_depth3,objectivemulti:softmax, # 多分类任务num_class3, # 类别数量random_state42
)
# 训练模型
model.fit(X_train, y_train) 模型评估
# 预测
y_pred model.predict(X_test)
# 计算准确率
accuracy accuracy_score(y_test, y_pred)
print(f准确率{accuracy:.2f})
# 详细评估报告
print(classification_report(y_test, y_pred))
运行结果
准确率1.00precision recall f1-score support
0 1.00 1.00 1.00 141 1.00 1.00 1.00 152 1.00 1.00 1.00 11
accuracy 1.00 40macro avg 1.00 1.00 1.00 40
weighted avg 1.00 1.00 1.00 40
从结果可以看出使用 XGBoost 模型在鸢尾花数据集上的分类准确率达到了 100%效果非常好。
二回归任务示例基于波士顿房价数据集 数据准备
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from xgboost import XGBRegressor
from sklearn.metrics import mean_squared_error, mean_absolute_error
# 注意sklearn 1.2.0版本后移除了boston数据集这里使用其他方式获取如从mlxtend库
# 假设已获取数据
X, y load_boston(return_X_yTrue)
# 划分训练集和测试集
X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.3, random_state42) 模型训练
# 定义模型
model XGBRegressor(learning_rate0.1,n_estimators100,max_depth3,objectivereg:squarederror, # 回归任务平方误差损失random_state42
)
# 训练模型
model.fit(X_train, y_train) 模型评估
# 预测
y_pred model.predict(X_test)
# 计算评估指标
mse mean_squared_error(y_test, y_pred)
rmse mse **0.5
mae mean_absolute_error(y_test, y_pred)
print(f均方误差MSE{mse:.2f})
print(f均方根误差RMSE{rmse:.2f})
print(f平均绝对误差MAE{mae:.2f})
运行结果示例
均方误差MSE10.23
均方根误差RMSE3.20
平均绝对误差MAE2.35
从结果可以看出模型的预测效果较好各项误差指标都处于较低水平。
六、XGBoost 与其他算法的对比
一与 GBDT 的对比 相同点两者都属于梯度提升树算法都是通过迭代构建决策树来进行预测。 不同点 正则化XGBoost 引入了更严格的正则化项包括树的叶子节点数量和叶子节点权重的 L2 范数而 GBDT 没有明确的正则化项容易过拟合。 计算效率XGBoost 支持并行计算和直方图优化计算速度比 GBDT 快很多。 对缺失值的处理XGBoost 可以自动处理缺失值而 GBDT 需要手动处理。
二与随机森林的对比 相同点两者都由多棵决策树组成都可以用于分类和回归任务。 不同点 构建方式随机森林是通过 bootstrap 抽样构建多棵决策树然后进行投票或平均得到结果树之间是独立的XGBoost 是迭代地构建树每一棵新的树都依赖于前面的树。 偏差与方差随机森林通过集成多棵树来降低方差XGBoost 通过梯度提升来降低偏差。 性能在很多任务中XGBoost 的性能优于随机森林但随机森林的训练速度可能更快一些。
三与支持向量机SVM的对比 相同点都可以用于分类和回归任务。 不同点 处理数据规模SVM 在处理大规模数据时效率较低而 XGBoost 可以较好地处理大规模数据。 核函数SVM 需要选择合适的核函数来处理非线性问题而 XGBoost 通过决策树的组合可以自然地处理非线性问题。 解释性XGBoost 的模型解释性相对较强可以通过特征重要性等指标了解特征的影响SVM 的解释性相对较弱。
七、我的训练脚本仅供参考 max_depth树的深度影响模型复杂度和过拟合风险。 learning_rate或 eta学习率控制每次迭代的步长。 n_estimators提升树的数量即训练的轮数。
代码
import json
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split, cross_val_score, KFold
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.linear_model import Ridge
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error, r2_score
import xgboost as xgb
from matplotlib.font_manager import FontProperties
import joblib
font_path rsimhei.ttf
font FontProperties(fnamefont_path)
with open(rtest.json, r, encodingutf-8) as f:data json.load(f)
#数据处理将嵌套列表展开为适合建模的表格
rows []
for item in data:gcbh item[gcbh]jxtbhj item[jxtbhj]for debh, sl, dj,dwsl in zip(item[debh], item[sl], item[dj],item[dwsl]):rows.append([gcbh, debh, sl, dj,dwsl, jxtbhj])
df pd.DataFrame(rows, columns[gcbh, debh, sl, dj, dwsl,jxtbhj])
# 新增特征
df[single_item_total] df[sl] * df[dj] * df[dwsl]
# 在DataFrame创建后添加更多特征
# 1. 工程级别的统计特征
df[total_by_gcbh] df.groupby(gcbh)[single_item_total].transform(sum)
df[items_count] df.groupby(gcbh)[debh].transform(count)
df[avg_price] df.groupby(gcbh)[dj].transform(mean)
df[price_std] df.groupby(gcbh)[dj].transform(std)
df[total_quantity] df.groupby(gcbh)[sl].transform(sum)
# 2. 项目级别的统计特征
df[price_ratio] df[dj] / df[avg_price]
df[quantity_ratio] df[sl] / df[total_quantity]
df[value_ratio] df[single_item_total] / df[total_by_gcbh]
# 修改特征列表
cat_features [debh]
num_features [sl, dj, single_item_total, # 基础特征total_by_gcbh, items_count,avg_price,price_std,total_quantity, price_ratio,quantity_ratio, value_ratio
]
# 3. 处理缺失值
print(处理缺失值前的数据形状:, df.shape)
print(缺失值统计:)
print(df[num_features].isnull().sum())
# 处理缺失值 - 使用中位数填充数值特征
for col in num_features:if df[col].isnull().sum() 0:median_val df[col].median()df[col].fillna(median_val, inplaceTrue)print(f列 {col} 使用中位数 {median_val:.2f} 填充了 {df[col].isnull().sum()} 个缺失值)
# 处理分类特征的缺失值
for col in cat_features:if df[col].isnull().sum() 0:mode_val df[col].mode()[0]df[col].fillna(mode_val, inplaceTrue)print(f列 {col} 使用众数 {mode_val} 填充了 {df[col].isnull().sum()} 个缺失值)
print(处理缺失值后的数据形状:, df.shape)
print(缺失值统计:)
print(df[num_features cat_features].isnull().sum())
# 4. 处理异常值
def handle_outliers(df, columns, n_sigmas3):for col in columns:mean df[col].mean()std df[col].std()df[col] df[col].clip(mean - n_sigmas * std, mean n_sigmas * std)return df
# 处理数值特征的异常值
df handle_outliers(df, num_features)
# 目标值不做对数变换因为看起来对数变换效果不好
y df[jxtbhj].values
# 检查目标值是否有缺失值
if np.isnan(y).any():print(警告目标值包含缺失值将删除这些行)mask ~np.isnan(y)df df[mask]y y[mask]print(f删除缺失值后的数据形状: {df.shape})
# 工程编号独热编码
encoder OneHotEncoder(sparse_outputFalse, handle_unknownignore)
X_cat encoder.fit_transform(df[cat_features])
X_num df[num_features].values
# 最终检查确保没有NaN值
print(最终数据检查:)
print(fX_cat 包含 NaN: {np.isnan(X_cat).any()})
print(fX_num 包含 NaN: {np.isnan(X_num).any()})
print(fy 包含 NaN: {np.isnan(y).any()})
X np.hstack([X_cat, X_num])
# 特征缩放
scaler StandardScaler()
X_scaled scaler.fit_transform(X)
# 4. 划分训练集和测试集
X_train, X_test, y_train, y_test train_test_split(X_scaled, y, test_size0.2, random_state42)
# 在数据处理后模型训练前添加这段代码
plt.figure(figsize(12, 4))
# 原始值分布
plt.subplot(121)
plt.hist(df[jxtbhj], bins50)
plt.title(原始 jxtbhj 分布, fontpropertiesfont)
# 对数变换后的分布
plt.subplot(122)
plt.hist(np.log1p(df[jxtbhj]), bins50)
plt.title(log(jxtbhj) 分布, fontpropertiesfont)
plt.tight_layout()
plt.show()
# 打印一些基本统计信息
print(原始 jxtbhj 统计信息)
print(df[jxtbhj].describe())
# 5. 建立多种模型
models {# 岭回归: Ridge(# alpha0.5, # 适中的正则化# fit_interceptTrue# ),# 随机森林: RandomForestRegressor(# n_estimators300, # 增加树的数量# max_depth8, # 控制过拟合# min_samples_leaf5,# max_featuressqrt,# random_state42# ),XGBoost: xgb.XGBRegressor(n_estimators1500,#900max_depth8,learning_rate0.1, # 降低学习率0.09subsample0.8, # 随机采样colsample_bytree0.8,# 特征采样reg_alpha0.1, # L1正则化reg_lambda1.0, # L2正则化random_state42,verbosity0)
}
results {}
kf KFold(n_splits5, shuffleTrue, random_state42)
for name, model in models.items():cv_scores cross_val_score(model, X_scaled, y, cvkf, scoringr2,error_scoreraise)print(f\n模型: {name})print(f交叉验证 R² 分数: {cv_scores.mean():.4f} (/- {cv_scores.std() * 2:.4f}))
# 在全部数据上训练和评估model.fit(X_train, y_train)y_pred model.predict(X_test)mse mean_squared_error(y_test, y_pred)r2 r2_score(y_test, y_pred)results[name] {model: model, mse: mse, r2: r2, y_pred: y_pred}print(f测试集 MSE: {mse:.2f})print(f测试集 R²: {r2:.4f})
# 在模型训练后添加def analyze_predictions(y_true, y_pred, name):# 计算预测误差百分比error_percent np.abs((y_pred - y_true) / y_true) * 100
print(f\n{name} 预测分析:)print(f平均百分比误差: {error_percent.mean():.2f}%)print(f中位数百分比误差: {np.median(error_percent):.2f}%)print(f90%预测的误差在 {np.percentile(error_percent, 90):.2f}% 以内)
# 计算不同误差范围的预测比例for threshold in [10, 20, 30, 50]:accuracy (error_percent threshold).mean() * 100print(f误差在{threshold}%以内的预测比例: {accuracy:.2f}%)
analyze_predictions(y_test, y_pred, name)
# 6. 选择最佳模型用于解释性分析
best_model_name max(results, keylambda k: results[k][r2])
best_model results[best_model_name][model]
y_pred results[best_model_name][y_pred]
print(f最佳模型: {best_model_name})
# 保存XGBoost模型
if best_model_name XGBoost:best_model.save_model(xgb_model.json)print(XGBoost模型已保存到 xgb_model.json)# 保存encoder和scalerjoblib.dump(encoder, encoder.joblib)joblib.dump(scaler, scaler.joblib)print(encoder和scaler已保存)
# 7. 特征重要性分析
feature_names list(encoder.get_feature_names_out(cat_features)) num_features
if hasattr(best_model, coef_):importances best_model.coef_
elif hasattr(best_model, feature_importances_):importances best_model.feature_importances_
else:importances np.zeros(len(feature_names))
plt.figure(figsize(12, 6))
sns.barplot(xfeature_names, yimportances)
plt.title(f{best_model_name} 特征重要性, fontpropertiesfont)
plt.xlabel(特征, fontpropertiesfont)
plt.ylabel(重要性, fontpropertiesfont)
plt.xticks(rotation90)
plt.tight_layout()
plt.show()
# 8. 预测值与真实值对比图
plt.figure(figsize(8, 8))
plt.scatter(y_test, y_pred, alpha0.6)
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], r--, lw2)
plt.title(f{best_model_name} 真实值 vs 预测值, fontpropertiesfont)
plt.xlabel(真实值, fontpropertiesfont)
plt.ylabel(预测值, fontpropertiesfont)
plt.tight_layout()
plt.show()
# 9. 残差分析
residuals y_test - y_pred
plt.figure(figsize(8, 5))
sns.histplot(residuals, bins30, kdeTrue)
plt.title(f{best_model_name} 残差分布, fontpropertiesfont)
plt.xlabel(残差, fontpropertiesfont)
plt.tight_layout()
plt.show()
plt.figure(figsize(8, 5))
plt.scatter(y_pred, residuals, alpha0.6)
plt.axhline(0, colorred, linestyle--)
plt.title(f{best_model_name} 预测值与残差, fontpropertiesfont)
plt.xlabel(预测值, fontpropertiesfont)
plt.ylabel(残差, fontpropertiesfont)
plt.tight_layout()
plt.show() 八、安装与资源 安装pip install xgboost 或 conda install -c conda-forge xgboost 官方文档XGBoost Documentation GitHub 仓库dmlc/xgboost