XGBoost是一种基于Boost算法的机器学习方法,全称EXtreme Gradient Boosting。
XGBoost在GBDT的基础上,引入了:
关于XGBoost的理论在官网上介绍地很清楚,可以参考: https://xgboost.readthedocs.io/en/stable/tutorials/model.html
XGBoost 的目标模型可以表示为:
其中L(θ)为损失项,Ω(θ)为正则项。正则项反映了模型的复杂程度。
一般L(θ)可以用方差来进行统计:
用于逻辑回归中:
下图可以解释两者和模型匹配程度之间的关系:
XGBoost树集成模型由一组分类和回归树 (CART) 组成。下面是一个 CART 的简单示例,用于对某人是否会喜欢假设的电脑游戏 X 进行分类。
我们将一个家族的成员分类为不同的叶子,并给他们分配相应叶子上的分数。CART 与决策树略有不同,在决策树中,叶仅包含决策值。在CART中,每片叶子都有一个真实的分数,这给了我们更丰富的解释,超越了分类。这也允许采用有原则的统一优化方法,我们将在本教程的后面部分中看到。
通常,一棵树不够坚固,无法在实践中使用。实际使用的是集成模型,它将多个树的预测相加。
在数学上,我们可以将模型写成
其中K是树的数量,f(x)是函数空间中的函数,并且是所有可能的 CART 的集合。要优化的目标函数由下式给出
下面给出用XGBoost求解的步骤,这部分参考:
https://zhuanlan.zhihu.com/p/162001079
合并一次项系数、二次项系数。
优化目标即让Obj的值尽可能的小
训练树时,分裂点的选择有如下几种算法:
用TPS2022 Mar的题目做示例,用过时间预测道路拥堵程度:
import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.preprocessing import OneHotEncoder, StandardScaler from sklearn.pipeline import make_pipeline from sklearn.metrics import mean_absolute_error, mean_squared_error train_orig = pd.read_csv('train.csv', index_col='row_id', parse_dates=['time']) train_orig.head()
%%time #用道路和方向进行OneHot编码 # Feature engineering # Combine x, y and direction into a single categorical feature with 65 unique values # which can be one-hot encoded def place_dir(df): return df.apply(lambda row: f"{row.x}-{row.y}-{row.direction}", axis=1).values.reshape([-1, 1]) for df in [train_orig]: df['place_dir'] = place_dir(df) ohe = OneHotEncoder(drop='first', sparse=False) ohe.fit(train_orig[['place_dir']]) def engineer(df): """Return a new dataframe with the engineered features""" new_df = pd.DataFrame(ohe.transform(df[['place_dir']]), columns=ohe.categories_[0][1:], index=df.index) new_df['saturday'] = df.time.dt.weekday == 5 new_df['sunday'] = df.time.dt.weekday == 6 new_df['daytime'] = df.time.dt.hour * 60 + df.time.dt.minute new_df['dayofyear'] = df.time.dt.dayofyear # to model the trend return new_df train = engineer(train_orig) train['congestion'] = train_orig.congestion features = list(train.columns) print(list(features))
处理后的数据:
# Split into train and test # Use all Monday-Wednesday afternoons in August and September for validation val_idx = ((train_orig.time.dt.month >= 8) & (train_orig.time.dt.weekday <= 3) & (train_orig.time.dt.hour >= 12)).values train_idx = ~val_idx X_tr, X_va = train.loc[train_idx, features], train.loc[val_idx, features] y_tr, y_va = train.loc[train_idx, 'congestion'], train.loc[val_idx, 'congestion']
%%time from sklearn.ensemble import AdaBoostRegressor regr = AdaBoostRegressor(random_state=0, n_estimators=100) regr.fit(X_tr, y_tr) y_pred = regr.predict(X_va) mean_absolute_error(y_pred, y_va)
%%time from sklearn.ensemble import GradientBoostingRegressor regr = GradientBoostingRegressor(random_state=0, n_estimators=100) regr.fit(X_tr, y_tr) y_pred = regr.predict(X_va) mean_absolute_error(y_pred, y_va)
%%time import xgboost as xgb model = xgb.XGBRegressor(n_estimators=200) model.fit(X_tr, y_tr) y_pred = model.predict(X_va) score_xgb = mean_absolute_error(y_pred, y_va)
算法 | 结果 |
---|---|
AdaBoost | 13.654161859220649 |
GBDT | 7.55620711428925 |
XGBoost | 5.880979271309312 |
详见官网,也可以参考这篇博客:https://www.cnblogs.com/TimVerion/p/11436001.html
XGBoost还有一个常用功能是做特征挖掘,挖掘房价预测的相关性示例:
清洗后的数据:
在挖掘特征相关性之前,需要提前做一次预测:
%%time xgbr = xgb.XGBRegressor(verbosity=0, n_estimators=100) xgbr.fit(X_train, y_train) y_pred = xgbr.predict(X_test)
之后用XGBoost自带的方法就可以plot模型中各个特征相关情况
xgb.plot_importance(xgbr)