Scikit-learn: 为决策树添加后修剪

创建于 2016-03-16  ·  64评论  ·  资料来源: scikit-learn/scikit-learn

我经常被问到有关修剪后的问题。 通常使用单个树对于可解释性很重要,而后修剪可以帮助可解释性和泛化性能。
[我很惊讶对此没有公开的问题,但是我找不到一个]

Moderate New Feature help wanted

最有用的评论

大家好 ,
我已经实现了:
CCP(成本复杂度修剪)算法
Python中的sklearn-CART-Classification-model,

ECP(错误复杂度修剪)算法
Python中的sklearn-CART-Regression-model,

这里是链接:
https://github.com/appleyuchi/Decision_Tree_Prune
你可能会喜欢。

所有64条评论

我可以试一下:)

这个问题#941似乎也在向树提议修剪方法,但是与此同时,我想代码也发生了很大的变化。

关于可解释性的主题,也已经发表了有关从随机森林中创建单个决策树的工作。 听起来有点违反直觉,由于标准决策树算法的非最佳性,这显然可以提供可以解释的单个决策树,并且比其他方法更好地提供分类器/回归器。

@amueller您能解释一下这个问题吗? 我想做这个。

实际上,可能要做的第一件事就是根据共同信息添加一个停止条件...

@lesshaste可以引用吗? (该死的,我最近一直在想,显然已经做到了^^)

@amueller自从我看了很久以来,但是:

第2.2节
Morteza Mashayekhi和Robin Gras撰写的“从随机森林中提取规则:RF + HC方法”具有我所知道的所有相关引用。 如果您无权访问此文件,请告诉我。

仅在一点相关的注释上,我记得有兴趣地看过http://blog.datadive.net/interpreting-random-forests/

实际上,可能要做的第一件事就是根据共同信息添加一个停止条件...

一个简单的加法就是在p(t) i(t, s*) < beta时停止构建,即当最佳拆分s*的加权杂质p(t) i(t, s*)小于某个用户定义的阈值beta

我经常被问到有关修剪后的问题。 通常使用单个树对于可解释性很重要,而后修剪可以帮助可解释性和泛化性能。

我认为这对于某些集成算法(例如(梯度)增强)也可能是有益的,尽管它通常不会提高装袋式合奏(例如随机森林)的预测准确性。

修剪还可能有助于节省一些内存并减少预测时间。

@amueller /其他: @jmschrei和我几个星期前见面讨论了修剪后的问题,我们不确定它是否适合当前的scikit-learn API。 通常,修剪后需要一个验证集,但这似乎与库的当前组织方式不太吻合(即,验证集的创建/来源等问题,以及该验证是否适合或单独使用)方法浮现在脑海)。 从API的角度来看,您如何看待这一点?
现在,我正在研究splitter.pyx代码,并在考虑MAE的同时添加基于GSoC加权杂质的提前停止标准。

似乎在https://github.com/scikit-learn/scikit-learn/pull/941中已经有一些关于API问题的讨论,但是tree模块已经改变了很多,也许我们应该再次进行讨论。 例如,我们有max_leaf_nodesmax_depth来稍微控制树的生长。

我倾向于将修剪设置为单独的方法。 实际上,可以采用一个单独的函数,该函数接受一棵树并返回修剪后的版本。 这是https://github.com/ajtulloch/sklearn-compiledtrees中使用的方法,用于为树生成优化的代码。

@ nelson-liu关于正则化选项,它们有时会导致所有子节点都属于同一类的子树。 尽管在正则化意义上不是修剪,但最好有一个函数来消除这些仅在预测期间增加计算成本的额外节点。

什么时候会得到所有节点都预测相同类的子树? 如果您的标准没有收益,您将不会分裂。

本质上,我想要的是一种“热启动”之类的方法来构建树木,就像我们为构建随机森林提供了一个良好的开始。 您应该有一种方法可以将单个节点添加到树中,但是在添加节点之前和之后仍然可以获得有效的估计量。 这将允许用户在构建评估集时评估其性能,就像您可以将树添加到随机林中一样,每次都在验证集上评估其性能。 从功能上来说,这应该不是很难添加的,最大的问题只是用于此的API。 @ogrisel @glouppe您有什么想法吗?

@jmschrei
我的意思是,如果树停在那里,将90:10拆分为80:0和10:10不会改变性能。

@pixelou要考虑的另一重要事项是我们是否希望将其与GridSearchCV ...单独的方法会破坏我的想法。

@ nelson-liu对不起,我不清楚:我的意思是,大多数艰苦的工作都是自行编写修剪程序。 集成不应该太难(但我显然不是这样做的人:-))

在我的脑海中,我看到了几个集成选项:

  • 然后, .fit赋予树构造函数的选项考虑在内
  • 选项直接赋予.fit
  • 必须显式调用单独的.prune.post_prune方法
  • 单独的prune_treepost_prune_tree函数获取树并返回另一棵修剪的树

您可以自行决定,但是我认为可以编写一种单独的私有(类)方法进行修剪,并将其作为上述解决方案之一提供给API。

