【问题标题】:Use dtreeviz to visualize decision tree使用 dtreeviz 可视化决策树
【发布时间】:2019-11-03 03:03:22
【问题描述】:

我喜欢 Dtreeviz library - GitHub 提供的决策树可视化,并且可以使用

# Install libraries
!pip install dtreeviz
!apt-get install graphviz

# Sample code
from sklearn.datasets import *
from sklearn import tree
from dtreeviz.trees import *
from IPython.core.display import display, HTML

classifier = tree.DecisionTreeClassifier(max_depth=4)
cancer = load_breast_cancer()

classifier.fit(cancer.data, cancer.target)
viz = dtreeviz(classifier,
               cancer.data,
               cancer.target,
               target_name='cancer',
               feature_names=cancer.feature_names, 
               class_names=["malignant", "benign"],
               fancy=False) 

display(HTML(viz.svg()))

但是,当我将上述内容应用于我自己制作的 dtree 时,代码会爆炸,因为我的数据位于 pandas DF(或 np 数组)中,而不是 scikit-learn 束对象。

现在,在Sci-kit learn - How to create a Bunch object,他们非常严厉地告诉我不要尝试创建一堆对象;但我也没有技能将我的 DF 或 NP 数组转换为上面的 viz 函数可以接受的东西。

我们可以假设我的 DF 有九个特征和一个目标,称为“Feature01”、“Feature02”等和“Target01”。

我通常会这样拆分

FeatDF  = FullDF.drop( columns = ["Target01"])
LabelDF = FullDF["Target01"]

然后设置我的快乐方式来分配一个分类器,或者如果对于 ML,创建一个测试/训练拆分。

在调用dtreeviz 时,这些都没有帮助——它期待诸如“feature_names”之类的东西(我认为它是包含在“bunch”对象中的东西)。而且由于我无法将我的 DF 转换为一堆,所以我非常卡住。哦,请带上你的智慧。

更新:我想任何简单的 DF 都会说明我的难题。我们可以一起摇摆

import pandas as pd

Things = {'Feature01': [3,4,5,0], 
          'Feature02': [4,5,6,0], 
          'Feature03': [1,2,3,8], 
          'Target01': ['Red','Blue','Teal','Red']}
DF = pd.DataFrame(Things,
                  columns= ['Feature01', 'Feature02', 
                            'Feature02', 'Target01']) 

以 DF 为例。现在,我会去吗

DataNP = DF.to_numpy()
classifier.fit(DF.data, DF.target)
feature_names = ['Feature01', 'Feature02', 'Feature03'] 
#..and what if I have 50 features...

viz = dtreeviz(classifier,
               DF.data,
               DF.target,
               target_name='Target01',
               feature_names=feature_names, 
               class_names=["Red", "Blue", "Teal"],
               fancy=False) 

或者这是愚蠢的?感谢您到目前为止的指导!

【问题讨论】:

  • 您能否提供minimal reproducible example 以便我们可以复制该问题?
  • 您能否提供您尝试调用 dtreeviz 的方式?因为我知道如何构造数据框,但我想知道如何使用数据框调用函数以及得到什么错误。

标签: python scikit-learn visualization dtreeviz


【解决方案1】:
  • sklearn 的决策树需要数值目标值
  • 您可以使用 sklearn 的 LabelEncoder 将您的字符串转换为整数

    from sklearn import preprocessing
    
    label_encoder = preprocessing.LabelEncoder()
    label_encoder.fit(df.Target01)
    
    df['target'] = label_encoder.transform(df.Target01)
    
  • dtreeviz 期望 class_nameslistdict,所以让我们从 label_encoder 获取它

    class_names = list(label_encoder.classes_)        
    

完整代码

import pandas as pd
from sklearn import preprocessing, tree
from dtreeviz.trees import dtreeviz

Things = {'Feature01': [3,4,5,0], 
          'Feature02': [4,5,6,0], 
          'Feature03': [1,2,3,8], 
          'Target01': ['Red','Blue','Teal','Red']}
df = pd.DataFrame(Things,
                  columns= ['Feature01', 'Feature02', 
                            'Feature02', 'Target01']) 

label_encoder = preprocessing.LabelEncoder()
label_encoder.fit(df.Target01)
df['target'] = label_encoder.transform(df.Target01)

classifier = tree.DecisionTreeClassifier()
classifier.fit(df.iloc[:,:3], df.target)

dtreeviz(classifier,
         df.iloc[:,:3],
         df.target,
         target_name='toy',
         feature_names=df.columns[0:3],
         class_names=list(label_encoder.classes_)
         )


旧答案

让我们使用癌症数据集来创建 Pandas 数据框

df = pd.DataFrame(cancer.data, columns=cancer.feature_names)
df['target'] = cancer.target

这为我们提供了以下数据框。

