Pipeline 和 GridSearchCV,以及 XGBoost 和 RandomForest 的多类挑战

Posted

技术标签:

【中文标题】Pipeline 和 GridSearchCV,以及 XGBoost 和 RandomForest 的多类挑战【英文标题】:Pipeline and GridSearchCV, and Multi-Class challenge for XGBoost and RandomForest 【发布时间】:2020-07-12 19:00:30 【问题描述】:

我正在使用 Pipeline 和 GridSearchCV 处理工作流。

MWE for RandomForest,如下,

#################################################################
# Libraries
#################################################################
import time
import pandas as pd
import numpy as np
from sklearn.pipeline import Pipeline
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier

#################################################################
# Data loading and Symlinks
#################################################################
train = pd.read_csv("data_train.csv")
test = pd.read_csv("data_test.csv")

#################################################################
# Train Test Split
#################################################################
# Selected features - Training data
X = train.drop(columns='fault_severity')

# Training data
y = train.fault_severity

# Test data
x = test

# Break off validation set from training data
X_train, X_valid, y_train, y_valid = train_test_split(X, y, train_size=0.8, test_size=0.2, random_state=0)

#################################################################
# Pipeline
#################################################################
pipe_rf = Pipeline([
    ('clf', RandomForestClassifier(random_state=0))
    ])

parameters_rf = 
        'clf__n_estimators':[30,40], 
        'clf__criterion':['entropy'], 
        'clf__min_samples_split':[15,20], 
        'clf__min_samples_leaf':[3,4]
    

grid_rf = GridSearchCV(pipe_rf,
    param_grid=parameters_rf,
    scoring='neg_mean_absolute_error',
    cv=5,
    refit=True) 

#################################################################
# Modeling
#################################################################
start_time = time.time()

grid_rf.fit(X_train, y_train)

#Calculate the score once and use when needed
mae = grid_rf.score(X_valid,y_valid)

print("Best params                        : %s" % grid_rf.best_params_)
print("Best training data MAE score       : %s" % grid_rf.best_score_)    
print("Best validation data MAE score (*) : %s" % mae)
print("Modeling time                      : %s" % time.strftime("%H:%M:%S", time.gmtime(time.time() - start_time)))

#################################################################
# Prediction
#################################################################
#Predict using the test data with selected features
y_pred = grid_rf.predict(x)

# Transform numpy array to dataframe
y_pred = pd.DataFrame(y_pred)

# Rearrange dataframe
y_pred.columns = ['prediction']
y_pred.insert(0, 'id', x['id'])

# Save to CSV
y_pred.to_csv("data_predict.csv", index = False, header=True)
#Output
# id,prediction
# 11066,0
# 18000,2
# 16964,0
# ...., ....

有一个MWE for XGBoost,如下所示,

#################################################################
# Libraries
#################################################################
import time
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
import xgboost as xgb
from sklearn.pipeline import Pipeline
from sklearn.model_selection import GridSearchCV

#################################################################
# Data loading and Symlinks
#################################################################
train = pd.read_csv("data_train.csv")
test = pd.read_csv("data_test.csv")

#################################################################
# Train Test Split
#################################################################

# Selected features - Training data
X = train.drop(columns='fault_severity')

# Training data
y = train.fault_severity

# Test data
x = test

# Break off validation set from training data
X_train, X_valid, y_train, y_valid = train_test_split(X, y, train_size=0.8, test_size=0.2, random_state=0)

#################################################################
# DMatrix
#################################################################
dtrain = xgb.DMatrix(data=X_train, label=y_train)
dtest = xgb.DMatrix(data=test)

params = 
    'max_depth': 6,
    'objective': 'multi:softprob',  # error evaluation for multiclass training
    'num_class': 3,
    'n_gpus': 0


#################################################################
# Modeling
#################################################################
start_time = time.time()
bst = xgb.train(params, dtrain)

#################################################################
# Prediction
#################################################################
#Predict using the test data with selected features
y_pred = bst.predict(dtest)

# Transform numpy array to dataframe
y_pred = pd.DataFrame(y_pred)

# Rearrange dataframe
y_pred.columns = ['prediction_0', 'prediction_1', 'prediction_2']
y_pred.insert(0, 'id', x['id'])

# Save to CSV
y_pred.to_csv("data_predict_xgb.csv", index = False, header=True)
# Expected Output:
# id,prediction_0,prediction_1,prediction_2
# 11066,0.4674369,0.46609518,0.06646795
# 18000,0.7578633,0.19379888,0.048337903
# 16964,0.9296321,0.04505246,0.025315404
# ...., ...., ...., ....

问题:

    如何使用 MWE for RandomForest 中的 Pipeline 和 GridSearchCV 技术将 MWE 转换为 XGBoost?必须在 XGBRegressor() 不支持的地方使用 'num_class'。

    如何将 RandomForrest 的多类预测输出作为 XGBoost(即 predict_0、predict_1、predict_2)?示例输出在上面的 MWE 中给出。我发现 num_class 不受 RandomForest 分类器的支持。

我花了几天的时间来解决这个问题,但仍然被阻止。感谢一些前进的指示。

数据:

    data_train:https://www.dropbox.com/s/bnomyoidkcgyb2y/data_train.csv 数据测试:https://www.dropbox.com/s/kn1bgde3hsf6ngy/data_test.csv

【问题讨论】:

【参考方案1】:

我假设在您的第一个问题中,您并不是指XGBRegressor

为了让XGBClassifier 在管道中运行,您只需更改管道的初始定义:

params = 
    'max_depth': 6,
    'objective': 'multi:softprob',
    'num_class': 3,
    'n_gpus': 0

pipe_xgb = Pipeline([
    ('clf', xgb.XGBClassifier(**params))
])

(注意:我已将管道名称更改为 pipe_xgb,因此您需要在其余代码中进行更改。)

从this question 的回答中可以看出,如果目标变量中有两个以上的类,XGBoost 会自动切换到多类分类。所以你既不能也不需要指定num_class

您还应该将指标更改为一个以进行分类,因为在您的每个示例中您都使用 MAE,这是一个回归指标。

这是您的代码的完整示例,使用 XGBClassifieraccuracy 作为指标:

#################################################################
# Libraries
#################################################################
import time
import pandas as pd
import numpy as np
from sklearn.pipeline import Pipeline
from sklearn.metrics import accuracy_score
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier

import xgboost as xgb

#################################################################
# Data loading and Symlinks
#################################################################
train = pd.read_csv("https://dl.dropbox.com/s/bnomyoidkcgyb2y/data_train.csv?dl=0")
test = pd.read_csv("https://dl.dropbox.com/s/kn1bgde3hsf6ngy/data_test.csv?dl=0")

#################################################################
# Train Test Split
#################################################################
# Selected features - Training data
X = train.drop(columns='fault_severity')

# Training data
y = train.fault_severity

# Test data
x = test

# Break off validation set from training data
X_train, X_valid, y_train, y_valid = train_test_split(X, y, train_size=0.8, test_size=0.2, random_state=0)


#################################################################
# Pipeline
#################################################################
params = 
    'max_depth': 6,
    'objective': 'multi:softprob',  # error evaluation for multiclass training
    'num_class': 3,
    'n_gpus': 0

pipe_xgb = Pipeline([
    ('clf', xgb.XGBClassifier(**params))
    ])

parameters_xgb = 
        'clf__n_estimators':[30,40], 
        'clf__criterion':['entropy'], 
        'clf__min_samples_split':[15,20], 
        'clf__min_samples_leaf':[3,4]
    

grid_xgb = GridSearchCV(pipe_xgb,
    param_grid=parameters_xgb,
    scoring='accuracy',
    cv=5,
    refit=True)

#################################################################
# Modeling
#################################################################
start_time = time.time()

grid_xgb.fit(X_train, y_train)

#Calculate the score once and use when needed
acc = grid_xgb.score(X_valid,y_valid)

print("Best params                        : %s" % grid_xgb.best_params_)
print("Best training data accuracy        : %s" % grid_xgb.best_score_)    
print("Best validation data accuracy (*)  : %s" % acc)
print("Modeling time                      : %s" % time.strftime("%H:%M:%S", time.gmtime(time.time() - start_time)))

#################################################################
# Prediction
#################################################################
#Predict using the test data with selected features
y_pred = grid_xgb.predict(X_valid)

# Transform numpy array to dataframe
y_pred = pd.DataFrame(y_pred)

# Rearrange dataframe
y_pred.columns = ['prediction']
y_pred.insert(0, 'id', x['id'])
accuracy_score(y_valid, y_pred.prediction)

编辑以解决评论中的其他问题。

您可以使用xgbsklearn API 的predict_proba 方法来获取每个类的概率:

y_pred = pd.DataFrame(grid_xgb.predict_proba(X_valid),
                      columns=['prediction_0', 'prediction_1', 'prediction_2'])
y_pred.insert(0, 'id', x['id'])

使用上面的代码,y_pred 的格式如下:

      id  prediction_0  prediction_1  prediction_2
0  11066      0.490955      0.436085      0.072961
1  18000      0.718351      0.236274      0.045375
2  16964      0.920252      0.052558      0.027190
3   4795      0.958216      0.021558      0.020226
4   3392      0.306204      0.155550      0.538246

【讨论】:

谢谢。从你那里学到了新东西,尤其是 **params 方法。 y_pred 在我的 XGB MWE 中的预期输出是 #id,prediction_0,prediction_1,prediction_2 #11066,0.4674369,0.46609518,0.06646795 #18000,0.7578633,0.19379888,0.048337903 .但是得到了 #id,prediction #160,1 #id,prediction #1有没有办法以预期的格式获取它。 @SaravananK 很高兴能够提供帮助。我已经为答案添加了更新——这样做有用吗? 它就像一个魅力。进一步研究了 XGBoost 的 predict_proba API。 xgboost.readthedocs.io/en/latest/python/python_api.html 为 RandomForestClassifier 寻找类似的东西。已经凌晨 3 点了,明天将继续研究这个。我的意思是今天晚些时候。你一直很有帮助。谢谢:-) 我的荣幸。 RandomForestClassifier 也有一个 predict_proba 方法,所以你应该可以从你的第一个例子中调用它。请参阅文档here。 我已经研究并测试了您的建议。再次,它完美无瑕。谢谢

以上是关于Pipeline 和 GridSearchCV,以及 XGBoost 和 RandomForest 的多类挑战的主要内容,如果未能解决你的问题,请参考以下文章

Scikit-learn 多输出分类器使用:GridSearchCV、Pipeline、OneVsRestClassifier、SGDClassifier

Scikit Learn GridSearchCV 和 pipeline 使用不同的方法

使用 scikit-learn Pipeline 和 GridSearchCV 时出错

Scikit-learn 中的 GridSearchCV 输出问题

将 Sklearn GridSearchCV 与 Pipeline 一起使用时如何传递权重

GridSearchCV 是用 rbf 内核和不同程度计算 SVC 吗?