图解机器学习实战以案例和代码驱动的方式展示机器学习算法的应用流程&链条各环节,掌握构建场景建模解决方案并进行效果调优的能力。本文详细讲解 XGBoost 的工程应用方法。XGBoost 是一个非常强大的 Boosting 算法工具包,是很多大厂机器学习方案的模型首选,在并行计算效率、缺失值处理、控制过拟合等能力上都表现非常优秀。、
XGBoost 是 eXtreme Gradient Boosting 的缩写称呼,它是一个非常强大的 Boosting 算法工具包,优秀的性能(效果与速度)让其在很长一段时间内霸屏数据科学比赛解决方案榜首,现在很多大厂的机器学习方案依旧会首选这个模型。XGBoost 在并行计算效率、缺失值处理、控制过拟合、预测泛化能力上都表现非常优秀。
XGBoost安装
XGBoost作为常见的强大Python机器学习工具库,安装也比较简单。
Python与IDE环境设置
Python 环境与 IDE 设置可以参考ShowMeAI文章 图解python | 安装与环境设置[2] 进行设置。
工具库安装
(1) Linux/Mac等系统
这些系统下的XGBoost安装,大家只要基于pip就可以轻松完成了,在命令行端输入命令如下命令即可等待安装完成。
pip install xgboost
大家也可以选择国内的pip源,以获得更好的安装速度
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple xgboost
(2) Windows系统
对于windows系统而言,比较高效便捷的安装方式是:在网址http://www.lfd.uci.edu/~gohlke/pythonlibs/ 中去下载对应版本的的XGBoost安装包,再通过如下命令安装。
pip install xgboost‑1.5.1‑cp310‑cp310‑win32.whl
XGBoost数据读取
应用 XGBoost 的第一步,需要加载所需的数据成为工具库所能支持的格式形态。XGBoost 可以加载多种数据格式的数据用于训练建模:
- libsvm 格式的文本数据。
- Numpy 的二维数组。
- XGBoost 的二进制的缓存文件。加载的数据存储在对象 DMatrix 中。
XGBoost 的 SKLearn 接口也支持对于 Dataframe 格式的数据(参考ShowMeAI的文章 Python数据分析|Pandas核心操作函数大全[3] 进行处理。下面是不同格式的数据,XGBoost 的加载方式。
- 加载libsvm格式的数据
dtrain1 = xgb.DMatrix('train.svm.txt')
- 加载二进制的缓存文件
dtrain2 = xgb.DMatrix('train.svm.buffer')
- 加载 numpy 的数组
data = np.random.rand(5,10) # 5 entities, each contains 10 features
label = np.random.randint(2, size=5) # binary target
dtrain = xgb.DMatrix( data, label=label)
-
将
**scipy.sparse**
格式的数据转化为**DMatrix**
格式
csr = scipy.sparse.csr_matrix( (dat, (row,col)) )
dtrain = xgb.DMatrix( csr )
-
将
**DMatrix**
格式的数据保存成 XGBoost 的二进制格式,在下次加载时可以提高加载速度,使用方式如下
dtrain = xgb.DMatrix('train.svm.txt')
dtrain.save_binary("train.buffer")
-
可以用如下方式处理
**DMatrix**
中的缺失值
dtrain = xgb.DMatrix( data, label=label, missing = -999.0)
- 当需要给样本设置权重时,可以用如下方式
w = np.random.rand(5,1)
dtrain = xgb.DMatrix( data, label=label, missing = -999.0, weight=w)
XGBoost不同建模方式
内置建模方式:libsvm格式数据源
XGBoost 内置了建模方式,有如下的数据格式与核心训练方法:
- 基于DMatrix格式的数据
- 基于xgb.train接口训练
下面是官方的一个简单示例,演示了读取libsvm格式数据(成DMatrix格式)并指定参数建模的过程。
# 导入工具库
import numpy as np
import scipy.sparse
import pickle
import xgboost as xgb
# 从libsvm文件中读取数据,做二分类
# 数据是libsvm的格式,如下样本格式
#1 3:1 10:1 11:1 21:1 30:1 34:1 36:1 40:1 41:1 53:1 58:1 65:1 69:1 77:1 86:1 88:1 92:1 95:1 102:1 105:1 117:1 124:1
#0 3:1 10:1 20:1 21:1 23:1 34:1 36:1 39:1 41:1 53:1 56:1 65:1 69:1 77:1 86:1 88:1 92:1 95:1 102:1 106:1 116:1 120:1
#0 1:1 10:1 19:1 21:1 24:1 34:1 36:1 39:1 42:1 53:1 56:1 65:1 69:1 77:1 86:1 88:1 92:1 95:1 102:1 106:1 116:1 122:1
dtrain = xgb.DMatrix('./data/agaricus.txt.train')
dtest = xgb.DMatrix('./data/agaricus.txt.test')
# 超参数设定
# 主要是树深、学习率、目标函数
param = {'max_depth':2, 'eta':1, 'silent':1, 'objective':'binary:logistic' }
# 设定watchlist用于建模过程中观测模型状态
watchlist = [(dtest,'eval'), (dtrain,'train')]
num_round = 2
bst = xgb.train(param, dtrain, num_round, watchlist)
# 使用模型预测
preds = bst.predict(dtest)
# 判断准确率
labels = dtest.get_label()
print('错误率为%f' % \
(sum(1 for i in range(len(preds)) if int(preds[i]>0.5)!=labels[i]) /float(len(preds))))
# 模型存储
bst.save_model('./model/0001.model')
[0] eval-error:0.042831 train-error:0.046522
[1] eval-error:0.021726 train-error:0.022263
错误率为0.021726
内置建模方式:csv格式数据源
下面的例子,输入的数据源是csv文件,我们使用大家熟悉的 Pandas 工具库(参考ShowMeAI教程 数据分析系列教程[4] 与 数据科学工具速查 | Pandas使用指南[5])把数据读取为 Dataframe 格式,再构建Dmatrix格式输入,后续使用内置建模方式进行训练。
# 皮马印第安人糖尿病数据集 包含很多字段:怀孕次数 口服葡萄糖耐量试验中血浆葡萄糖浓度 舒张压(mm Hg) 三头肌组织褶厚度(mm)
# 2小时血清胰岛素(μU/ ml) 体重指数(kg/(身高(m)^2) 糖尿病系统功能 年龄(岁)
import pandas as pd
data = pd.read_csv('./data/Pima-Indians-Diabetes.csv')
data.head()
# 导入工具库
import numpy as np
import pandas as pd
import pickle
import xgboost as xgb
from sklearn.model_selection import train_test_split
# 用pandas读入数据
data = pd.read_csv('./data/Pima-Indians-Diabetes.csv')
# 做数据切分
train, test = train_test_split(data)
# 转换成Dmatrix格式
feature_columns = ['Pregnancies', 'Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', 'BMI', 'DiabetesPedigreeFunction', 'Age']
target_column = 'Outcome'
# 取出Dataframe的numpy数组值去初始化DMatrix对象
xgtrain = xgb.DMatrix(train[feature_columns].values, train[target_column].values)
xgtest = xgb.DMatrix(test[feature_columns].values, test[target_column].values)
#参数设定
param = {'max_depth':5, 'eta':0.1, 'silent':1, 'subsample':0.7, 'colsample_bytree':0.7, 'objective':'binary:logistic' }
# 设定watchlist用于查看模型状态
watchlist = [(xgtest,'eval'), (xgtrain,'train')]
num_round = 10
bst = xgb.train(param, xgtrain, num_round, watchlist)
# 使用模型预测
preds = bst.predict(xgtest)
# 判断准确率
labels = xgtest.get_label()
print('错误类为%f' % \
(sum(1 for i in range(len(preds)) if int(preds[i]>0.5)!=labels[i]) /float(len(preds))))
# 模型存储
bst.save_model('./model/0002.model')
[0] eval-error:0.354167 train-error:0.194444
[1] eval-error:0.34375 train-error:0.170139
[2] eval-error:0.322917 train-error:0.170139
[3] eval-error:0.28125 train-error:0.161458
[4] eval-error:0.302083 train-error:0.147569
[5] eval-error:0.286458 train-error:0.138889
[6] eval-error:0.296875 train-error:0.142361
[7] eval-error:0.291667 train-error:0.144097
[8] eval-error:0.302083 train-error:0.130208
[9] eval-error:0.291667 train-error:0.130208
错误类为0.291667
预估器建模方式:SKLearn接口+Dataframe
XGBoost 也支持用 SKLearn 中统一的预估器形态接口进行建模如下为典型的参考案例,对于读取为 Dataframe 格式的训练集和测试集,可以直接使用 XGBoost初始化 XGBClassifier 进行 fit 拟合训练。使用方法与接口,和 SKLearn 中其他预估器一致。
# 导入工具库
import numpy as np
import pandas as pd
import pickle
import xgboost as xgb
from sklearn.model_selection import train_test_split
# 用pandas读入数据
data = pd.read_csv('./data/Pima-Indians-Diabetes.csv')
# 做数据切分
train, test = train_test_split(data)
# 特征列
feature_columns = ['Pregnancies', 'Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', 'BMI', 'DiabetesPedigreeFunction', 'Age']
# 标签列
target_column = 'Outcome'
# 初始化模型
xgb_classifier = xgb.XGBClassifier(n_estimators=20,\
max_depth=4, \
learning_rate=0.1, \
subsample=0.7, \
colsample_bytree=0.7, \
eval_metric='error')
# Dataframe格式数据拟合模型
xgb_classifier.fit(train[feature_columns], train[target_column])
# 使用模型预测
preds = xgb_classifier.predict(test[feature_columns])
# 判断准确率
print('错误类为%f' %((preds!=test[target_column]).sum()/float(test_y.shape[0])))
# 模型存储
joblib.dump(xgb_classifier, './model/0003.model')
错误类为0.265625
['./model/0003.model']