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

Posted

技术标签:

【中文标题】如何处理 sklearn GradientBoostingClassifier 中的分类变量?【英文标题】:How to handle categorical variables in sklearn GradientBoostingClassifier? 【发布时间】:2014-09-02 14:34:21 【问题描述】:

我正在尝试使用分类变量训练带有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 可以构建模型之前,似乎需要在分类变量上使用One Hot Encoding。

GradientBoostingClassifier 可以使用分类变量构建模型而无需进行一次热编码吗?

R gbm 包能够处理上面的示例数据。我正在寻找具有同等功能的 Python 库。

【问题讨论】:

您确实需要使用 OneHotEncoder。那么这应该不是问题。另外,不要将 pandas DataFrames 放入 scikit-learn 估计器中,您应该使用 numpy 数组(通过调用 np.array(dataframe) 或 dataframe.values)。 有work in progress 允许这样做。 与this one相同的问题。 【参考方案1】:

当然它可以处理它,您只需将分类变量编码为管道上的一个单独步骤。 Sklearn 完全能够处理分类变量以及 R 或任何其他 ML 包。 R 包仍然(可能)在幕后进行 one-hot 编码,它只是没有在这种情况下分离编码和拟合的问题(可以说应该)。

【讨论】:

Afaik 一些 R 库本机处理分类变量。在决策树中,使用 one-hot 编码与使用分类变量不同。 Sklearn 仅适用于 numpy 数组,不允许混合类型。【参考方案2】:

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 指示不应将 pandas Dataframe 用于 scikit-learn 估算器。

【讨论】:

以上是关于如何处理 sklearn GradientBoostingClassifier 中的分类变量?的主要内容,如果未能解决你的问题,请参考以下文章

如何处理 sklearn 随机森林中的类不平衡。我应该使用样本权重还是类权重参数

sklearn.cluster.KMeans 如何处理缺少质心(可用质心小于 n_clusters)的 init ndarray 参数?

如何处理多元线性回归中的误差维度?

决策树分类器如何处理全局约束?

sklearn 集成和树中连续变量的分箱

处理 sklearn.tree.DecisionTreeClassifier 中的连续变量