【机器学习(12)】集成学习:随机森林和XGBOOST基础讲解及代码实现

1. 集成学习基础介绍

1) 概念:
        通过构建并结合多个模型来共同完成学习任务

2) 流程:
        ①构建多个子学习器
        ②使用某种集成策略将模型集成
        ③完成学习任务

3) 目的:
        通过集成,提高多个子学习器的模型泛化能力(组成一个团队,实现1+1>2)

4) 子学习器筛选原则:
        每个子学习器都要有一定的准确性(团队内部人员各司其职)
        子学习器之间要保持相对独立性和多样性(分工明确,尽量不做重复的事情)

5)Bagging:并行式集成学习
        基本原理:同时训练多个子学习机,分别对y进行预测,最后所有子学习机以投票的形式(分类问题),或者均值的形式(回归问题),返回集成的预测结果

        子学习器的构建策略:
        对样本按一定比例有放回的抽样,抽出m个样本子集,然后构建m个子学习器分别在m个样本子集上进行训练
        策略选择:投票法或者均值法

代表模型:随机森林

        子学习器:决策树模型
        子学习器构建方法:按一定比例对样本和特征有放回的抽样,抽取的m个特征和样本都存在差异的样本子集,再在这m个子集上训练m个决策树模型
        集成方法:分类问题采用投票法返回预测结果,回归采用均值法返回预测结果

6) Boosting:提升式集成学习
        基本原理:先训练一个子学习机,再计算子学习机的误差或者残差,并以此作为下一个学习机的输入,之后不断迭代重复整个过程,是的模型损失函数不断减小

        Gradient Boosting梯度提升算法:
        根据当前模型损失函数的负梯度信息来训练新加入的子学习器,然后将所有训练好的自学习器以累加的形式混合到最终模型中

集大成者(代表模型):XGBOOST

        基本思想:Gradient Boosting梯度提升
        防止过拟合:加入L1和L2正则系数
        子学习器:决策树模型(CART)、线性回归、线性分类器
        集成策略:在传统梯度提升模型的基础上,融入随机森林模型对子学习器训练样本和特征进行随机取样的策略
        优化方法:同时使用损失函数一阶、二阶导数信息,加快优化速度
        工程优化:提高训练效率,支持并行计算

2. 随机森林模型代码实现

2.1 加载数据

和之前的操作是一致的,直接copy过来即可

# 数据读取以及xy提取
import pandas as pd
import matplotlib.pyplot as plt
import os
os.chdir(r'C:\Users\86177\Desktop')
# 样例数据读取
df = pd.read_excel('realestate_sample_preprocessed.xlsx')
# 根据共线性矩阵,保留与房价相关性最高的日间人口,将夜间人口和20-39岁夜间人口进行比例处理
def age_percent(row):
    if row['nightpop'] == 0:
        return 0
    else:
        return row['night20-39']/row['nightpop']
df['per_a20_39'] = df.apply(age_percent,axis=1)
df = df.drop(columns=['nightpop','night20-39'])
# 制作标签变量
price_median = df['average_price'].median()
print(price_median)
df['is_high'] = df['average_price'].map(lambda x: True if x>= price_median else False)
print(df['is_high'].value_counts())
# 数据集基本情况查看
print(df.shape)
print(df.dtypes)
# 划分数据集
x = df[['complete_year','area', 'daypop', 'sub_kde',
       'bus_kde', 'kind_kde','per_a20_39']]
y = df['is_high']
print(x.shape)
print(y.shape)

–> 输出的结果为:

30273.0

True     449
False    449
Name: is_high, dtype: int64

(898, 10)

id                 int64
complete_year      int64
average_price    float64
area             float64
daypop           float64
sub_kde          float64
bus_kde          float64
kind_kde         float64
per_a20_39       float64
is_high             bool
dtype: object

(898, 7)
(898,)
2.2 划分验证集和测试集

这里使用留出法,按照0.75:0.25进行划分,这里x_train和x_test的选择方式和之前不一样,这里是直接选择符合的特征,之前是去掉不要的特征

from sklearn.model_selection import train_test_split
# 将数据集划分成训练集和验证集:划分比例0.75训练,0.25验证
training, testing = train_test_split(df,test_size=0.25, random_state=1)
# 提取训练集中的x与y
x_train = training.copy()[['complete_year','area', 'daypop', 'sub_kde',
       'bus_kde', 'kind_kde','per_a20_39']]
y_train = training.copy()['is_high']
# 提取验证集中的x与y
x_test = testing.copy()[['complete_year','area', 'daypop', 'sub_kde',
       'bus_kde', 'kind_kde','per_a20_39']]