请注意,我只是给出以上几点而没有进一步的考虑;-)。 2和4显然不是sklearn的处理方式,您刚才提到3可能是一个问题。

这些选项的第一个选项似乎与sklearn最一致。

@ameuller @glouppe @GaelVaroquaux对用于后期修剪的api有任何意见吗? 我看到了这三个选项,第一个对我来说似乎是最好的。 我只是想先澄清一下,然后再开始考虑进行以下工作:

  • 然后,.fit将赋予树构造函数的选项考虑在内
  • 拟合后必须调用单独的.prune.post_prune方法
  • 单独的prune_treepost_prune_tree函数获取树并返回另一棵修剪的树

是的,第一种选择肯定是最适合我们的API的选择。

如果合适的话,不是在修剪前吗? 我们不是应该检查树的复杂性并使用后期修剪来减少它吗?

从第三个选项开始,然后决定其他选项是否合适...

为此+1

(我的意思是,示例代码可能有助于确定)

如果执行得当,构建完整的树然后向后移并删除节点,则不是预修剪。 我同意@glouppe的观点,第一个是最好的选择,但是我也同意@jnothman的观点,因为该代码将依赖于prune_tree方法(无论如何),因此在开发阶段创建一个独立的东西可能会更好。

如果执行得当,构建完整的树然后向后移并删除节点,则不是预修剪。

我假设用户将要基于构建的树来选择是否发布修剪...

例如,这就是rpart工作方式-通过单独的prune方法,该方法向后进行并修剪树...

大概您希望验证集性能来指导是否/如何修剪树。

我担心的是-如果用户希望窥视fit和修剪后操作之间的树,则他们将不得不重新适应而无需启用修剪后功能...

但是正如您所说,如果后修剪的需要是基于验证集的性能而不是用户的决定,那么这不是必需的...

@ nelson-liu如果您不是我可以做这个吗?

当然,这可能是熟悉树代码的好方法。 当然,这绝对不是一件容易的事,所以请随时询问您是否需要帮助...

谢谢@ nelson-liu。

那么这是已经实施还是仍然存在?

@datavinci它仍然存在。

如果没有人正在使用此功能,我想自己或使用@dalmia进行此操作。 好?

看来这已经停滞了,所以继续吧。

在2017年7月19日星期三下午2:32,avidale [email protected]写道:

如果没有人正在使用此功能,我想自己或
@dalmia https://github.com/dalmia 。 好?


您收到此邮件是因为有人提到您。
直接回复此电子邮件,在GitHub上查看
https://github.com/scikit-learn/scikit-learn/issues/6557#issuecomment-316524038
或使线程静音
https://github.com/notifications/unsubscribe-auth/ADvEEOVYL_gQbMzWFixoHO1D0YfvuItCks5sPnXlgaJpZM4HybHH

我认为@dalmia这些天没有

2017年7月20日,8:01,Jacob Schreiber [email protected]写道:

看来这已经停滞了,所以继续吧。

在2017年7月19日星期三下午2:32,avidale [email protected]写道:

如果没有人正在使用此功能,我想自己做
要么
@dalmia https://github.com/dalmia 。 好?


您收到此邮件是因为有人提到您。
直接回复此电子邮件,在GitHub上查看
6557#issuecomment-316524038>,
或使线程静音
gQbMzWFixoHO1D0YfvuItCks5sPnXlgaJpZM4HybHH>

>


您收到此邮件是因为有人提到您。
直接回复此电子邮件,在GitHub上查看
https://github.com/scikit-learn/scikit-learn/issues/6557#issuecomment-316531460
或使线程静音
https://github.com/notifications/unsubscribe-auth/AAEz64HQd8rQr3u2hD0QFR-RxktyYZoaks5sPnzTgaJpZM4HybHH

我还看到大型子树预测了相同的类。 在这种情况下,即使是天真的修剪也可以提高解释性(并且对预测没有影响)。

@cjmay它将更改预测的概率。 但是,是的,添加任何形式的修剪都很好;)

希望看到修剪后与修剪前的基准。 我认为“ min_impurity_decrease”是一个相对合理的停止标准。 或者,您可以对n_leafs进行网格搜索...人们通常会对修剪参数进行网格搜索吗? (我会这样想)。 看到产生不同结果的频率会很有趣。

@amueller哦,我明白了。

对此期待!

对于某些合奏方法,可以自然地进行。 如果有套袋,则可以将OOB样本用于验证和修剪。 这就像在GradientBoostingClassifier中如何计算oob_improvement_

现在有人在为此工作吗?

据我所知

有没有人做的?

有没有人做过可以共享您的代码的......

基于sklearn.decisiontreeclassifier的成本复杂度修剪

有人可以基于sklearn.decisiontreeclassifier()进行成本复杂性修剪吗?如果没有,我会再问一次。

发现了这一点:
https://github.com/shenwanxiang/sklearn-post-prune-tree

不知道这是否完全是成本复杂性修剪?

@zanderbraam不是CCP

