从SKlearn决策树中检索决策边界线(x,y坐标格式)

时间:2017-05-12 04:38:17

标签: python python-3.x matplotlib scikit-learn

我正在尝试在外部可视化平台上创建表面图。我正在处理sklearn decision tree documentation page上展示的虹膜数据集。我也使用相同的方法来创建我的决策曲面图。我的最终目标不是matplot lib visual,所以从这里我将数据输入到我的可视化软件中。为此,我在flatten()tolist()xx上调用了yyZ,并编写了包含这些列表的JSON文件。

问题是,当我尝试绘制它时,我的可视化程序崩溃了。事实证明数据太大了。当展平时,列表的长度> 86,000。这是因为步长/绘图步骤非常小.02。因此,根据模型的预测,它实际上是在数据的最小和最大范围以及绘图/填充过程中采取小步骤。它有点像像素网格;我将尺寸缩小到只有2000的数组,并注意到坐标只是来回的线条(最终包含整个坐标平面)。

问题:我可以检索决策边界线本身的x,y坐标(而不是遍历整个平面)吗?理想情况下,列表仅包含每行的转折点。或者,是否可能有其他完全不同的方式重新创建此图,以便它在计算上更有效率?

通过将contourf()调用替换为countour()

,可以在某种程度上实现这一点

enter image description here

我只是不确定如何检索管理这些行的数据(通过xxyyZ或其他方式?)。

注意:我并不挑剔包含行格式的列表/或数据结构的确切格式,只要其计算效率很高。例如,对于上面的第一个图,一些红色区域实际上是预测空间中的岛屿,因此这可能意味着我们必须像它自己的线一样处理它。我猜测只要该类与x,y坐标耦合,就不应该使用多少数组(包含坐标)来捕获决策边界。

2 个答案:

答案 0 :(得分:1)

@ kazemakase的方法是“正确”的方法。为了完整起见,这里有一个简单的方法来获得Z中作为决策边界的每个“像素”:

steps = np.diff(Z,axis=0)[:,1:] + np.diff(Z,axis=1)[1:,:]
is_boundary = steps != 0
x,y = np.where(is_boundary)
# rescale to convert pixels into into original units
x = x.astype(np.float) * plot_step
y = y.astype(np.float) * plot_step

is_boundary的情节(扩张,以便可以看到所有非零条目):

enter image description here

答案 1 :(得分:1)

对于那些感兴趣的人,我最近还必须针对更高维度的数据实现此功能,代码如下:

number_of_leaves = (tree.tree_.children_left == -1).sum()
features = x.shape[1]
boundaries = np.zeros([number_of_leaves, features, 2])
boundaries[:,:,0] = -np.inf
boundaries[:,:,1] = np.inf

locs = np.where(tree.tree_.children_left == -1)[0]

for k in range(locs.shape[0]):
    idx = locs[k]
    idx_new = idx

    while idx_new != 0:
        i_check = np.where(tree.tree_.children_left == idx_new)[0]
        j_check = np.where(tree.tree_.children_right == idx_new)[0]

        if i_check.shape[0] == 1:
            idx_new = i_check[0]
            feat_ = tree.tree_.feature[idx_new]
            val_ = tree.tree_.value[idx_new]
            boundaries[k,feat_, 0] = val_
        elif j_check.shape[0] == 1:
            idx_new = j_check[0]
            feat_ = tree.tree_.feature[idx_new]
            val_ = tree.tree_.value[idx_new]
            boundaries[k,feat_, 1] = val_ 
        else: 
            print('Fail Case') # for debugging only - never occurs

基本上,我建立了一个n * d * 2张量,其中n是树的叶子数,d是空间的维数,第三个维包含最小值和最大值。叶子以-1的形式存储在tree.tree_.children_left / tree.tree_.children_right中,然后向后循环查找导致分裂的分支,并将分裂标准添加到决策范围。