将 OneHotEncoder 用于决策树分类器中的分类特征

Posted

技术标签:

【中文标题】将 OneHotEncoder 用于决策树分类器中的分类特征【英文标题】:Using OneHotEncoder for categorical features in decision tree classifier 【发布时间】:2018-09-07 11:20:34 【问题描述】:

我是 Python 中的 ML 新手,对如何使用分类变量实现决策树感到非常困惑,因为它们会被 R 中的 partyctree 自动编码。

我想制作一个具有两个分类独立特征和一个依赖类的决策树。

我使用的数据框如下所示:

data
      title_overlap_quartile sales_rank_quartile rank_grp
    0                     Q4                  Q2    GRP 1
    1                     Q4                  Q3    GRP 1
    2                     Q2                  Q1    GRP 1
    3                     Q4                  Q1    GRP 1
    5                     Q2                  Q1    GRP 2

我知道分类特征需要在 scikit learn 中使用 labelencoder 和/或一个热编码器进行编码。

首先我尝试只使用标签编码器,但这并没有解决问题,因为DecisionTreeClassifier 开始将编码变量视为连续变量。然后我从这篇文章中读到:Issue with OneHotEncoder for categorical features 应该首先使用标签编码器对变量进行编码,然后使用一个热编码器再次编码。

我尝试通过以下方式在此数据集上实现该功能,但出现错误。

def encode_features(df, columns):
    le = preprocessing.LabelEncoder()
    ohe = preprocessing.OneHotEncoder(sparse=False)
    for i in columns:
        le.fit(df[i].unique())
        df[i+'_le'] = le.transform(df[i])
        df[i+'_le'] = df[i+'_le'].values.reshape(-1, 1)
        df[i+'_le'+'_ohe'] = ohe.fit_transform(df[i+'_le'])
    return(df)

data = encode_features(data, ['title_overlap_quartile', 'sales_rank_quartile'])


  File "/Users/vaga/anaconda2/envs/py36/lib/python3.5/site-packages/pandas/core/series.py", line 2800, in _sanitize_index
    raise ValueError('Length of values does not match length of ' 'index')

ValueError: Length of values does not match length of index

当我从函数中删除 ohe 部分并在外部运行时,它会运行但结果看起来很奇怪:

def encode_features(df, columns):
    le = preprocessing.LabelEncoder()
    ohe = preprocessing.OneHotEncoder(sparse=False)
    for i in columns:
        le.fit(df[i].unique())
        df[i+'_le'] = le.transform(df[i])
        # df[i+'_le'] = df[i+'_le'].values.reshape(-1, 1)
        # df[i+'_le'+'_ohe'] = ohe.fit_transform(df[i+'_le'])
    return(df)

data = encode_features(data, ['title_overlap_quartile', 'sales_rank_quartile']) 

data['title_overlap_quartile_le'] = data['title_overlap_quartile_le'].values.reshape(-1, 1)

print(ohe.fit_transform(data['title_overlap_quartile_le']))

[[ 1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.
   1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.
   1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.
   1.  1.  1.  1.  1.  1.  1.  1.  1.  1.]]

我还尝试使用pandas.get_dummies,它将变量转换为具有二进制编码的多列并使用它,但决策树分类器再次将其视为连续变量。

有人可以帮助我了解如何使用分类变量作为分类来拟合决策树并输出树图吗?

我正在使用的拟合和绘制树的代码是:

clf = tree.DecisionTreeClassifier()
clf = clf.fit(data[['title_overlap_score', 'sales_rank_quartile']], data[['rank_grp']])

dot_data = tree.export_graphviz(clf, out_file=None, feature_names=data[['title_overlap_score', 'sales_rank_quartile']].columns,  
                         filled=True, rounded=True,  
                         special_characters=True)  

graph = graphviz.Source(dot_data)  
graph.render("new_tree")

【问题讨论】:

【参考方案1】:

虽然决策树应该处理分类变量,但由于this 未解决的错误,sklearn 的实现目前不能。当前的解决方法有点复杂,是在将分类变量传递给分类器之前对它们进行一次热编码。

你试过category_encoders吗?这更容易处理,也可以在管道中使用。

latest 尚未发布的 scikit-learn 版本似乎允许字符串列类型,无需转换为 int。

【讨论】:

以上是关于将 OneHotEncoder 用于决策树分类器中的分类特征的主要内容,如果未能解决你的问题,请参考以下文章

尝试将 AdaBostM1 weka 分类器与配置用于修剪的 J48 决策树分类器一起使用时,Weka 引发命令行错误

决策树与随机森林

决策树

决策树唯一性sklearn

ValueError 将 sklearn 和 pandas 用于决策树?

决策树