一、问题
上篇文章中我们已经搞明白了逻辑回归的问题中,xgboost的train(),fit()方法以及不同参数的objective的对应的输出结果和关系,这篇文章我们就来研究下xgboost再做多分类时,train(),fit()建模后输出的值是怎么样的,它都有那些objective的参数,并且分别对应着怎样的输出?
二、objective参数比较
xgboost的官方文档关于多分类的objective如下:
从文档中我们可以看出,multi:softmax是使用softmax后产生的分类结果,而multi:softprob是输出的概率矩阵。我们这里以标签为0,1,2的三分类数据为例,前者输出的结果是一维数据,0,1,2的分类标签;后者输出的是n*3的概率矩阵(n为测试数据的条数)。
这两个参数之间有什么关系呢?
从这里我们可以看出,最终的分类标签是从概率矩阵中得到的,在n*3的概率矩阵中(如下图):
我们可以看出概率矩阵中每行数据的数值相加得1,我们取每行数据中概率值最大数值的下标作为最终的分类标签,然后给multi:softmax的输出结果做对比看是否一致。
xgb_params = {
'learning_rate': 0.1, # 步长
'n_estimators': 10,
'max_depth': 5, # 树的最大深度
'objective': 'multi:softprob',
'num_class': 3,
'min_child_weight': 1, # 决定最小叶子节点样本权重和,如果一个叶子节点的样本权重和小于min_child_weight则拆分过程结束。
'gamma': 0, # 指定了节点分裂所需的最小损失函数下降值。这个参数的值越大,算法越保守
'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))
softprob_pred = model.predict(xgb.DMatrix(x_test))
print softprob_pred
# 处理概率矩阵-得到最终的预测标签
indexlist = []
for item in softprob_pred:
maxnum = max(item)
item = np.where(item == maxnum)
indexlist.append(item[0].item())
################################
xgb_params = {
'learning_rate': 0.1, # 步长
'n_estimators': 20,
'max_depth': 5, # 树的最大深度
'objective': 'multi:softmax',
'num_class': 3,
'min_child_weight': 1, # 决定最小叶子节点样本权重和,如果一个叶子节点的样本权重和小于min_child_weight则拆分过程结束。
'gamma': 0, # 指定了节点分裂所需的最小损失函数下降值。这个参数的值越大,算法越保守
'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))
softmax_pred = model.predict(xgb.DMatrix(x_test))
count = 0
for i in np.arange(0, len(softmax_pred)):
if (softmax_pred[i] == indexlist[i]):
count += 1
print "len:", len(softmax_pred)
print "count:", count
if count == len(softmax_pred):
print "true"
else:
print "false"
输出的结果:
由此可见,最终的预测标签就是通过取概率矩阵的每行数据最大值的下标获得的。
那么问题来了,我们知道像xgboost这类集成树算法,他本身用到的是回归树,这就决定了它本身就是用来做回归的,调整后可以用来做分类,对于多分类来说是通过softmax函数把回归结果映射成最终的多分类标签的。我们把objective改成线性回归的参数(reg:linear),看下结果如何?如何通过softmax函数转换成最终分类标签?
输出结果如下:
得到的是一个一维0-2之间的预测值,怎么映射成一个831*3的矩阵呢?
对于softmax函数它的输入和输出是相同的shape,对于一个831*1的数据,得到的也是一个值都在0-1之间的831*1的数据,根本无法直接这样得到概率矩阵。这个问题有想法的同学可以加QQ群:821675528交流!
三、多分类问题中fit()和train()的结果
用相同的数据,相同的参数(objective:multi:softmax),分别用fit()和train()方法得到的输出结果是一致的,都是预测的0,1,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"
实验结果如下:
总结:综上我们可以看出xgboost多分类问题就是通过softmax函数做映射得到最终的分类标签,只是怎么把回归的结果映射成概率矩阵,我还没有搞清楚,有好的想法或者同样疑问的同学可以加QQ群:821675528交流!!
————————————————
版权声明:本文为CSDN博主「phyllisyuell」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/phyllisyuell/article/details/81011660