parameters: (dtec, sorted_feature_names,
                                  num_dense, num_sparse_float,
                                  num_sparse_int,
                                  feature_name_to_proto=None)
return_statement: return model_and_features
docstring: Convert GTFlow trees to universal format.
docstring_summary: Convert GTFlow trees to universal format.
docstring_tokens: Convert GTFlow trees to universal format .
function: def convert_to_universal_format(dtec, sorted_feature_names,
                                  num_dense, num_sparse_float,
                                  num_sparse_int,
                                  feature_name_to_proto=None):
    """Convert GTFlow trees to universal format."""
    del num_sparse_int  # unused.
    model_and_features = generic_tree_model_pb2.ModelAndFeatures()
    # TODO(jonasz): Feature descriptions should contain information about how each
    # feature is processed before it's fed to the model (e.g. bucketing
    # information). As of now, this serves as a list of features the model uses.
    for feature_name in sorted_feature_names:
      if not feature_name_to_proto:
        model_and_features.features[feature_name].SetInParent()
      else:
        model_and_features.features[feature_name].CopyFrom(
            feature_name_to_proto[feature_name])
    model = model_and_features.model
    model.ensemble.summation_combination_technique.SetInParent()
    for tree_idx in range(len(dtec.trees)):
      gtflow_tree = dtec.trees[tree_idx]
      tree_weight = dtec.tree_weights[tree_idx]
      member = model.ensemble.members.add()
      member.submodel_id.value = tree_idx
      tree = member.submodel.decision_tree
      for node_idx in range(len(gtflow_tree.nodes)):
        gtflow_node = gtflow_tree.nodes[node_idx]
        node = tree.nodes.add()
        node_type = gtflow_node.WhichOneof("node")
        node.node_id.value = node_idx
        if node_type == "leaf":
          leaf = gtflow_node.leaf
          if leaf.HasField("vector"):
            for weight in leaf.vector.value:
              new_value = node.leaf.vector.value.add()
              new_value.float_value = weight * tree_weight
          else:
            for index, weight in zip(
                leaf.sparse_vector.index, leaf.sparse_vector.value):
              new_value = node.leaf.sparse_vector.sparse_value[index]
              new_value.float_value = weight * tree_weight
        else:
          node = node.binary_node
          # Binary nodes here.
          if node_type == "dense_float_binary_split":
            split = gtflow_node.dense_float_binary_split
            feature_id = split.feature_column
            inequality_test = node.inequality_left_child_test
            inequality_test.feature_id.id.value = sorted_feature_names[feature_id]
            inequality_test.type = (
                generic_tree_model_pb2.InequalityTest.LESS_OR_EQUAL)
            inequality_test.threshold.float_value = split.threshold
          elif node_type == "sparse_float_binary_split_default_left":
            split = gtflow_node.sparse_float_binary_split_default_left.split
            node.default_direction = (generic_tree_model_pb2.BinaryNode.LEFT)
            feature_id = split.feature_column + num_dense
            inequality_test = node.inequality_left_child_test
            inequality_test.feature_id.id.value = (
                _SPARSE_FLOAT_FEATURE_NAME_TEMPLATE %
                (sorted_feature_names[feature_id], split.dimension_id))
            model_and_features.features.pop(sorted_feature_names[feature_id])
            (model_and_features.features[inequality_test.feature_id.id.value]
             .SetInParent())
            inequality_test.type = (
                generic_tree_model_pb2.InequalityTest.LESS_OR_EQUAL)
            inequality_test.threshold.float_value = split.threshold
          elif node_type == "sparse_float_binary_split_default_right":
            split = gtflow_node.sparse_float_binary_split_default_right.split
            node.default_direction = (
                generic_tree_model_pb2.BinaryNode.RIGHT)
            # TODO(nponomareva): adjust this id assignement when we allow multi-
            # column sparse tensors.
            feature_id = split.feature_column + num_dense
            inequality_test = node.inequality_left_child_test
            inequality_test.feature_id.id.value = (
                _SPARSE_FLOAT_FEATURE_NAME_TEMPLATE %
                (sorted_feature_names[feature_id], split.dimension_id))
            model_and_features.features.pop(sorted_feature_names[feature_id])
            (model_and_features.features[inequality_test.feature_id.id.value]
             .SetInParent())
            inequality_test.type = (
                generic_tree_model_pb2.InequalityTest.LESS_OR_EQUAL)
            inequality_test.threshold.float_value = split.threshold
          elif node_type == "categorical_id_binary_split":
            split = gtflow_node.categorical_id_binary_split
            node.default_direction = generic_tree_model_pb2.BinaryNode.RIGHT
            feature_id = split.feature_column + num_dense + num_sparse_float
            categorical_test = (
                generic_tree_model_extensions_pb2.MatchingValuesTest())
            categorical_test.feature_id.id.value = sorted_feature_names[
                feature_id]
            matching_id = categorical_test.value.add()
            matching_id.int64_value = split.feature_id
            node.custom_left_child_test.Pack(categorical_test)
          elif (node_type == "oblivious_dense_float_binary_split" or
                node_type == "oblivious_categorical_id_binary_split"):
            raise ValueError("Universal tree format doesn't support oblivious "
                             "trees")
          else:
            raise ValueError("Unexpected node type %s" % node_type)
          node.left_child_id.value = split.left_id
          node.right_child_id.value = split.right_id
    return model_and_features