大家好 ,
我已经实现了:
CCP(成本复杂度修剪)算法
Python中的sklearn-CART-Classification-model,

ECP(错误复杂度修剪)算法
Python中的sklearn-CART-Regression-model,

这里是链接:
https://github.com/appleyuchi/Decision_Tree_Prune
你可能会喜欢。

@appleyuchi谢谢!
我发现很难遵循代码的结构,特别是考虑到文件名和注释为中文。 似乎也有很多重复的代码。

我不再使用DT,但是有人看过https://github.com/beedotkiran/randomforestpruning-ismm-2017吗? 似乎与此问题有关。

一棵树只是一个很小的森林。 这种实现方式不能缩小到树木吗?

@appleyuchi我不确定我是否遵循您的意思,但是我们不会采用基于JSON的实现。 scikit-learn中的任何实现都必须直接与scikit-learn数据结构一起使用。

@appleyuchi感谢您的努力。 关于实现此功能可能有多么棘手,我们确实认识到触摸树代码库不一定是一项琐碎的任务。 已经做出了努力来改变这种状况,并实现了更具可读性的实现。 此外,由于该确切原因,此问题未标记为“简单”。

希望您找到其他您可能感兴趣的问题,并继续努力:)

我正在使用成本复杂度修剪(CPP)算法来解决此问题。 我看到一些可用于检查树修剪的测试:

  1. 增加Alpha(在CPP中)应导致更少或相等数量的节点。
  2. 确保修剪后的树实际上是原始树的子树。

还有哪些其他测试适用于树木修剪?

@appleyuchi感谢您的分享! 我担心的是,即使是中国人,我仍然很难遵循代码。 我认为最好将代码模块化,以便其他人可以将您的实现应用于任何数据集。

@ zhenyu-zhou
因为几乎所有人都从未认真阅读过《分类和回归树》这本书。

这本书的第一作者已经去世了,所以您不能联系他。

这本书的缺陷在
http://www.dcc.fc.up.pt/~ltorgo/PhD/th4.pdf
要么
http://www.doc88.com/p-6445227043649.html

指出CCP / ECP算法交叉验证对于不平衡的小型数据集将失败,
在实施之前,您应该了解上述学术材料。

我分析并总结了以下缺陷:

https://blog.csdn.net/appleyuchi/article/details/84957220

我为CCP / ECP提供的Github链接只是“应用程序样式”,而不是sklearn的“底部变量样式”(后者将更加高效和快捷)
所以他们拒绝了。

即使是中国人,我仍然很难遵守该守则。 我认为最好将代码模块化,以便其他人可以将您的实现应用于任何数据集。

它可以应用于我测试过的许多数据集,我想您甚至都没有点击并阅读Github链接中的说明

@appleyuchi

但是它可以应用于您想要的任何数据集,我相信您甚至都没有点击并阅读链接中的说明

你是绝对错误的。 简而言之,我只想问您一个问题:您是否像sklearn一样提供了干净的API?

如果您将代码作为sklearn当作库使用,则不应指望每个人在使用代码之前先阅读每一个细节,而应责怪其他人。 这就是他们拒绝代码的原因之一。 当您使用其他库时,请考虑使用它,以sklearn为例,如果它只有一堆用于实验的自包含代码,这需要某种输入格式,而没有通用框架。 您需要仔细检查库代码,以确定如何拆分主要逻辑并将其应用于数据集。 你会用吗? 我承认该实验很有趣,但它不是一个库。 我只是想在代码中添加一些东西来改进代码,但这太难了。

@ zhenyu-zhou

您不应该指望所有人在使用代码之前先阅读每一个细节,并为此而责怪其他人,

您误解了,我说的是实质性的,不是代码。
请注意,它是指一本书,而不是我编写的代码。

我的意思是《分类和回归树》是一本著名的书,不是我写的代码,
因此,这不是罪魁祸首。“您”是指新的贡献者,不是sklearn的现有成员。

我只是想在代码中添加一些东西来改进代码,但这太难了。

同样,在实施之前,您应该仔细阅读这本书。

@ zhenyu-zhou

,如果它只有一堆用于实验的自包含代码,则需要某种输入格式,而没有通用框架。 您需要仔细检查库代码,以确定如何拆分主要逻辑并将其应用于数据集。

几个月前,当您还没来过API风格时,
再次,
我实现的是“应用程序样式”,而不是“ sklearn底部数据结构”

祝好运。
问题

ps:由于我很忙,因此已取消来自此问题的通知。@me将不再生效。如有任何疑问,请通过电子邮件与我联系。

@ameuller @glouppe @GaelVaroquaux对用于后期修剪的api有任何意见吗? 我看到了这三个选项,第一个对我来说似乎是最好的。 我只是想先澄清一下,然后再开始考虑进行以下工作:

  • 然后,.fit将赋予树构造函数的选项考虑在内
  • 拟合后必须调用单独的.prune.post_prune方法
  • 单独的prune_treepost_prune_tree函数获取树并返回另一棵修剪的树
    你有任何代码吗?
    谢谢
此页面是否有帮助?
0 / 5 - 0 等级