机器学习算法(二): 基于XGBoost的分类预测

阿里云机器学习案例(二)

1.实验室介绍

1.1 XGBoost介绍

XGBoost是2016年由华盛顿大学陈天奇老师带领开发的一个可扩展机器学习系统。严格意义上讲XGBoost并不是一种模型,而是一个可供用户轻松解决分类、回归或排序问题的软件包。它内部实现了梯度提升树(GBDT)模型,并对模型中的算法进行了诸多优化,在取得高精度的同时又保持了极快的速度,在一段时间内成为了国内外数据挖掘、机器学习领域中的大规模杀伤性武器。

更重要的是,XGBoost在系统优化和机器学习原理方面都进行了深入的考虑。毫不夸张的讲,XGBoost提供的可扩展性,可移植性与准确性推动了机器学习计算限制的上限,该系统在单台机器上运行速度比当时流行解决方案快十倍以上,甚至在分布式系统中可以处理十亿级的数据。

XGBoost的主要优点:

1.简单易用。相对其他机器学习库,用户可以轻松使用XGBoost并获得相当不错的效果。
2.高效可扩展。在处理大规模数据集时速度快效果好,对内存等硬件资源要求不高。
3.鲁棒性强。相对于深度学习模型不需要精细调参便能取得接近的效果。
4.XGBoost内部实现提升树模型,可以自动处理缺失值。

XGBoost的主要缺点:

1.相对于深度学习模型无法对时空位置建模,不能很好地捕获图像、语音、文本等高维数据。
2.在拥有海量训练数据,并能找到合适的深度学习模型时,深度学习的精度可以遥遥领先XGBoost。

1.2 XGBoost的应用

XGBoost在机器学习与数据挖掘领域有着极为广泛的应用。据统计在2015年Kaggle平台上29个获奖方案中,17只队伍使用了XGBoost;在2015年KDD-Cup中,前十名的队伍均使用了XGBoost,且集成其他模型比不上调节XGBoost的参数所带来的提升。这些实实在在的例子都表明,XGBoost在各种问题上都可以取得非常好的效果。

同时,XGBoost还被成功应用在工业界与学术界的各种问题中。例如商店销售额预测、高能物理事件分类、web文本分类;用户行为预测、运动检测、广告点击率预测、恶意软件分类、灾害风险预测、在线课程退学率预测。虽然领域相关的数据分析和特性工程在这些解决方案中也发挥了重要作用,但学习者与实践者对XGBoost的一致选择表明了这一软件包的影响力与重要性。

2.实验室手册

2.1 学习目标

2.1.1 了解 XGBoost 的参数与相关知识
2.1.2 掌握 XGBoost 的Python调用并将其运用到天气数据集预测

2.2 代码流程

Part1 基于天气数据集的XGBoost分类实践

Step1: 库函数导入
Step2: 数据读取/载入
Step3: 数据信息简单查看
Step4: 可视化描述
Step5: 对离散变量进行编码
Step6: 利用 XGBoost 进行训练与预测
Step7: 利用 XGBoost 进行特征选择
Step8: 通过调整参数获得更好的效果

2.3 算法实战

2.3.1 基于天气数据集的XGBoost分类实战

%%%数据集地址如下%%% :
https://tianchi-media.oss-cn-beijing.aliyuncs.com/DSW/7XGBoost/train.csv

step1:库函数导入

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns # 与matplotlib的区别是实现固化可视化模板,而非高度定制化绘图
import warnings
import xgboost

step2:数据载入

plt.rcParams['axes.unicode_minus'] = False
# sns.set_style('darkgrid', {'font.sans-serif':['SimHei', 'Arial']})
warnings.filterwarnings('ignore')
data = pd.read_csv(r"E:\train.csv")

step3:数据信息简单查看

data.info
data.head()
data = data.fillna(-1)
data.tail()
pd.Series(data['RainTomorrow']).value_counts()
data.describe()

step4:可视化描述

