笔记,记录龙珠机器学习训练营的第二阶段,关于xgboost的学习
xgboost有听说过,也在kaggle上经常看到有人用。关于原理这方面,网络上大都只有应用的资料,关于原理的很少,通俗来讲,xgboost属于梯度提升树(GBDT)模型的范畴,GBDT的基本思想是让n层模型去拟合n-1层模型的偏差,从而不断使加法模型的偏差降低。相比于GBDT,xgboost做了一些改进,从而在效果和性能上有明显的提升。本节我们的重点还是放在实战应用上。
#代码是在DSW上运行,首先下载天池提供的天气数据集
!wget https://tianchi-media.oss-cn-beijing.aliyuncs.com/DSW/7XGBoost/train.csv
#读取数据并简略查看
import pandas as pd
data = pd.read_csv('train.csv')
data.head(5)
#可以看到train数据集中每一条数据有23个特征值
可以看到数据是某天的天气状况,其中RainTomorrow属于预测label
特征名称 | 意义 | 取值范围 |
---|---|---|
Date | 日期 | 字符串 |
Location | 气象站的地址 | 字符串 |
MinTemp | 最低温度 | 实数 |
MaxTemp | 最高温度 | 实数 |
Rainfall | 降雨量 | 实数 |
Evaporation | 蒸发量 | 实数 |
Sunshine | 光照时间 | 实数 |
WindGustDir | 最强的风的方向 | 字符串 |
WindGustSpeed | 最强的风的速度 | 实数 |
WindDir9am | 早上9点的风向 | 字符串 |
WindDir3pm | 下午3点的风向 | 字符串 |
WindSpeed9am | 早上9点的风速 | 实数 |
WindSpeed3pm | 下午3点的风速 | 实数 |
Humidity9am | 早上9点的湿度 | 实数 |
Humidity3pm | 下午3点的湿度 | 实数 |
Pressure9am | 早上9点的大气压 | 实数 |
Pressure3pm | 早上3点的大气压 | 实数 |
Cloud9am | 早上9点的云指数 | 实数 |
Cloud3pm | 早上3点的云指数 | 实数 |
Temp9am | 早上9点的温度 | 实数 |
Temp3pm | 早上3点的温度 | 实数 |
RainToday | 今天是否下雨 | No,Yes |
RainTomorrow | 明天是否下雨 | No,Yes |
#对于缺省值,用-1填充
data = data.fillna(-1)
#查看数据集中label的分布情况
pd.Series(data['RainTomorrow']).value_counts()
#可以看到负样本的数量是要大于正样本,不平衡
#将数字value和非数字value分别存储
numerical_features = [x for x in data.columns if data[x].dtype == np.float]
category_features = [x for x in data.columns if data[x].dtype != np.float and x != 'RainTomorrow']
#选取降雨量、蒸发量、光照时间以明日是否降雨进行分类并绘制散点图
sns.pairplot(data=data[['Rainfall','Evaporation','Sunshine'] +
['RainTomorrow']], diag_kind='hist', hue= 'RainTomorrow')
plt.show()
从上图可以发现,在2D情况下不同的特征组合对于第二天下雨与不下雨的散点分布,以及大概的区分能力。相对的Sunshine与其他特征的组合更具有区分能力
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()
利用箱型图我们也可以得到不同类别在不同特征上的分布差异情况。我们可以发现Sunshine,Humidity3pm,Cloud9am,Cloud3pm的区分能力较强
#用tlog和flog统计明日是否降雨的所有value的分布情况
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()
如tolg中Location项存储所有地区出现raintomorrow的次数情况
#绘制降雨和不降雨两幅图,以地区为分类条件
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()
从上图可以发现不同地区降雨情况差别很大,有些地方明显更容易降雨
#分析raintoday对raintomorrow的影响
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()
两图分别代表today下雨的yes or no对raintomorrow下雨的影响,图一看出今天下雨并不会对明天下雨有影响,但是今天天晴,明天大概率天气为晴
# 把所有的相同类别的特征编码为同一个值
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:#非数字value编码
data[i] = data[i].apply(get_mapfunction(data[i]))
data['Location'].unique()
#例如Location被从0到48进行编码,转化成数字类型
from sklearn.model_selection import train_test_split
data_target_part = data['RainTomorrow']#预测label提出
data_features_part = data[[x for x in data.columns if x != 'RainTomorrow']]#除去label的data作为train的数据
x_train, x_test, y_train, y_test = train_test_split(data_features_part, data_target_part, test_size = 0.2, random_state = 2021)
#训练集和测试集4:1划分
#导入模型并对traindata和trainlabel进行拟合
from xgboost.sklearn import XGBClassifier
clf = XGBClassifier()
clf.fit(x_train, y_train)
train_predict = clf.predict(x_train)
test_predict = clf.predict(x_test)
#对x_train进行回测正确率0.85,在划分的x_test测试正确率0.84
#我们可以通过查看模型的参数观察不同feature的权重
sns.barplot(y=data_features_part.columns, x=clf.feature_importances_)
#如下图,所有feature中,最为突出的为下午三点湿度和今日是否下雨,这两个也是影响明日降雨的最关键因素
另外对于model的调参,使用GridSearchCV寻找最佳参数或是手动调参都是可以的。
XGBoost中包括但不限于下列对模型影响较大的参数:
#下面举例,对四个参数分别选取可能的最优结果并存储到para字典,传入GridSearchCV进行三次cv验证得到最优参数的clf
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,5,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_
#如本次参数选取了如下图所示为最优