function_tokens: def convert_to_universal_format ( dtec , sorted_feature_names , num_dense , num_sparse_float , num_sparse_int , feature_name_to_proto = None ) : del num_sparse_int # unused. model_and_features = generic_tree_model_pb2 . ModelAndFeatures ( ) # TODO(jonasz): Feature descriptions should contain information about how each # feature is processed before it's fed to the model (e.g. bucketing # information). As of now, this serves as a list of features the model uses. for feature_name in sorted_feature_names : if not feature_name_to_proto : model_and_features . features [ feature_name ] . SetInParent ( ) else : model_and_features . features [ feature_name ] . CopyFrom ( feature_name_to_proto [ feature_name ] ) model = model_and_features . model model . ensemble . summation_combination_technique . SetInParent ( ) for tree_idx in range ( len ( dtec . trees ) ) : gtflow_tree = dtec . trees [ tree_idx ] tree_weight = dtec . tree_weights [ tree_idx ] member = model . ensemble . members . add ( ) member . submodel_id . value = tree_idx tree = member . submodel . decision_tree for node_idx in range ( len ( gtflow_tree . nodes ) ) : gtflow_node = gtflow_tree . nodes [ node_idx ] node = tree . nodes . add ( ) node_type = gtflow_node . WhichOneof ( "node" ) node . node_id . value = node_idx if node_type == "leaf" : leaf = gtflow_node . leaf if leaf . HasField ( "vector" ) : for weight in leaf . vector . value : new_value = node . leaf . vector . value . add ( ) new_value . float_value = weight * tree_weight else : for index , weight in zip ( leaf . sparse_vector . index , leaf . sparse_vector . value ) : new_value = node . leaf . sparse_vector . sparse_value [ index ] new_value . float_value = weight * tree_weight else : node = node . binary_node # Binary nodes here. if node_type == "dense_float_binary_split" : split = gtflow_node . dense_float_binary_split feature_id = split . feature_column inequality_test = node . inequality_left_child_test inequality_test . feature_id . id . value = sorted_feature_names [ feature_id ] inequality_test . type = ( generic_tree_model_pb2 . InequalityTest . LESS_OR_EQUAL ) inequality_test . threshold . float_value = split . threshold elif node_type == "sparse_float_binary_split_default_left" : split = gtflow_node . sparse_float_binary_split_default_left . split node . default_direction = ( generic_tree_model_pb2 . BinaryNode . LEFT ) feature_id = split . feature_column + num_dense inequality_test = node . inequality_left_child_test inequality_test . feature_id . id . value = ( _SPARSE_FLOAT_FEATURE_NAME_TEMPLATE % ( sorted_feature_names [ feature_id ] , split . dimension_id ) ) model_and_features . features . pop ( sorted_feature_names [ feature_id ] ) ( model_and_features . features [ inequality_test . feature_id . id . value ] . SetInParent ( ) ) inequality_test . type = ( generic_tree_model_pb2 . InequalityTest . LESS_OR_EQUAL ) inequality_test . threshold . float_value = split . threshold elif node_type == "sparse_float_binary_split_default_right" : split = gtflow_node . sparse_float_binary_split_default_right . split node . default_direction = ( generic_tree_model_pb2 . BinaryNode . RIGHT ) # TODO(nponomareva): adjust this id assignement when we allow multi- # column sparse tensors. feature_id = split . feature_column + num_dense inequality_test = node . inequality_left_child_test inequality_test . feature_id . id . value = ( _SPARSE_FLOAT_FEATURE_NAME_TEMPLATE % ( sorted_feature_names [ feature_id ] , split . dimension_id ) ) model_and_features . features . pop ( sorted_feature_names [ feature_id ] ) ( model_and_features . features [ inequality_test . feature_id . id . value ] . SetInParent ( ) ) inequality_test . type = ( generic_tree_model_pb2 . InequalityTest . LESS_OR_EQUAL ) inequality_test . threshold . float_value = split . threshold elif node_type == "categorical_id_binary_split" : split = gtflow_node . categorical_id_binary_split node . default_direction = generic_tree_model_pb2 . BinaryNode . RIGHT feature_id = split . feature_column + num_dense + num_sparse_float categorical_test = ( generic_tree_model_extensions_pb2 . MatchingValuesTest ( ) ) categorical_test . feature_id . id . value = sorted_feature_names [ feature_id ] matching_id = categorical_test . value . add ( ) matching_id . int64_value = split . feature_id node . custom_left_child_test . Pack ( categorical_test ) elif ( node_type == "oblivious_dense_float_binary_split" or node_type == "oblivious_categorical_id_binary_split" ) : raise ValueError ( "Universal tree format doesn't support oblivious " "trees" ) else : raise ValueError ( "Unexpected node type %s" % node_type ) node . left_child_id . value = split . left_id node . right_child_id . value = split . right_id return model_and_features