numerical_features = [x for x in data.columns if data[x].dtype == np.float64]
category_features = [x for x in data.columns if data[x].dtype != np.float64 and x != 'RainTomorrow']
## 选取三个特征与标签组合的散点可视化
sns.pairplot(data = data[['Rainfall',
                          'Evaporation',
                          'Sunshine'] + ['RainTomorrow']], diag_kind = 'hist', hue = 'RainTomorrow')
plt.show()
for col in data[numerical_features].columns:
    if col != 'RainTomorrow':
        sns.boxplot(x = 'RainTomorrow', y = col, saturation = 0.5, palette = 'pastel', data = data)
        plt.title(col)
        plt.show() # 不要忘记()
# 依据明天是否下雨将其它非数值列分别进行聚合(各维度行数不一)
tlog = {} ###### 字典??????????????
for i in category_features:
    tlog[i] = data[data['RainTomorrow'] == 'Yes'][i].value_counts()
flog = {}
for i in category_features:
    flog[i] = data[data['RainTomorrow'] == 'No'][i].value_counts()
plt.figure(figsize=(10, 10))
plt.subplot(1,2,1)
plt.title('RainTomorrow')
sns.barplot(x = pd.DataFrame(tlog['Location']).sort_index()['Location'], y = pd.DataFrame(tlog['Location']).sort_index().index, color = 'red')
plt.subplot(1,2,2)
plt.title('Not RainTomorrow')
sns.barplot(x = pd.DataFrame(flog['Location']).sort_index()['Location'], y = pd.DataFrame(flog['Location']).sort_index().index, color = 'blue')
plt.show()
plt.figure(figsize=(10,2))
plt.subplot(1,2,1)
plt.title('RainTomorrow')
sns.barplot(x = pd.DataFrame(tlog['RainToday'][:2]).sort_index()['RainToday'], y = pd.DataFrame(tlog['RainToday'][:2]).sort_index().index, color = 'red')
plt.subplot(1,2,2)
plt.title('Not RainTomorrow')
sns.barplot(x = pd.DataFrame(flog['RainToday'][:2]).sort_index()['RainToday'], y = pd.DataFrame(flog['RainToday'][:2]).sort_index().index, color = 'blue')
plt.show()

step5:对离散变量进行编码

# 由于XGBoost无法处理字符串类型的数据,因此需要对其进行编码,将其转化为数据类型
def get_mapfunction(x):
    mapp = dict(zip(x.unique().tolist(),
                  range(len(x.unique().tolist()))))
    def mapfunction(y):
        if y in mapp:
            return mapp[y]
        else:
            return -1
    return mapfunction
for i in category_features:
    data[i] = data[i].apply(get_mapfunction(data[i]))
data['RainTomorrow'] = data['RainTomorrow'].apply(get_mapfunction(data['RainTomorrow']))

step6:接下来利用XGBoost进行训练与预测

# 为了正确评估模型性能,将数据划分为训练集和测试集,并在训练集上训练模型,在测试集上验证模型性能
from sklearn.model_selection import train_test_split

## 选择其类别为0 和 1 的样本(不包括类别为2的样本
data_features_part = data[[x for x in data.columns if x != 'RainTomorrow']]
data_target_part = data['RainTomorrow']

## 测试集合设置为20%
x_train, x_test, y_train, y_test = train_test_split(data_features_part, data_target_part, test_size=0.2, random_state= 2020)

## 导入XGBoost模型
from xgboost.sklearn import XGBClassifier
## 定义XGBoost模型
clf = XGBClassifier()
# 在训练集上训练XGBoost模型
clf.fit(x_train, y_train)

## 在训练集和测试集上分布利用训练好的模型进行预测
train_predict = clf.predict(x_train)
test_predict = clf.predict(x_test)
from sklearn import metrics # 用于计算训练结果的评价指标

## 利用accuracy(准确度)【预测正确的样本数目占总预测样本数目的比例】 评估模型效果
print('The accuracy of the Logistic Regression is:', metrics.accuracy_score(y_train, train_predict))
print('The accuracy of the Logistic Regression is:', metrics.accuracy_score(y_test, test_predict))

## 查看混淆矩阵(预测值和真实值的各类情况统计矩阵)
confusion_matrix_result = metrics.confusion_matrix(test_predict, y_test)
print('The confusion matrix result:\n', confusion_matrix_result)

