如何在sklearn的GradientBoostingClassifier中处理分类变量?

12 投票
2 回答
24746 浏览
提问于 2025-04-18 13:00

我正在尝试使用GradientBoostingClassifier来训练模型,数据中包含分类变量。

下面是一个简单的代码示例,目的是尝试将分类变量输入到GradientBoostingClassifier中。

from sklearn import datasets
from sklearn.ensemble import GradientBoostingClassifier
import pandas

iris = datasets.load_iris()
# Use only data for 2 classes.
X = iris.data[(iris.target==0) | (iris.target==1)]
Y = iris.target[(iris.target==0) | (iris.target==1)]

# Class 0 has indices 0-49. Class 1 has indices 50-99.
# Divide data into 80% training, 20% testing.
train_indices = list(range(40)) + list(range(50,90))
test_indices = list(range(40,50)) + list(range(90,100))
X_train = X[train_indices]
X_test = X[test_indices]
y_train = Y[train_indices]
y_test = Y[test_indices]

X_train = pandas.DataFrame(X_train)

# Insert fake categorical variable. 
# Just for testing in GradientBoostingClassifier.
X_train[0] = ['a']*40 + ['b']*40

# Model.
clf = GradientBoostingClassifier(learning_rate=0.01,max_depth=8,n_estimators=50).fit(X_train, y_train)

出现了以下错误:

ValueError: could not convert string to float: 'b'

根据我的理解,在GradientBoostingClassifier构建模型之前,需要对分类变量进行独热编码

请问GradientBoostingClassifier能否在不进行独热编码的情况下,直接使用分类变量来构建模型呢?

R语言中的gbm包能够处理上述样本数据。我希望找到一个功能相当的Python库。

2 个回答

-5

当然可以处理这个问题,你只需要在流程中单独对分类变量进行编码。Sklearn 完全能够处理分类变量,就像 R 语言或其他机器学习工具一样。R 语言的工具在后台也在进行一种叫做“独热编码”的操作,只是它在这个情况下没有把编码和模型训练分开来处理(其实这样分开处理会更好)。

11

pandas.get_dummies 或者 statsmodels.tools.tools.categorical 可以用来把分类变量转换成一个虚拟矩阵。然后,我们可以把这个虚拟矩阵合并回训练数据中。

下面是问题中的示例代码,展示了上述过程是如何进行的。

from sklearn import datasets
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.metrics import roc_curve,auc
from statsmodels.tools import categorical
import numpy as np

iris = datasets.load_iris()
# Use only data for 2 classes.
X = iris.data[(iris.target==0) | (iris.target==1)]
Y = iris.target[(iris.target==0) | (iris.target==1)]

# Class 0 has indices 0-49. Class 1 has indices 50-99.
# Divide data into 80% training, 20% testing.
train_indices = list(range(40)) + list(range(50,90))
test_indices = list(range(40,50)) + list(range(90,100))
X_train = X[train_indices]
X_test = X[test_indices]
y_train = Y[train_indices]
y_test = Y[test_indices]


###########################################################################
###### Convert categorical variable to matrix and merge back with training
###### data.

# Fake categorical variable.
catVar = np.array(['a']*40 + ['b']*40)
catVar = categorical(catVar, drop=True)
X_train = np.concatenate((X_train, catVar), axis = 1)

catVar = np.array(['a']*10 + ['b']*10)
catVar = categorical(catVar, drop=True)
X_test = np.concatenate((X_test, catVar), axis = 1)
###########################################################################

# Model and test.
clf = GradientBoostingClassifier(learning_rate=0.01,max_depth=8,n_estimators=50).fit(X_train, y_train)

prob = clf.predict_proba(X_test)[:,1]   # Only look at P(y==1).

fpr, tpr, thresholds = roc_curve(y_test, prob)
roc_auc_prob = auc(fpr, tpr)

print(prob)
print(y_test)
print(roc_auc_prob)

感谢Andreas Muller的指导,提醒我们在使用scikit-learn的估计器时,不应该使用pandas的Dataframe。

撰写回答