我正在一些Panda数据帧X
上训练决策树分类器。
clf = DecisionTreeClassifier()
clf = clf.fit(X, y)
现在,我遍历树clf.tree_
,并希望获得属于该内部节点或叶的记录(最好是作为数据帧(。我现在所做的事情如下。
fn = [ X.columns[i] if i != TREE_UNDEFINED else "undefined!" for i in clf.tree_.feature ]
def recurse(node, tmp):
tree = clf.tree_
if self.test_node(tmp):
return
if tree.feature[node] != TREE_UNDEFINED:
mask = tmp[fn[node]] <= tree.threshold[node]
recurse(tree.children_left[node], tmp[mask])
recurse(tree.children_right[node], tmp[~mask])
recurse(0, X)
这显然是有效的,但当对10K树执行此操作时,我使用探查器发现,代码中95%以上的时间都花在了拆分数据帧上。数据的运行拟合可能是2%,我对每个节点的数据帧所做的就是剩下的
是否有更高效的方法来拆分数据?
我假设DT内部必须拆分数据(我可以得到每个节点的记录数(。我可以以某种方式将df附加到节点上吗?
**更新**
建议使用CCD_ 3。在该矩阵中,每列j
表示一个节点,而行i
中的1
表示它通过该节点。
我试了几个";方法";使用这个矩阵得到每个节点的df。所有这些都比我目前使用的天真方法慢。
Walk tree: default: 2.4888 s +- 0.01 s per loop (mean +- std. dev. of 10 runs, 50 loops each)
Walk tree: no recursion: 2.5427 s +- 0.07 s per loop (mean +- std. dev. of 10 runs, 50 loops each)
Walk tree: decision path Numpy : 16.5346 s +- 0.08 s per loop (mean +- std. dev. of 10 runs, 50 loops each)
Walk tree: decision path Scipy: 8.8154 s +- 0.56 s per loop (mean +- std. dev. of 10 runs, 50 loops each)
Walk tree: decision path Pandas: 28.3901 s +- 0.69 s per loop (mean +- std. dev. of 10 runs, 50 loops each)
对于使用该数组的方法中速度最快的Scipy,我还试图了解获取索引还是部分df是最耗时的。
Walk tree: decision path Scipy: 5.3404 s +- 0.20 s per loop (mean +- std. dev. of 10 runs, 30 loops each)
Walk tree: decision path Scipy (take=False): 4.5698 s +- 0.27 s per loop (mean +- std. dev. of 10 runs, 30 loops each)
我还尝试将上面的基本递归更改为使用df.query(..)
,但速度也较慢。
我相信
pd.DataFrame(clf.decision_path(X).toarray())
可能是你想要的。如果观察i
经过树的节点j
,则结果中的条目[i, j]
将为1。这里还有一个关于决策树结构的很好的例子,可能会有所帮助。