在使用DecisionTreeClassifier时,我使用graphviz进行了可视化,让我惊讶的是,它似乎将分类数据当作连续数据来使用。
我所有的特征都是分类特征,例如,你可以看到如下决策树(请注意,第一个特征X[0]有6个可能的值:0, 1, 2, 3, 4, 5):根据这里的描述,该类使用的是二叉树,这在sklearn中是一个限制条件。
有没有人知道我遗漏了什么方法可以让决策树以分类的方式使用数据?(我知道这对任务来说不是最佳方法,但由于目前需要分类,我在数据上使用了一热编码向量)。
原始数据的一个样本如下所示:
f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 c1 c2 c30 C S O 1 2 1 1 2 1 2 0 0 01 D S O 1 3 1 1 2 1 2 0 0 02 C S O 1 3 1 1 2 1 1 0 0 03 D S O 1 3 1 1 2 1 2 0 0 04 D A O 1 3 1 1 2 1 2 0 0 05 D A O 1 2 1 1 2 1 2 0 0 06 D A O 1 2 1 1 2 1 1 0 0 07 D A O 1 2 1 1 2 1 2 0 0 08 D K O 1 3 1 1 2 1 2 0 0 09 C R O 1 3 1 1 2 1 1 0 0 0
其中X[0] = f1,我将字符串编码为整数,因为sklearn不接受字符串。
回答:
确实让我惊讶的是,sklearn的决策树确实无法处理分类数据。有一个关于此问题的Github issue(#4899)从2015年6月开始,但它仍然未解决(更新:现在已关闭,但继续在#12866中进行讨论,因此问题仍未解决)。
像你在这里所做的那样,将分类变量编码为整数的问题在于,它为它们强加了一个顺序,这可能有意义也可能没有意义,具体取决于情况;例如,你可以将['low', 'medium', 'high']
编码为[0, 1, 2]
,因为'low' < 'medium' < 'high'
(我们称这些分类变量为有序),尽管你仍然隐式地做出了额外的(可能不希望的)假设,即'low'
和'medium'
之间的距离与'medium'
和'high'
之间的距离相同(在决策树中没有影响,但在k-nn和聚类中很重要)。但这种方法在像['red','green','blue']
或['male','female']
这样的情况下完全失败,因为我们无法声称它们之间有任何有意义的相对顺序。
因此,对于非有序的分类变量,正确的编码方法是使用OneHotEncoder
模块。用户指南中的编码分类特征部分也可能有帮助。