## 利用热力图对于结果进行可视化
plt.figure(figsize=(8,6))
sns.heatmap(confusion_matrix_result, annot=True, cmap='Blues')
plt.xlabel('Predicted labels')
plt.ylabel('True labels')
plt.show()

step7:利用XGBoost进行特征选择

?sns.barplot
# 从图中可以看出今天是否下雨和下午三点的湿度是明天是否下雨的最重要的因素
sns.barplot(y=data_features_part.columns, x=clf.feature_importances_)
# 除此之外,还可以使用xgboost中的下列重要属性来评估特征的重要性
# weight:是以特征用到的次数来评价
# gain:当利用特征做划分时候的评价基尼系数
# cover:利用一个覆盖样本的指标二阶导数平均值来划分(具体原理不清楚,有待探究
# total_gain:总基尼系数
# total_cover:总覆盖

from sklearn.metrics import accuracy_score
from xgboost import plot_importance

def estimate(model, data):
    # sns.barplot(data.columns, model.feature_importances_)
    ax1 = plot_importance(model, importance_type='gain')
    ax1.set_title('gain')
    ax2 = plot_importance(model, importance_type='weight')
    ax2.set_title('weight')
    ax3 = plot_importance(model, importance_type='cover')
    ax3.set_title('cover')
    plt.show()
    
def classes(data, label, test):
    model = XGBClassifier()
    model.fit(data, label)
    ans = model.predict(test)
    estimate(model, data)
    return ans

ans = classes(x_train, y_train, x_test)
pre = accuracy_score(y_test, ans)
print('acc=', pre)

step8:通过调整参数获得更好的效果

# XGBoost包括但不限于以下对模型影响较大的参数
# learning_rate:有时候也叫做eta,系统默认0.3,每一步迭代的步长,很重要。太大运行准确率不高,太小运行速度慢。
# subsample:系统默认为1.这个参数控制对于每棵树,随机采样的比例,减小该数值,算法会更加保守,避免过拟合,取值[0,1]
# colsample_bytree:系统默认值为1.一般设置成0.8左右,用来控制每棵树随机采样的列数的占比(每一列是一个特征)
# max_depth:系统默认值为6,常设置为3-10之间,值为树的最大深度,用来控制过拟合,max_depth越大,模型学习的更具体。
# 调节模型参数的方法有贪心算法、网格调参、贝叶斯调参等。这里我们采用网格调参,
# 它的基本思想是穷举搜索:在所有候选的参数选择中,通过循环遍历,尝试每一种可能性,表现最好的参数就是最终的结果。
## 从sklearn库中导入网格调参函数
from sklearn.model_selection import GridSearchCV

# 定义参数取值范围
learning_rate = [0.1, 0.3, 0.6]
subsample = [0.8, 0.9]
colsample_bytree = [0.6, 0.8]
max_depth = [3, 6, 8]

parameters = {
    'learning_rate': learning_rate,
    'subsample': subsample,
    'colsample_bytree': colsample_bytree,
    'max_depth': max_depth    
}
model = XGBClassifier(n_estimators = 50)

## 进行网格搜索
clf = GridSearchCV(model, parameters, cv=3, scoring='accuracy', verbose=1, n_jobs=-1)
clf = clf.fit(x_train, y_train)
clf.best_params_
## 在训练集和测试机上分布利用最好的参数进行预测

## 定义带参数的XGBoost模型
clf = XGBClassifier(colsample_bytree = 0.8, learning_rate = 0.3, max_depth = 6, subsample = 0.8)
# 在训练集上训练XGBoost模型
clf.fit(x_train, y_train)

train_predict = clf.predict(x_train)
test_predict = clf.predict(x_test)

## 利用accuracy(准确度)【预测正确的样本数目占总预测样本数目的比例】评估模型效果
print('The accuracy of the Logistic Regression is:', metrics.accuracy_score(y_train, train_predict))
print('The accuracy of the Logistic Regression is:', metrics.accuracy_score(y_test, test_predict))

