Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 修剪决策树_Python_Scikit Learn - Fatal编程技术网

Python 修剪决策树

Python 修剪决策树,python,scikit-learn,Python,Scikit Learn,下面是决策树的一个片段,因为它非常庞大 当节点中的最低值小于5时,如何使树停止生长。下面是生成决策树的代码。在上,我们可以看到唯一的方法是通过减少杂质但我不确定它具体是如何工作的 import numpy as np import pandas as pd from sklearn.datasets import make_classification from sklearn.ensemble import RandomForestClassifier from sklearn.tree i

下面是决策树的一个片段,因为它非常庞大

当节点中的最低值小于5时,如何使树停止生长。下面是生成决策树的代码。在上,我们可以看到唯一的方法是通过减少杂质但我不确定它具体是如何工作的

import numpy as np
import pandas as pd
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier


X, y = make_classification(n_samples=1000,
                           n_features=6,
                           n_informative=3,
                           n_classes=2,
                           random_state=0,
                           shuffle=False)

# Creating a dataFrame
df = pd.DataFrame({'Feature 1':X[:,0],
                                  'Feature 2':X[:,1],
                                  'Feature 3':X[:,2],
                                  'Feature 4':X[:,3],
                                  'Feature 5':X[:,4],
                                  'Feature 6':X[:,5],
                                  'Class':y})


y_train = df['Class']
X_train = df.drop('Class',axis = 1)

dt = DecisionTreeClassifier( random_state=42)                
dt.fit(X_train, y_train)

from IPython.display import display, Image
import pydotplus
from sklearn import tree
from sklearn.tree import _tree
from sklearn import tree
import collections
import drawtree
import os  

os.environ["PATH"] += os.pathsep + 'C:\\Anaconda3\\Library\\bin\\graphviz'

dot_data = tree.export_graphviz(dt, out_file = 'thisIsTheImagetree.dot',
                                 feature_names=X_train.columns, filled   = True
                                    , rounded  = True
                                    , special_characters = True)

graph = pydotplus.graph_from_dot_file('thisIsTheImagetree.dot')  

thisIsTheImage = Image(graph.create_png())
display(thisIsTheImage)
#print(dt.tree_.feature)

from subprocess import check_call
check_call(['dot','-Tpng','thisIsTheImagetree.dot','-o','thisIsTheImagetree.png'])
更新 我认为减少杂质在某种程度上有助于达到目标。因为调整
min\u inclution\u reduce
实际上会修剪树。有谁能解释一下为什么杂质减少了

我试图理解scikit learn中的方程式,但我不确定右杂质和左杂质的值是多少

N = 256
N_t = 256
impurity = ??
N_t_R = 242
N_t_L = 14
right_impurity = ??
left_impurity = ??

New_Value = N_t / N * (impurity - ((N_t_R / N_t) * right_impurity)
                    - ((N_t_L / N_t) * left_impurity))
New_Value
更新2 我们不是在某个值上修剪,而是在某个条件下修剪。 比如 我们确实按6/4和5/5进行拆分,但不按6000/4或5000/5进行拆分。假设一个值与其在节点中的相邻值相比低于某个百分比,而不是某个特定值

      11/9
   /       \
  6/4       5/5
 /   \     /   \
6/0  0/4  2/2  3/3

编辑:正如@SBylemans和@Viktor在评论中指出的那样,这是不正确的。我不会删除答案,因为其他人可能也认为这是解决方案

min\u samples\u leaf
设置为5

min\u samples\u leaf

叶节点所需的最小样本数:

更新:我认为使用
minu\u杂质减少
是无法做到的。考虑以下场景:

      11/9
   /         \
  6/4       5/5
 /   \     /   \
6/0  0/4  2/2  3/3

根据您的规则,您不希望分割节点
6/4
,因为4小于5,但您希望分割
5/5
节点。但是,拆分
6/4
节点的信息增益为0.48,拆分
5/5
的信息增益为0。

