人工智能学习8(集成学习之xgboost)

编译工具:PyCharm

集成学习

解决欠拟合问题:弱弱组合变强,boosting
解决过拟合问题:互相遏制变壮,Bagging

集成学习(Ensemble learning)通过构建并结合多个学习器来完成学习任务。
同质

同质(homogeneous)集成:集成中只包含同种类型的“个体学习器”相应的学习算法称为“基学习算法”(base learning algorithm)
个体学习器亦称“基学习器”(base learner)
异质(heterogeneous)集成:个体学习器由不同的学习算法生成不存在“基学习算法”
Bagging方法(并行)
boosting方法(串行)基本思想:基分类器层层叠加,每一层在训练的时候对前一层基分类器分错的样本给予更高的权重。

XGBoost(Extreme Gradient Boosting)极端梯度提升树

1.最优模型的构建方法

构建最优模型的一般方法:最小化训练数据的损失函数

(1.1)经验风险最小化,训练得到的模型复杂度哈皮,但是当训练数据集较小的时候,模型容易出现问题。
在这里插入图片描述

为进度模型复杂度,采用(2.1)结构风险最小化,它对训练数据以及未知数据都有较好的预测。
J(f)是模型的复杂度
在这里插入图片描述

应用:
决策树的生成:经验风险最小化
剪枝:结构风险最小化
XGBoost的决策树生成:结构风险最小化

XGBoost目标函数

正则化损失函数:
在这里插入图片描述

CART树
在这里插入图片描述

树的复杂度
在这里插入图片描述

目标函数:
目标函数推导过程
在这里插入图片描述

分裂节点计算
分开前-分开后,结果>0,可以进行分裂,<0不进行
γ:减去一个加入新叶子节点引入的复杂度代价。
在这里插入图片描述

案例1:泰坦尼克号

数据集:https://hbiostat.org/data/repo/titanic.txt

# xgboost
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split        # 进行数据集划分
from sklearn.feature_extraction import DictVectorizer
import matplotlib.pyplot as plt
from xgboost import XGBClassifier

# 读取数据
# titan = pd.read_csv("https://hbiostat.org/data/repo/titanic.txt")
titan = pd.read_csv("./data/titanic.csv")
# print(titan.describe())

# 获取样本和目标值
# 这里取pclass社会等级、age年龄、sex性别作为特征值
# 取survived存活为目标值
x = titan[["pclass","age","sex"]]
y = titan["survived"]

# 缺失值处理:对age为空的用平均值替换
x['age'].fillna(value=titan["age"].mean(),inplace=True)
# print(x.head())

# 数据集划分
x_train,x_test,y_train,y_test = train_test_split(x,y,random_state=22,test_size=0.2)
# 特征抽取(字典特征提取)
x_train = x_train.to_dict(orient="records")
x_test = x_test.to_dict(orient="records")
tranfer = DictVectorizer()
x_train = tranfer.fit_transform(x_train)
x_test = tranfer.fit_transform(x_test)

# xgboost 初步模型训练
# 实例化
xg = XGBClassifier()
# 训练
xg.fit(x_train,y_train)
# 初步模型评估
print("xg初步模型训练评估: ",xg.score(x_test, y_test))

# xgboost 调优模型训练
depth_range = range(5)
score = []
for i in depth_range:
    xg=XGBClassifier(eta=1,gamma=0,max_depth=i)
    xg.fit(x_train,y_train)
    s = xg.score(x_test,y_test)
    print("第",i+1,"次训练评估: ",s)
    score.append(s)
# 对调优结果可视化
# plt.plot(depth_range,score)
# plt.show()

在这里插入图片描述

案例2:对奥拓集团差评进行正确分类。

数据准备:

数据集:https://download.csdn.net/download/weixin_42320758/15728128?utm_source=bbsseo

使用pycharm下载包的时候,容易下载不成功,建议使用清华大学提供的网站进行下载
-i https://pypi.tuna.tsinghua.edu.cn/simple 包名称
在命令行进行下载也可以使用:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple
在这里插入图片描述
在这里插入图片描述

1.第一种基础的训练方式(不全,作对比)

数据分割使用:train_test_split
模型训练选择:RF进行模型训练


