【问题标题】:How to get node information on Spark Decision Tree model如何获取 Spark 决策树模型的节点信息
【发布时间】:2018-09-23 02:55:56
【问题描述】:

我想了解 Spark MLlib 的决策树生成模型的每个节点的更详细信息。我可以使用 API 获得的最接近的是 print(model.toDebugString()),它返回类似这样的内容(取自 PySpark 文档)

  DecisionTreeModel classifier of depth 1 with 3 nodes
  If (feature 0 <= 0.0)
   Predict: 0.0
  Else (feature 0 > 0.0)
   Predict: 1.0

如何修改 MLlib 源代码以获取例如每个节点的杂质和深度? (如果有必要,如何在 PySpark 中调用新的 Scala 函数?)

【问题讨论】:

    标签: python scala pyspark apache-spark-mllib apache-spark-ml


    【解决方案1】:

    我将尝试通过描述我如何使用 PySpark 2.4.3 来补充 @mostOfMajority 的答案。

    根节点

    给定一个经过训练的决策树模型,您可以通过以下方式获取其根节点:

    def _get_root_node(tree: DecisionTreeClassificationModel):
        return tree._call_java('rootNode')
    

    杂质

    我们可以通过从根节点沿着树向下走来获取杂质。它的pre-order transversal 可以这样做:

    def get_impurities(tree: DecisionTreeClassificationModel) -> List[float]:
        def recur(node):
            if node.numDescendants() == 0:
                return []
            ni = node.impurity()
            return (
                recur(node.leftChild()) + [ni] + recur(node.rightChild())
            )
        return recur(_get_root_node(tree))
    

    示例

    In [1]: print(tree.toDebugString)
    DecisionTreeClassificationModel (uid=DecisionTreeClassifier_f90ba6dbb0fe) of depth 3 with 7 nodes
      If (feature 0 <= 6.5)
       If (feature 0 <= 3.5)
        Predict: 1.0
       Else (feature 0 > 3.5)
        If (feature 0 <= 5.0)
         Predict: 0.0
        Else (feature 0 > 5.0)
         Predict: 1.0
      Else (feature 0 > 6.5)
       Predict: 0.0
    
    
    In [2]: cat.get_impurities(tree)
    Out[2]: [0.4444444444444444, 0.5, 0.5]
    

    【讨论】:

      【解决方案2】:

      不幸的是,我找不到任何方法直接在 PySpark 或 Spark (Scala API) 中访问节点。但是有一种方法可以从一个根节点开始,遍历到不同的节点。

      (我刚刚在这里提到了杂质,但对于深度,可以很容易地用impurity 替换subtreeDepth。)

      假设决策树模型实例为dt

      PySpark

      root = dt.call("topNode")
      root.impurity() # gives the impurity of the root node
      

      现在如果我们看看适用于root的方法:

      dir(root)
      [u'apply', u'deepCopy', u'emptyNode', u'equals', 'getClass', u'getNode', u'hashCode', u'id', 'impurity', u'impurity_$eq', u'indexToLevel', u'initializeLogIfNecessary', u'isLeaf', u'isLeaf_$eq', u'isLeftChild', u'isTraceEnabled', u'leftChildIndex', u'leftNode', u'leftNode_$eq', u'log', u'logDebug', u'logError', u'logInfo', u'logName', u'logTrace', u'logWarning', u'maxNodesInLevel', u'notify', u'notifyAll', u'numDescendants', u'org$apache$spark$internal$Logging$$log_', u'org$apache$spark$internal$Logging$$log__$eq', u'parentIndex', u'predict', u'predict_$eq', u'rightChildIndex', u'rightNode', u'rightNode_$eq', u'split', u'split_$eq', u'startIndexInLevel', u'stats', u'stats_$eq', u'subtreeDepth', u'subtreeIterator', u'subtreeToString', u'subtreeToString$default$1', u'toString', u'wait']
      

      我们可以这样做:

      root.leftNode().get().impurity()
      

      这可能会在树中更深,例如:

      root.leftNode().get().rightNode().get().impurity()
      

      由于在应用leftNode()rightNode() 之后,我们得到一个option,应用get 或getOrElseis necessary to get to the desiredNode` 类型。

      如果你想知道我是怎么弄到这些奇怪的方法的,我得承认,我作弊了!!,即我首先研究了 Scala API:

      火花

      以下行与上面的行完全相同,并且假设dt 相同,则给出相同的结果:

      val root = dt.topNode
      root.impurity
      

      我们可以这样做:

      root.leftNode.get.impurity
      

      这可能会在树中更深,例如:

      root.leftNode.get.rightNode.get.impurity
      

      【讨论】:

      • 决策树模型实例在 pyspark 2.3 中没有 call() 方法。你用的是什么版本的火花?
      • 这是 pyspark 2.2.1。还没试过 2.3。
      • @sgu 你找到 pyspark2.3 的解决方案了吗?
      猜你喜欢
      • 2021-09-03
      • 2016-10-07
      • 2017-11-06
      • 1970-01-01
      • 2014-05-21
      • 2016-07-08
      • 2011-06-01
      • 1970-01-01
      • 2015-01-31
      相关资源
      最近更新 更多