直接限制叶的最低值(特定类别的出现次数)不能使用最小杂质减少或任何其他内置停止标准

我认为在不更改scikit learn的源代码的情况下实现这一点的唯一方法是对树进行后期修剪。要实现这一点,您只需遍历树并移除最小类计数小于5(或您可以想到的任何其他条件)的节点的所有子节点。我将继续你的例子:

from sklearn.tree._tree import TREE_LEAF

def prune_index(inner_tree, index, threshold):
    if inner_tree.value[index].min() < threshold:
        # turn node into a leaf by "unlinking" its children
        inner_tree.children_left[index] = TREE_LEAF
        inner_tree.children_right[index] = TREE_LEAF
    # if there are shildren, visit them as well
    if inner_tree.children_left[index] != TREE_LEAF:
        prune_index(inner_tree, inner_tree.children_left[index], threshold)
        prune_index(inner_tree, inner_tree.children_right[index], threshold)

print(sum(dt.tree_.children_left < 0))
# start pruning from the root
prune_index(dt.tree_, 0, 5)
sum(dt.tree_.children_left < 0)
从sklearn.tree.\u tree导入tree\u LEAF
def prune_索引(内部_树、索引、阈值):
如果内部树.value[index].min()小于阈值:
#通过“取消链接”其子节点,将节点变为叶
内部树。子树左[索引]=树叶
内部树。子树右[索引]=树叶
#如果有孩子,也去看看他们
如果是内部树。子树左[索引]!=树叶:
修剪索引(内树,内树。左子树[索引],阈值)
修剪索引(内树,内树。子树右[索引],阈值)
打印(总和(dt.tree\uu.children\u left<0))
#从根开始修剪
修剪索引(dt.tree,0,5)
总和(dt.tree_u.children_uleft<0)
此代码将首先打印
74
,然后打印
91
。这意味着代码已经创建了17个新的叶节点(实际上删除了到它们祖先的链接)。这棵树以前看起来像

现在看来


所以你可以看到它确实减少了很多

有趣的是,
min\u杂质减少
看起来不允许您在提供的代码片段中显示的任何节点增长(分裂后的杂质总和等于分裂前的杂质,因此没有杂质减少)。然而,虽然它不会给出您想要的结果(如果最小值小于5,则终止节点),但它可能会给出类似的结果

如果我的测试是正确的,官方文件会让它看起来比实际情况更复杂。只需从潜在的父节点中取较低的值,然后减去建议的新节点的较低值之和-这是杂质减少。然后除以整树中的样本总数——这将为您提供在分割节点时实现的分数杂质减少


如果您有1000个样本,并且一个节点的值较低为5(即5“杂质”),则5/1000表示如果该节点完全拆分,您可以实现的最大杂质减少量。因此,将
min\u include\u reduce
设置为0.005将近似于使用Scikit学习库中的停止叶片,您可以使用名为
ccp\u alpha
的参数作为
DiscisionTreeClassifier
的参数。使用此选项,您可以对DecessionTrees进行竞争后修剪。查看此项

该值代表什么?最小杂质减少适用于某个节点中可能发生的拆分,并没有考虑当前节点的值,但是如果一个节点分裂,则会增加孩子的纯度。@ SBILMENS值项是在学期取舍的实际决策树中,左和右杂质分别是左子和右子中的样本的杂质。(根据标准参数计算)我认为您无法使用SciKit的决策树,除非您可能知道最大深度或样本数(当值小于5时)。也许在施工后可以穿过这棵树?该树位于分类器对象的
树中。您需要指定使用的标准:基尼或熵。你不能实现你自己的功能,他没有说5代表样本数node@Selcuk这是不正确的!min_damples_leaf位于叶节点中。问题是,查看节点中的最小值,如果它低于某个值,请停止拆分。@Victor,我明白了。我误解了这个问题,但我认为你要找的东西不能用
minu\u inclution\u decrease
来完成。请检查答案的更新部分,以获取详细信息