import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# 欠采样方法从大量数据中抽取数据
from imblearn.under_sampling import RandomUnderSampler
# 将标签转化为数字
from sklearn.preprocessing import LabelEncoder
# 数据分割
from sklearn.model_selection import train_test_split
# RF模型训练
from sklearn.ensemble import RandomForestClassifier
# log_loss模型评估
from sklearn.metrics import log_loss
# one-hot处理数据
from sklearn.preprocessing import OneHotEncoder

# 获取数据
data = pd.read_csv("./data/otto_train.csv")
# 数据标签可视化,查看数据的分布情况
sns.countplot(data.target)
plt.show()

x = data.drop(["id","target"], axis=1)
y = data["target"]
# 数据已结果脱敏处理(保护一些隐私等信息的安全)
# 截取部分数据进行训练(防止数据量过大)
# 使用欠采样的方法获取数据,注意:不能直接按照前n行的方式进行截取
rus = RandomUnderSampler(random_state=0)
x_resampled,y_resampled = rus.fit_resample(x,y)
sns.countplot(y_resampled)
plt.show()

# 将标签转数字
le = LabelEncoder()
y_resampled = le.fit_transform(y_resampled)
print(y_resampled)


# 数据分割
x_train,x_test,y_train,y_test = train_test_split(x_resampled,y_resampled,test_size=0.2)
print(x_train.shape,y_train.shape)
print(x_test.shape,y_test.shape)

# 模型训练1
# 基于RF模型训练
rf = RandomForestClassifier(oob_score=True)
rf.fit(x_train,y_train)
y_pre = rf.predict(x_test)
print("基于RF模型训练的评估结果score:",rf.score(x_test, y_test))
# log_loss模型评估
# log_loss(y_test,y_pre,eps=1e-15,normalize=True)       # 这样子写会报错,log_loss中要求输出用one-hot表示
# one-hot处理
one_hot=OneHotEncoder(sparse=False)
y_test1=one_hot.fit_transform(y_test.reshape(-1,1))
y_pre1 = one_hot.fit_transform(y_pre.reshape(-1,1))
print("log_loss评估结果:",log_loss(y_test1, y_pre1, eps=1e-15, normalize=True))


原始数据标签可视化,,查看数据的分布情况
在这里插入图片描述
数据量过大,用欠采样的方法抽取部分数据后,标签可视化:
在这里插入图片描述
输出结果:
在这里插入图片描述

2.第二种优化后的训练方式

数据分割处理:StratifiedShuffleSplit

2.1数据处理部分
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# 欠采样方法从大量数据中抽取数据
from imblearn.under_sampling import RandomUnderSampler
# 将标签转化为数字
from sklearn.preprocessing import LabelEncoder
# 数据分割
from sklearn.model_selection import StratifiedShuffleSplit
# 数据标准化
from sklearn.preprocessing import StandardScaler
# 数据pca降维
from sklearn.decomposition import PCA


# 获取数据
data = pd.read_csv("./data/otto_train.csv")
# 数据标签可视化,查看数据的分布情况
# sns.countplot(data.target)
# plt.show()

x = data.drop(["id","target"], axis=1)
y = data["target"]
# 数据已结果脱敏处理(保护一些隐私等信息的安全)
# 截取部分数据进行训练(防止数据量过大)
# 使用欠采样的方法获取数据,注意:不能直接按照前n行的方式进行截取
rus = RandomUnderSampler(random_state=0)
x_resampled,y_resampled = rus.fit_resample(x,y)
# sns.countplot(y_resampled)
# plt.show()

# 将标签转数字
le = LabelEncoder()
y_resampled = le.fit_transform(y_resampled)
print("标签转为数值后: ",y_resampled)


# 数据分割
x_train = []
x_val = []
y_train = []
y_val=[]
sss = StratifiedShuffleSplit(n_splits=1,test_size=0.2,random_state=0)
for train_index,test_index in sss.split(x_resampled.values,y_resampled):
    # print(len(train_index))
    # print(len(test_index))
    x_train = x_resampled.values[train_index]   # 训练集的数据
    x_val = x_resampled.values[test_index]  # 测试集的数据
    y_train = y_resampled[train_index]      # 训练集的标签
    y_val = y_resampled[test_index]     # 测试集的标签