y_test = testing.copy()['is_high']
print(f'the shape of training set is: {x_train.shape}')
print(f'the shape of testing set is: {x_test.shape}')

–> 输出的结果为:

the shape of training set is: (673, 7)
the shape of testing set is: (225, 7)
2.3 使用Pipeline创建工作流,构造模型
from sklearn.preprocessing import PowerTransformer, StandardScaler, PolynomialFeatures
from sklearn.pipeline import Pipeline
from sklearn.ensemble import RandomForestClassifier
rf_model = RandomForestClassifier(criterion='gini',
                                  n_jobs=16,#16个线程
                                  max_features = 'auto',
                                  n_estimators = 100,
                                  max_depth = None,
                                  random_state=133)
pipe_clf = Pipeline([
        ('sc',StandardScaler()),
        ('power_trans',PowerTransformer()),
        ('polynom_trans',PolynomialFeatures(degree=2)),
        ('rf_clf', rf_model)
        ])
print(pipe_clf)

–> 输出的结果为:

Pipeline(memory=None,
         steps=[('sc',
                 StandardScaler(copy=True, with_mean=True, with_std=True)),
                ('power_trans',
                 PowerTransformer(copy=True, method='yeo-johnson',
                                  standardize=True)),
                ('polynom_trans',
                 PolynomialFeatures(degree=2, include_bias=True,
                                    interaction_only=False, order='C')),
                ('rf_clf',
                 RandomForestClassifier(bootstrap=True, class_weight=None,
                                        criterion='gini', max_depth=None,
                                        max_features='auto',
                                        max_leaf_nodes=None,
                                        min_impurity_decrease=0.0,
                                        min_impurity_split=None,
                                        min_samples_leaf=1, min_samples_split=2,
                                        min_weight_fraction_leaf=0.0,
                                        n_estimators=100, n_jobs=16,
                                        oob_score=False, random_state=133,
                                        verbose=0, warm_start=False))],
         verbose=False)
2.4 随机森林参数讲解

1) 特有参数:
        n_estimators: 也就是子学习器的个数(越大越好,但是要权衡,100,500,1000)

        max_features: 每棵树选择的特征的最大数量,默认是"auto"

        bootstrap: 默认True(推荐),构建决策树的时候是否使用有放回的抽样方式构建训练数据

2) 决策树模型参数:
        criterion:做划分时对特征的评价标准默认是基尼系数gini,另一个可选择的标准是信息增益。回归树默认是均方差mse,另一个可是绝对值差mae

        max_depth: 每棵树的最大深度,默认None

        min_samples_split: 内部节点再划分所需最小样本数

        min_samples_leaf: 叶子节点最少样本数

        max_leaf_nodes: 最大叶子节点数

2.5 留出法在验证集上模型的表现
import warnings
from sklearn.metrics import accuracy_score, precision_score, recall_score, roc_auc_score
warnings.filterwarnings('ignore')
pipe_clf.fit(x_train,y_train)
y_predict = pipe_clf.predict(x_test)
print(f'accuracy score is: {accuracy_score(y_test,y_predict)}')
print(f'precision score is: {precision_score(y_test,y_predict)}')
print(f'recall score is: {recall_score(y_test,y_predict)}')
print(f'auc: {roc_auc_score(y_test,y_predict)}')

–> 输出的结果为:

accuracy score is: 0.8622222222222222
precision score is: 0.8761061946902655
recall score is: 0.853448275862069
auc: 0.862503954444796

3. XGBOOST模型代码实现

3.1 交叉验证法划分数据

xgboost需要单独安装此模块,在命令行安装即可,加载数据和之前的一样,这里不进行赘述,接下来不采用留出法进行数据的划分,这里采用交叉验证法进行数据的划分(取k=5)

from sklearn.model_selection import StratifiedKFold
k = 5
kf = StratifiedKFold(n_splits=k, shuffle=True)
kf.get_n_splits(x, y)
print(kf)

–> 输出的结果为:(这里由于是分类,加载的模块和之前的是不同的,可以对比之前的)

StratifiedKFold(n_splits=5, random_state=None, shuffle=True)
3.2 使用Pipeline创建工作流,构造模型
from sklearn.preprocessing import PowerTransformer, StandardScaler, PolynomialFeatures
from sklearn.pipeline import Pipeline
import xgboost as xgb

xgb_model = xgb.XGBClassifier(objective='binary:hinge',
                             nthread=16,
                             booster='gbtree',
                             n_estimators=500,
                             learning_rate=0.05,
                             max_depth=9,
                             subsample=0.8,
                             colsample_bytree=0.8                          
)

