【发布时间】:2021-12-25 14:24:37
【问题描述】:
我正在一些 pandas 数据框 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 放在节点上吗?
** 更新 **
建议使用clf.decision_path(X).toarray()。在这个矩阵中,每一列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(..),但这也较慢。
【问题讨论】:
标签: pandas scikit-learn decision-tree