print("训练集和测试集的大小:",x_train.shape,x_val.shape)
# 分割后的数据可视化
# sns.countplot(y_val)
# plt.show()


# 数据标准化
scaler = StandardScaler()
scaler.fit(x_train)
x_train_scaled = scaler.transform(x_train)
x_val_scaled = scaler.transform(x_val)


# 数据pca降维
pca = PCA(n_components=0.9)
x_train_pca = pca.fit_transform(x_train_scaled)
x_val_pca = pca.transform(x_val_scaled)
print("pca降维后: ",x_train_pca.shape,x_val_pca.shape)
# 可视化数据降维信息变化程度
plt.plot(np.cumsum(pca.explained_variance_ratio_))
# plt.xlabel("元素数量")
# plt.ylabel("可表达信息的百分占比")
plt.show()

在这里插入图片描述

在这里插入图片描述

2.2模型训练及调优

在这里插入图片描述

这一段运行起来需要些时间

# 模型训练
# 基本模型训练
xgb = XGBClassifier()
xgb.fit(x_train_pca,y_train)
# 输出预测值(一定是输出带有百分比的预测值)
y_pre_proba = xgb.predict_proba(x_val_pca)
# log-loss评估
print("基础训练的log_loss评估值: ",log_loss(y_val, y_pre_proba, eps=1e-15, normalize=True))

# 模型调优
scores_ne = []
n_estimators = [100,200,300,400,500,550,600,700]
for nes in n_estimators:
    print("n_estimators: ",nes)
    xgb=XGBClassifier(max_depth=3,learning_rate=0.1,n_estimators=nes,objective="multi:softprob",
                      n_jobs=-1,nthread=4,min_child_weight=1,subsample=1,colsample_bytree=1,seed=42)
    xgb.fit(x_train_pca,y_train)
    y_pre = xgb.predict_proba(x_val_pca)
    score = log_loss(y_val,y_pre)
    scores_ne.append(score)
    print("每次测试的log_loss评估值为:{}".format(score))
# 图形化logloss
plt.plot(n_estimators,scores_ne,"o-")
plt.xlabel("n_estimators")
plt.ylabel("log_loss")
plt.show()
print("最优的e_estimators的值是: {}".format(n_estimators[np.argmin(scores_ne)]))

# 最优max_depth的调试
scores_md = []
max_depths = [1,3,5,6,9]
for md in max_depths:
    print("max_depth: ",md)
    xgb=XGBClassifier(max_depth=md,learning_rate=0.1,n_estimators=n_estimators[np.argmin(scores_ne)],objective="multi:softprob",
                      n_jobs=-1,nthread=4,min_child_weight=1,subsample=1,colsample_bytree=1,seed=42)
    xgb.fit(x_train_pca,y_train)
    y_pre = xgb.predict_proba(x_val_pca)
    score = log_loss(y_val,y_pre)
    scores_md.append(score)
    print("每次测试的log_loss评估值为:{}".format(score))
# 图形化logloss
plt.plot(max_depths,scores_md,"o-")
plt.xlabel("max_depths")
plt.ylabel("log_loss")
plt.show()
print("最优的max_depth的值是: {}".format(max_depths[np.argmin(scores_md)]))

# (省略)调优min_child_weights,subsamples,consample_bytrees,etas
# 调优后这几个参数为min_child_weight=3,subsample=0.7,consample_bytree=0.7
# 找到最优参数后
xgb = XGBClassifier(max_depth=3,learning_rate=0.1,n_estimators=600,objective="multi:softprob",nthread=4,min_child_weight=3,subsample=0.7,colsample_bytree=0.7,seed=42)
xgb.fit(x_train_pca,y_train)
# y_pre = xgb.predict_proba(x_val_scaled)
y_pre = xgb.predict_proba(x_val_pca)
print("测试数据的log_loss值为: {}".format(log_loss(y_val,y_pre,eps=1e-15,normalize=True)))

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

由于有好几个参数min_child_weights,subsamples,consample_bytrees没有跑,没找出最优的值,所以最后的log_loss的值还是有些大的。
在这里插入图片描述

  • 20
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值