赞
踩
在应用XGBoost算法进行多分类应用时,发生了如下错误:
XGBoostError: b’value 0 for Parameter num_class should be greater equal to 1’
意思是,参数num_class的xgboost sklearn包装值0应该大于1。
忽然,我理解了参数及其设置,这里的”num_class“参数,与”objective“参数匹配,本案例是多分类应用,那么”objective“参数设置为”multi:softmax“,同时,”num_class“参数设置为”4“(本文用到的4个分类,0、1、2、3,分别代表着0-正常,1- 抽油杆断,2- 供液不足,3- 气影响,参考[3])。
本案例数据源为csv格式(csv格式为每个数据由逗号“,”分隔)。
0.29,0.31,32.8,92.5,22,20,0.7750820447097237,0.5326322957198866
0.61,0.76,7.8,84.4,42,40,0.6650599517190358,0.47773242152197465
0.21,0.23,19.8,84.8,31,30,0.6798212287221709,0.6725660513935667
0.25,0.28,88.1,94.3,75,74,0.529969222169283,0.5878974216397194
0.45,0.48,16.5,99.9,77,75,0.6958968659268767,0.7047297521312826
0.4,0,39.2,94.2,36,32,0.7301196680207003,0.48968041620245173
数据的含义分别是“油压”、“套压”、“产液量”、“含水率”、“上行电流”、“下行电流”,以及数据特征变换值“欧几里得距离”、“功图面积与基准面积的比值”。
使用numpy中的 loadtxt(‘gtdata0010.csv’, delimiter=",")读取csv格式数据进入到List中。
注:输入数据是数值型。XGBoost 和 CatBoost 以及 LGBM 算法不同,XGBoost 本身无法处理分类变量,而是像随机森林一样,只接受数值数据。因此在将分类数据传入 XGBoost 之前,必须通过各种编码方式:例如标记编码、均值编码或独热编码对数据进行处理。
由于每个井的井号是非数值型,而且只是个分类标识号,无数值意义。为了区分各个井的差别,体现相同的井,使用井的描述参数,例如:泵径、沉没度、下泵深度等等。
XGBoost模型objective说明:
params ={'learning_rate': 0.1,
'max_depth': 5,
'num_boost_round':20,
'objective': 'multi:softmax',
'random_state': 27,
'silent':0,
'num_class':4
}
model = xgb.train(params,xgb.DMatrix(X_train, y_train))#,num_boost_round=20)
y_pred=model.predict(xgb.DMatrix(X_test))
在多分类预测模型下,预测输出分为两种情况:一是直接输出分类,参数’objective’为’multi:softmax’;另一种是输出各个分类的概率,参数’objective’为’multi:softprob’。本案例使用输出各个分类概率,贴近实际工作场景,如出现一种工况,计算机给出“供液不足”的概率是78%、“气影响”的概率是21%、其他…。
通过取出最大概率的分类,则可以为预测分析结果,如下代码所示:
y_pred=model.predict(xgb.DMatrix(X_test))
yprob = np.argmax(y_pred, axis=1) # return the index of the biggest pro
注:训练模型时,输入的标签(Lable)为单列分类数字,例如本案例分类为[0,1,2,3],通过代码中“np.argmax(y_pred, axis=1)”取到最大概率值的位置为结果。
对于数据源,分成训练数据及其对应的标签,例如本案例中的“gtdata0010.csv”为训练数据的自变量X,“gtlable001.csv”为训练数据的因变量Y。数据源准备,先由少量再到大量数据,数据维度和特征也逐步扩大。
随着数据维度和特征的增加,模型的准确度也在提高。如下图所示,数据增加了2个维度。
看到“Feature Importance”图的代码如下所示:
# 显示重要特征
plot_importance(model)
plt.show()
数据预处理、特征工程、调参对Xgboost的效果有着非常重要的影响。
在这里只介绍Tree,重点是调优“learning_rate”学习率和“max_dept”构建树的深度,一般学习率中0.1 ~ 1间调整,而树的深度是随着数据量和维度增加而增加,我实验的经历是从5开始,已经到24了,再增大的效果是反而下降。网上推荐“max_dept”取值为6 ~ 10。
params ={'learning_rate': 0.4,
'max_depth': 20, # 构建树的深度,越大越容易过拟合
'num_boost_round':2000,
'objective': 'multi:softprob', # 多分类的问题
'random_state': 7,
'silent':0,
'num_class':4, # 类别数,与 multisoftmax 并用
'eta':0.8 #为了防止过拟合,更新过程中用到的收缩步长。eta通过缩减特征 的权重使提升计算过程更加保守。缺省值为0.3,取值范围为:[0,1]
}
关于优化,后续将参考寒小阳的博文《机器学习系列(12)_XGBoost参数调优完全指南(附Python代码)》 ,使用xgb.cv()函数交叉验证,优化参数。
''' Created on 2019年4月1日 @author: xiaoyw ''' from xgboost import plot_importance from matplotlib import pyplot as plt import xgboost as xgb from numpy import loadtxt from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score import numpy as np # load data dataset = loadtxt('gtdata0010.csv', delimiter=",") # split data into X and y X = dataset[:,:8] dataset = loadtxt('gtlable001.csv', delimiter=",") Y = dataset[:,1] # split data into train and test sets seed = 7 test_size = 0.2 X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=test_size, random_state=seed) params ={'learning_rate': 0.4, 'max_depth': 20, # 构建树的深度,越大越容易过拟合 'num_boost_round':2000, 'objective': 'multi:softprob', # 多分类的问题 'random_state': 7, 'silent':0, 'num_class':4, # 类别数,与 multisoftmax 并用 'eta':0.8 #为了防止过拟合,更新过程中用到的收缩步长。eta通过缩减特征 的权重使提升计算过程更加保守。缺省值为0.3,取值范围为:[0,1] } model = xgb.train(params,xgb.DMatrix(X_train, y_train)) y_pred=model.predict(xgb.DMatrix(X_test)) model.save_model('testXGboostClass.model') # 保存训练模型 yprob = np.argmax(y_pred, axis=1) # return the index of the biggest pro predictions = [round(value) for value in yprob] # evaluate predictions accuracy = accuracy_score(y_test, predictions) print("Accuracy: %.2f%%" % (accuracy * 100.0)) # 显示重要特征 plot_importance(model) plt.show()
这段是困惑的内容,以下是摘自网络参考文档,还未展开研究。
1、xgboost.XGBClassifier()利用函数参数设置模型参数
XGBClassifier()使用sklearn接口(推荐) ,XGBClassifier - 是xgboost的sklearn包。这个包允许我们像GBM一样使用Grid Search 和并行处理。
2、xgboost.train()利用param列表设置模型参数。
原始的xgboost,xgb - 直接引用xgboost。 有“cv”函数。
参考代码,还抽出时间实验,先收录到本文中再用[2]。
clf = XGBClassifier( n_estimators=20, # 迭代次数 learning_rate=0.1, # 步长 max_depth=5, # 树的最大深度 min_child_weight=1, # 决定最小叶子节点样本权重和 silent=1, # 输出运行信息 subsample=0.8, # 每个决策树所用的子样本占总样本的比例(作用于样本) colsample_bytree=0.8, # 建立树时对特征随机采样的比例(作用于特征)典型值:0.5-1 objective='multi:softmax', # 多分类!!!!!! num_class=3, nthread=4, seed=27) print "training..." clf.fit(x_train, y_train, verbose=True) fit_pred = clf.predict(x_test) print fit_pred xgb_params = { 'learning_rate': 0.1, # 步长 'max_depth': 5, # 树的最大深度 'objective': 'multi:softmax', 'num_class': 3, 'min_child_weight': 1, # 决定最小叶子节点样本权重和,如果一个叶子节点的样本权重和小于min_child_weight则拆分过程结束。 'silent': 0, # 输出运行信息 'subsample': 0.8, 'colsample_bytree': 0.8, # 建立树时对特征随机采样的比例(作用于特征)典型值:0.5-1 'nthread': 4, 'seed': 27} print "training..." model = xgb.train(xgb_params, xgb.DMatrix(x_train, y_train), num_boost_round=20) train_pred = model.predict(xgb.DMatrix(x_test)) count = 0 print train_pred # 判断train_pred和fit_pred是否一致 for i in np.arange(0, len(train_pred)): if (train_pred[i] == fit_pred[i]): count += 1 print "len:", len(train_pred) print "count:", count if count == len(train_pred): print "true" else: print "false"
参考:
[1]《XGBOOST从原理到实战:二分类 、多分类》 CSDN博客 DemonHunter211 2018年7月
[2]《xgboost 多分类:objective参数(reg:linear,multi:softmax,multi:softprob)对比分析》 CSDN博客 phyllisyuell 2018年7月
[3]《TensorFlow CNN卷积神经网络实现工况图分类识别(一)》 CSDN博客 肖永威 2019年3月
[4]《xgboost.XGBClassifier, xgboost.train()》 CSDN博客 liulina603 2017年12月
[5]《XGBoost算法应用入门学习实践》 CSDN博客 肖永威 2018年6月
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。