## 查看混淆矩阵(预测值和真实值的各类情况统计矩阵)
confusion_matrix_result = metrics.confusion_matrix(test_predict, y_test)
print('The confusion matrix result:\n', confusion_matrix_result)

# 利用热力图对结果进行可视化
plt.figure(figsize=(8,6))
sns.heatmap(confusion_matrix_result, annot=True, cmap='Blues')
plt.xlabel('Predicted labels')
plt.ylabel('True labels')
plt.show()

3.知识点

3.1 XGBoost的重要参数

##### 1.eta[默认值0.3]:通过为每一棵树增加权重,提高模型的鲁棒性。典型值为0.01-0.2
##### 2.min_child_weight[默认1],决定最小叶子节点样本权重和。这个参数可以避免过拟合。当它的值较大时,可以避免模型学习到局部的特殊样本。入股这个值过高,则会导致模型拟合不充分
##### 3.max_depth[默认6],这个值也是用来避免过拟合的。max_depth越大,模型会学到更具体更具不的样本。典型值为:3-10
##### 4.max_leaf_nodes,树上最大的节点或叶子的数量。可以替代max_depth的作用。这个参数的定义会导致忽略max_depth参数
##### 5.gamma[默认0],在节点分裂时,只有分裂后损失函数的值下降了,才会分裂这个节点。gamma指定了节点分裂所需的最小损失函数下降值。这个参数的值越大,算法越保守。这个参数的值和损失函数息息相关。
##### 6.max_delta_step[默认0],这个参数限制每棵树权重改变的最大步长。如果这个参数的值为0,那就意味着没有约束。如果被赋予了某个正值,那么他会让这个算法更保守。但是当各类别的样本十分不均衡时,它对分类问题是很有帮助的。
##### 7.subsample[默认1],这个参数控制对于每棵树随机采样的比例。减小这个参数的值,算法会更加保守,避免过拟合。但是如果这个值设置的过小,它可能导致欠拟合。典型值:0.5-1
##### 8.colsample_bytree[默认1],用来控制每棵随机采样列数的占比(列值即一个特征值)。典型值:0.5-1
##### 9.colsample_bylevel[默认1],用来控制树的每一级的每一次分裂,对列数的采样占比。subsample参数和colsample_bytree参数可以起到相同的作用,一般用不到
##### 10.lambda[默认1],权重L2正则化项。(和Ridge regression类似)。这个参数用来控制XGBoost的正则化部分的。虽然大部分数据科学家很少用到这个参数,但是这个参数在减少过拟合上还是可以挖掘出更多用处的。
##### 11.alpha[默认1],权重L1的正则化项。(和Lasso regression类似)。可以应用在很高维的情况下,使得算法的速度更快。
##### 12.scale_pos_weight{默认1],在各类样本十分不均衡时,把这个参数设定为一个正值,可以使算法更快收敛

3.2 XGBoost原理粗略讲解

#### XGBoost底层实现了GBDT算法,并对GBDT算法做了一系列优化:
##### 1.对目标函数进行了泰勒展示的二阶展开,可以更加高效拟合误差。
##### 2.提出了一种估计分裂点的算法,加速CART树的构建过程,同时可以处理稀疏数据。
##### 3.提出了一种树的并行策略加速迭代。
##### 4.为模型的分布式算法进行了底层优化。
#### XGBoost是基于CART树的集成模型,它的思想是串联多个决策树模型共同决策
##### 那么如何串联呢?XGBoost采用迭代预测误差的方法串联。举个通俗的例子,我们现在需要预测一辆车价值3000元。我们构建决策树1训练后预测为2600元,我们发现有400元的误差,那么决策树2的训练目标为400元,但决策树2的预测结果为350元,还存在50元的误差就交给第三棵树……以此类推,每一颗树用来估计之前所有树的误差,最后所有树预测结果的求和就是最终预测结果!
#### XGBoost的基模型是CART回归树,它有两个特点:
##### 1.CART树,是一颗二叉树。2.回归树,最后拟合结果是连续值。

机器学习算法(二): 基于XGBoost的分类预测_第1张图片

你可能感兴趣的:(机器学习算法,机器学习,python)