【问题标题】:How to add custom tree to custom Keras layer?如何将自定义树添加到自定义 Keras 层?
【发布时间】:2022-06-13 01:15:39
【问题描述】:

我正在尝试汇总以下教程:

  1. Creating decision tree by hand
  2. Custom layers via subclassing
  3. Composing Decision Forest and Neural Network models

目标是 1. 创建自定义树,2. 将其嵌入自定义层,3. 将其与其他层结合到模型中。

问题在于,在第 1 步中,通过使用 RandomForestBuilder,模型被序列化和反序列化,导致对象类型为 keras.saving.saved_model.load.C​​oreModel

但是,第 3 步中的教程通过 tfdf.keras.RandomForestModel 嵌入树层

理想情况下,自定义层将通过在其构造函数中调用 RandomForestBuilder 来创建自定义树,但是,考虑到模型的导出和加载,这并不简单。

下面给出了输入层结构的错误,如果省略了前者,则会给出从 SavedModel 加载的没有匹配的具体函数调用的错误:

第 1 步:

builder = tfdf.builder.RandomForestBuilder(
    path="/tmp/manual_model",
    objective = tfdf.py_tree.objective.RegressionObjective(label='tree_result')
)

Tree = tfdf.py_tree.tree.Tree
SimpleColumnSpec = tfdf.py_tree.dataspec.SimpleColumnSpec
ColumnType = tfdf.py_tree.dataspec.ColumnType
RegressionValue = tfdf.py_tree.value.RegressionValue

NonLeafNode = tfdf.py_tree.node.NonLeafNode
LeafNode = tfdf.py_tree.node.LeafNode
NumericalHigherThanCondition = tfdf.py_tree.condition.NumericalHigherThanCondition
CategoricalIsInCondition = tfdf.py_tree.condition.CategoricalIsInCondition

tree = Tree(
    NonLeafNode(
        condition=CategoricalIsInCondition(
            feature=SimpleColumnSpec(name='feature_name', type=ColumnType.CATEGORICAL),
            mask=['class_1'],
            missing_evaluation=False
        ),
        pos_child = LeafNode(value=RegressionValue(value=0.5)),
        neg_child = LeafNode(value=RegressionValue(value=0.6))
    )
)

builder.add_tree(tree)
builder.close()
custom_tree = tf.keras.models.load_model("/tmp/manual_model")

第 2 步:

class CustomTree(tf.keras.layers.Layer):
  def __init__(self, custom_tree):
    super(CustomTree, self).__init__()
    self.custom_tree = custom_tree

  def call(self, inputs):
    return self.custom_tree(inputs)


input_layer = tf.keras.layers.Input(shape=(None,), name='feature_name', dtype=tf.string)
output_layer = CustomTree(custom_tree)(input_layer)

model = tf.keras.models.Model(input_layer, output_layer, name='SomeModel')

model.predict(tf.data.Dataset.from_tensor_slices(
    {'feature_name': ['class_1','class_2']}
).batch(1))

【问题讨论】:

    标签: python tensorflow keras decision-tree


    【解决方案1】:

    找到以下解决方案:

    1. 以 yggdrasil 格式导出自定义树:

       builder = tfdf.builder.RandomForestBuilder(
           model_format = tfdf.builder.ModelFormat.YGGDRASIL_DECISION_FOREST,
           path=self._temp_directory,
           objective = objective)
      
    2. 通过关闭构建器保存模型后,将树加载为 CoreModel:

       builder.close()
      
       inspector_lib = tfdf.component.inspector.inspector
       inspector = inspector_lib.make_inspector(self._temp_directory, file_prefix=None)
      
       custom_tree = tfdf.keras.CoreModel(
           task=objective.task,
           learner='MANUAL',
           ranking_group=None,
           temp_directory=self._temp_directory)
      
       custom_tree._set_from_yggdrasil_model(
           inspector,
           self._temp_directory,
           file_prefix=None, 
           input_model_signature_fn=builder._input_model_signature_fn)
      
    3. 使用自定义拟合函数创建 tfdf.keras.CartModel 的模型子类,将自定义树结构分配给模型:

      class CustomDT(tfdf.keras.CartModel):
          def __init__(self, name=None, **kwargs):
              super(CustomDT, self).__init__(name=name, **kwargs)
      
          def fit(self):
              custom_tree = self.create_custom_tree()
              self._model = custom_tree._model
              self._is_trained.assign(True)
              self._semantics = custom_tree._semantics
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-08
      • 2018-04-04
      • 1970-01-01
      • 1970-01-01
      • 2021-04-06
      • 1970-01-01
      • 1970-01-01
      • 2021-10-27
      相关资源
      最近更新 更多