pipe_clf = Pipeline([
        ('sc',StandardScaler()),
        ('power_trans',PowerTransformer()),
        ('polynom_trans',PolynomialFeatures(degree=2)),
        ('xgb_clf', xgb_model)
        ])
print(pipe_clf)

–> 输出的结果为:

Pipeline(memory=None,
         steps=[('sc',
                 StandardScaler(copy=True, with_mean=True, with_std=True)),
                ('power_trans',
                 PowerTransformer(copy=True, method='yeo-johnson',
                                  standardize=True)),
                ('polynom_trans',
                 PolynomialFeatures(degree=2, include_bias=True,
                                    interaction_only=False, order='C')),
                ('xgb_clf',
                 XGBClassifier(base_score=None, booster='gbtree',
                               colsample_bylevel=None...
                               interaction_constraints=None, learning_rate=0.05,
                               max_delta_step=None, max_depth=9,
                               min_child_weight=None, missing=nan,
                               monotone_constraints=None, n_estimators=500,
                               n_jobs=None, nthread=16, num_parallel_tree=None,
                               objective='binary:hinge', random_state=None,
                               reg_alpha=None, reg_lambda=None,
                               scale_pos_weight=None, subsample=0.8,
                               tree_method=None, validate_parameters=False,
                               verbosity=None))],
         verbose=False)
3.3 xgboost 模型参数讲解

1) 通用参数:
        booster:默认gbtree
           gbtree:基于树的模型
           gbliner:线性模型

        nthread:最大线程数
        objective:任务类型
        回归任务:reg:squarederror

        二元分类任务:
           binary:logistic(输出概率)
           binary:hinge(输出分类结果)

2) 训练参数,以tree booster为例:
        n_estimators: 子学习器数量(和训练步长搭配的,不是越多越好)
        learning rate:训练步长
        max_depth:树最大深度
        max_leaf_nodes:树最大节点或叶子数量
        subsample:控制每棵树,训练样本比例
        colsample_bytree:控制每棵树,训练特征比例
        lambda:L2正则系数
        alpha:L1正则系数

3.4 交叉验证法在验证集上模型的表现

这里直接将分别输出和最后取均值的过程放在一块了

import warnings
from sklearn.metrics import accuracy_score, precision_score, recall_score, roc_auc_score
warnings.filterwarnings('ignore')
acc = []
precision = []
recall = []
auc = []
for train_index, test_index in kf.split(x,y):  # 拆分
    x_traincv, x_testcv = x.loc[train_index], x.loc[test_index]
    y_traincv, y_testcv = y.loc[train_index], y.loc[test_index]
    pipe_clf.fit(x_traincv, y_traincv)  # 训练
    y_predictcv = pipe_clf.predict(x_testcv)  # 预测
    k_acc = accuracy_score(y_testcv,y_predictcv)
    print(f'accuracy score is: {k_acc}')
    acc.append(k_acc)
    k_precision = precision_score(y_testcv,y_predictcv)
    print(f'precision score is: {k_precision}')
    precision.append(k_precision)
    k_recall = recall_score(y_testcv,y_predictcv)
    print(f'recall score is: {k_recall}')
    recall.append(k_recall)
    k_auc = roc_auc_score(y_testcv,y_predictcv)
    print(f'auc: {k_auc}')
    auc.append(k_auc)
import numpy as np
print(f'-----------------------------------------------------')
print(f'average accuracy score is: {np.array(acc).mean()}')
print(f'average precision is: {np.array(precision).mean()}')
print(f'average recall is: {np.array(recall).mean()}')
print(f'average auc is: {np.array(auc).mean()}')

–> 输出的结果为:

accuracy score is: 0.9060758082497213
precision score is: 0.900054914881933
recall score is: 0.9136008918617614
auc: 0.9060758082497213
accuracy score is: 0.9066071926400893
precision score is: 0.9028161236885699
recall score is: 0.9113712374581939
auc: 0.90660586412787
accuracy score is: 0.9157836029001674
precision score is: 0.9067103109656302
recall score is: 0.9269380925822643
auc: 0.9157836029001672
accuracy score is: 0.9079754601226994
precision score is: 0.8905499199145755
recall score is: 0.9302844394868934
auc: 0.9079754601226994
accuracy score is: 0.9012827663134412
precision score is: 0.9039865244244806
recall score is: 0.8979364194088121
auc: 0.9012827663134412
-----------------------------------------------------
average accuracy score is: 0.9075449660452237
average precision is: 0.900823558775038
average recall is: 0.9160262161595851
average auc is: 0.9075447003427799
  • 1
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lys_828

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值