mean radius mean texture    mean perimeter  mean area   mean smoothness mean compactness    mean concavity  mean concave points mean symmetry   mean fractal dimension  radius error    texture error   perimeter error area error  smoothness error    compactness error   concavity error concave points error    symmetry error  fractal dimension error worst radius    worst texture   worst perimeter worst area  worst smoothness    worst compactness   worst concavity worst concave points    worst symmetry  worst fractal dimension target
0   17.99   10.38   122.8   1001.0  0.1184  0.2776  0.3001  0.1471  0.2419  0.07871 1.095   0.9053  8.589   153.4   0.006399    0.04904 0.05373 0.01587 0.03003 0.006193    25.38   17.33   184.6   2019.0  0.1622  0.6656  0.7119  0.2654  0.4601  0.1189  0
1   20.57   17.77   132.9   1326.0  0.08474 0.07864 0.0869  0.07017 0.1812  0.05667 0.5435  0.7339  3.398   74.08   0.005225    0.01308 0.0186  0.0134  0.01389 0.003532    24.99   23.41   158.8   1956.0  0.1238  0.1866  0.2416  0.186   0.275   0.08902 0
2   19.69   21.25   130.0   1203.0  0.1096  0.1599  0.1974  0.1279  0.2069  0.05999 0.7456  0.7869  4.585   94.03   0.00615 0.04006 0.03832 0.02058 0.0225  0.004571    23.57   25.53   152.5   1709.0  0.1444  0.4245  0.4504  0.243   0.3613  0.08758 0
[...]
568 7.76    24.54   47.92   181.0   0.05263 0.04362 0.0 0.0 0.1587  0.05884 0.3857  1.428   2.548   19.15   0.007189    0.00466 0.0 0.0 0.02676 0.002783    9.456   30.37   59.16   268.6   0.08996 0.06444 0.0 0.0 0.2871  0.07039 1

对于您的分类器,它可以按以下方式使用。

classifier.fit(df.iloc[:,:-1], df.target)

即只需将除最后一列以外的所有列作为训练/输入,将target 列作为输出/目标。

可视化也是如此:

viz = dtreeviz(classifier,
               df.iloc[:,:-1],
               df.target,
               target_name='cancer',
               feature_names=df.columns[0:-1],
               class_names=["malignant", "benign"]) 

【讨论】:

  • 感谢您再次加入。在癌症集中,目标是整数,对吧?但是,当我使用玩具 df 和 class_names = ["Red", "Blue", "Teal"] 时,我得到 TypeError: can't multiply sequence by non-int of type 'float' ,而当我说 class_names = list(DF['Target01'].unique()) 时,它会引发不祥的 KeyError: 3 。这有什么意义吗?
  • 对不起,我应该补充一点,在上面的第二部分中,我还把红色改为 1,蓝色改为 2,蓝绿色改为 3...
  • @RandomForestRanger:检查更新的答案,希望对你有用!
  • 天哪。优雅的。谢谢!
【解决方案2】:

我认为您对文档中提供的示例感到困惑。

Here 让我们看一下带有 iris 数据集的示例。

from sklearn.datasets import *

# Loading iris data
iris = load_iris()

# Type of iris
type(iris)
<class 'sklearn.utils.Bunch'>

数据集存储为您提到的 sklearn Bunch 对象。

但是dtreeviz 没有在它的任何参数中使用这个对象。所有参数都是numpy数组。

# Iris data - parameter
type(iris.data)
<class 'numpy.ndarray'>

# Shape
data.data.shape
(150, 4)

所以很明显dtreeviz 方法正在使用 numpy 数组并且没有使用 Bunch 对象。在您的情况下,功能名称与所选功能的列名无关。

更新

# Replace the following the the sample code to fit your dataframe
cancer.data <> DF.iloc[:, :-1]
cancer.target <> DF['Target01']

# Other parameters
feature_names = DF.columns[:-1]
class_names = DF['Target01'].unique()

【讨论】:

  • 谢谢。你对我的困惑是完全正确的!假设我采用上述 DF - 我是否转换为单个 numpy 数组并使用它?似乎不起作用。此外,在上面的示例中,cancer.data 和cancer.target 不是colls - 所以似乎还有其他事情发生(除了feature_names = colls(我得到))。在最基本的层面上:你将如何处理玩具 DF 以使其对 dtreeviz 友好?再次,非常感谢。
  • 我已经用集成示例数据框DF 的方式更新了答案。它还包括您是否拥有大量特征和标签。如果您觉得有帮助,请选中回答旁边的复选框。干杯!
  • 谢谢。我认为我们很接近...也许我只是犯了一个明显的错误。上面返回错误说Exception: class_names must be dict or sequence, not ndarray. 如果我用class_names = ["Red", "Blue", "Teal"] 替换class_names = DF['Target01'].unique(),我会得到TypeError: can't multiply sequence by non-int of type 'float'
  • 它需要一个list 的类名。您的错误消息指定您将列表与某个值相乘。确保您仅将单个元素列表分配给 class_names Try list(DF['Target01'].unique())
  • 如果您认为该解决方案有帮助,请给它一个赞成票并选中复选框以接受该解决方案。
猜你喜欢
  • 2022-01-11
  • 2021-09-18
  • 2012-07-03
  • 2020-08-17
  • 2017-08-10
  • 2019-03-10
  • 2022-08-24
  • 2014-08-28
相关资源
最近更新 更多