There may be still be an issue with conflicts between TF-DF and YDF. When I execute:
df_model.to_tensorflow_saved_model(path="multi/ranking/1/", mode="tf")
in ydf 0.4.1, it outputs this error:
TypeError Traceback (most recent call last)
Cell In[55], line 4
1 # Export the model to the TensorFlow SavedModel format.
2 # The model can be executed with Servomatic, TensorFlow Serving and
3 # Vertex AI.
----> 4 df_model.to_tensorflow_saved_model(path="multi/ranking/1/", mode="tf")
File ~/anaconda3/envs/tensorflow2_p310/lib/python3.10/site-packages/ydf/model/generic_model.py:729, in GenericModel.to_tensorflow_saved_model(self, path, input_model_signature_fn, mode, feature_dtypes, servo_api, feed_example_proto, pre_processing, post_processing, temp_dir)
602 def to_tensorflow_saved_model( # pylint: disable=dangerous-default-value
603 self,
604 path: str,
(...)
613 temp_dir: Optional[str] = None,
614 ) -> None:
615 """Exports the model as a TensorFlow Saved model.
616
617 This function requires TensorFlow and TensorFlow Decision Forests to be
(...)
726 (default), uses `tempfile.mkdtemp` default temporary directory.
727 """
--> 729 export_tf.ydf_model_to_tensorflow_saved_model(
730 ydf_model=self,
731 path=path,
732 input_model_signature_fn=input_model_signature_fn,
733 mode=mode,
734 feature_dtypes=feature_dtypes,
735 servo_api=servo_api,
736 feed_example_proto=feed_example_proto,
737 pre_processing=pre_processing,
738 post_processing=post_processing,
739 temp_dir=temp_dir,
740 )
File ~/anaconda3/envs/tensorflow2_p310/lib/python3.10/site-packages/ydf/model/export_tf.py:141, in ydf_model_to_tensorflow_saved_model(ydf_model, path, input_model_signature_fn, mode, feature_dtypes, servo_api, feed_example_proto, pre_processing, post_processing, temp_dir)
137 if input_model_signature_fn is not None:
138 raise ValueError(
139 "input_model_signature_fn is not supported for `tf` mode."
140 )
--> 141 ydf_model_to_tensorflow_saved_model_tf_mode(
142 ydf_model=ydf_model,
143 path=path,
144 feature_dtypes=feature_dtypes,
145 servo_api=servo_api,
146 feed_example_proto=feed_example_proto,
147 pre_processing=pre_processing,
148 post_processing=post_processing,
149 temp_dir=temp_dir,
150 )
151 else:
152 raise ValueError(f"Invalid mode: {mode}")
File ~/anaconda3/envs/tensorflow2_p310/lib/python3.10/site-packages/ydf/model/export_tf.py:194, in ydf_model_to_tensorflow_saved_model_tf_mode(ydf_model, path, feature_dtypes, servo_api, feed_example_proto, pre_processing, post_processing, temp_dir)
190 # The temporary files should remain available until the call to
191 # "tf.saved_model.save"
192 with tempfile.TemporaryDirectory(dir=temp_dir) as effective_temp_dir:
--> 194 tf_module = ydf_model.to_tensorflow_function(
195 temp_dir=effective_temp_dir,
196 squeeze_binary_classification=not servo_api,
197 )
199 # Store pre / post processing operations
200 # Note: Storing the raw variable allows for pre/post-processing to be
201 # TensorFlow modules with resources.
202 tf_module.raw_pre_processing = pre_processing
File ~/anaconda3/envs/tensorflow2_p310/lib/python3.10/site-packages/ydf/model/generic_model.py:808, in GenericModel.to_tensorflow_function(self, temp_dir, can_be_saved, squeeze_binary_classification)
742 def to_tensorflow_function( # pytype: disable=name-error
743 self,
744 temp_dir: Optional[str] = None,
745 can_be_saved: bool = True,
746 squeeze_binary_classification: bool = True,
747 ) -> "tensorflow.Module":
748 """Converts the YDF model into a @tf.function callable TensorFlow Module.
749
750 The output module can be composed with other TensorFlow operations,
(...)
805 A TensorFlow @tf.function.
806 """
--> 808 return export_tf.ydf_model_to_tf_function(
809 ydf_model=self,
810 temp_dir=temp_dir,
811 can_be_saved=can_be_saved,
812 squeeze_binary_classification=squeeze_binary_classification,
813 )
File ~/anaconda3/envs/tensorflow2_p310/lib/python3.10/site-packages/ydf/model/export_tf.py:310, in ydf_model_to_tf_function(ydf_model, temp_dir, can_be_saved, squeeze_binary_classification)
304 """Converts a YDF model to a TensorFlow function.
305
306 See GenericModel.to_tensorflow_function for the documentation.
307 """
309 tf = import_tensorflow()
--> 310 tfdf = import_tensorflow_decision_forests()
311 tf_op = tfdf.keras.core.tf_op
313 # Using prefixes ensure multiple models can be combined in a single
314 # SavedModel.
File ~/anaconda3/envs/tensorflow2_p310/lib/python3.10/site-packages/ydf/model/export_tf.py:381, in import_tensorflow_decision_forests()
379 """Imports the tensorflow decision forests module."""
380 try:
--> 381 import tensorflow_decision_forests as tfdf # pylint: disable=g-import-not-at-top,import-outside-toplevel # pytype: disable=import-error
383 return tfdf
384 except ImportError as exc:
File ~/anaconda3/envs/tensorflow2_p310/lib/python3.10/site-packages/tensorflow_decision_forests/__init__.py:64
60 from tensorflow_decision_forests.tensorflow import check_version
62 check_version.check_version(__version__, compatible_tf_versions)
---> 64 from tensorflow_decision_forests import keras
65 from tensorflow_decision_forests.component import py_tree
66 from tensorflow_decision_forests.component.builder import builder
File ~/anaconda3/envs/tensorflow2_p310/lib/python3.10/site-packages/tensorflow_decision_forests/keras/__init__.py:53
15 """Decision Forest in a Keras Model.
16
17 Usage example:
(...)
48 ```
49 """
51 from typing import Callable, List
---> 53 from tensorflow_decision_forests.keras import core
54 from tensorflow_decision_forests.keras import wrappers
56 # Utility classes
File ~/anaconda3/envs/tensorflow2_p310/lib/python3.10/site-packages/tensorflow_decision_forests/keras/core.py:62
60 from tensorflow.python.data.ops import dataset_ops
61 from tensorflow.python.data.ops import load_op
---> 62 from tensorflow_decision_forests.component.inspector import inspector as inspector_lib
63 from tensorflow_decision_forests.component.tuner import tuner as tuner_lib
64 from tensorflow_decision_forests.keras import core_inference
File ~/anaconda3/envs/tensorflow2_p310/lib/python3.10/site-packages/tensorflow_decision_forests/component/inspector/inspector.py:64
61 import six
62 import tensorflow as tf
---> 64 from tensorflow_decision_forests.component import py_tree
65 from tensorflow_decision_forests.component.inspector import blob_sequence
66 from yggdrasil_decision_forests.dataset import data_spec_pb2
File ~/anaconda3/envs/tensorflow2_p310/lib/python3.10/site-packages/tensorflow_decision_forests/component/py_tree/__init__.py:20
1 # Copyright 2021 Google LLC.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
(...)
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 """Decision trees stored as python objects.
16
17 To be used with the model inspector and model builder.
18 """
---> 20 from tensorflow_decision_forests.component.py_tree import condition
21 from tensorflow_decision_forests.component.py_tree import dataspec
22 from tensorflow_decision_forests.component.py_tree import node
File ~/anaconda3/envs/tensorflow2_p310/lib/python3.10/site-packages/tensorflow_decision_forests/component/py_tree/condition.py:26
22 from typing import List, Union, Optional
24 import six
---> 26 from tensorflow_decision_forests.component.py_tree import dataspec as dataspec_lib
27 from yggdrasil_decision_forests.dataset import data_spec_pb2
28 from yggdrasil_decision_forests.model.decision_tree import decision_tree_pb2
File ~/anaconda3/envs/tensorflow2_p310/lib/python3.10/site-packages/tensorflow_decision_forests/component/py_tree/dataspec.py:24
21 import math
22 from typing import NamedTuple, Union, Optional, List
---> 24 from yggdrasil_decision_forests.dataset import data_spec_pb2
26 ColumnType = data_spec_pb2.ColumnType
28 # Special value to out of vocabulary items.
File ~/anaconda3/envs/tensorflow2_p310/lib/python3.10/site-packages/yggdrasil_decision_forests/dataset/data_spec_pb2.py:16
9 # @@protoc_insertion_point(imports)
11 _sym_db = _symbol_database.Default()
---> 16 DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n2yggdrasil_decision_forests/dataset/data_spec.proto\x12(yggdrasil_decision_forests.dataset.proto\"\xb9\x01\n\x11\x44\x61taSpecification\x12\x41\n\x07\x63olumns\x18\x01 \x03(\x0b\x32\x30.yggdrasil_decision_forests.dataset.proto.Column\x12\x18\n\x10\x63reated_num_rows\x18\x02 \x01(\x03\x12G\n\nunstackeds\x18\x03 \x03(\x0b\x32\x33.yggdrasil_decision_forests.dataset.proto.Unstacked\"\x95\x05\n\x06\x43olumn\x12K\n\x04type\x18\x01 \x01(\x0e\x32\x34.yggdrasil_decision_forests.dataset.proto.ColumnType:\x07UNKNOWN\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x1d\n\x0eis_manual_type\x18\x03 \x01(\x08:\x05\x66\x61lse\x12\x46\n\ttokenizer\x18\x04 \x01(\x0b\x32\x33.yggdrasil_decision_forests.dataset.proto.Tokenizer\x12J\n\tnumerical\x18\x05 \x01(\x0b\x32\x37.yggdrasil_decision_forests.dataset.proto.NumericalSpec\x12N\n\x0b\x63\x61tegorical\x18\x06 \x01(\x0b\x32\x39.yggdrasil_decision_forests.dataset.proto.CategoricalSpec\x12\x14\n\tcount_nas\x18\x07 \x01(\x03:\x01\x30\x12\x61\n\x15\x64iscretized_numerical\x18\x08 \x01(\x0b\x32\x42.yggdrasil_decision_forests.dataset.proto.DiscretizedNumericalSpec\x12\x46\n\x07\x62oolean\x18\t \x01(\x0b\x32\x35.yggdrasil_decision_forests.dataset.proto.BooleanSpec\x12O\n\x0cmulti_values\x18\n \x01(\x0b\x32\x39.yggdrasil_decision_forests.dataset.proto.MultiValuesSpec\x12\x1b\n\x0cis_unstacked\x18\x0b \x01(\x08:\x05\x66\x61lse\"\xdf\x03\n\x0f\x43\x61tegoricalSpec\x12\x1b\n\x13most_frequent_value\x18\x01 \x01(\x03\x12\x1f\n\x17number_of_unique_values\x18\x02 \x01(\x03\x12\x1a\n\x0fmin_value_count\x18\x03 \x01(\x05:\x01\x35\x12)\n\x1bmax_number_of_unique_values\x18\x04 \x01(\x05:\x04\x32\x30\x30\x30\x12\x1e\n\x16is_already_integerized\x18\x05 \x01(\x08\x12S\n\x05items\x18\x07 \x03(\x0b\x32\x44.yggdrasil_decision_forests.dataset.proto.CategoricalSpec.ItemsEntry\x12\x32\n#offset_value_by_one_during_training\x18\x08 \x01(\x08:\x05\x66\x61lse\x1ar\n\nItemsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12S\n\x05value\x18\x02 \x01(\x0b\x32\x44.yggdrasil_decision_forests.dataset.proto.CategoricalSpec.VocabValue:\x02\x38\x01\x1a*\n\nVocabValue\x12\r\n\x05index\x18\x01 \x01(\x03\x12\r\n\x05\x63ount\x18\x02 \x01(\x03\"b\n\rNumericalSpec\x12\x0f\n\x04mean\x18\x01 \x01(\x01:\x01\x30\x12\x11\n\tmin_value\x18\x02 \x01(\x02\x12\x11\n\tmax_value\x18\x03 \x01(\x02\x12\x1a\n\x12standard_deviation\x18\x04 \x01(\x01\"G\n\x0fMultiValuesSpec\x12\x19\n\x11max_observed_size\x18\x01 \x01(\x05\x12\x19\n\x11min_observed_size\x18\x02 \x01(\x05\"6\n\x0b\x42ooleanSpec\x12\x12\n\ncount_true\x18\x01 \x01(\x03\x12\x13\n\x0b\x63ount_false\x18\x02 \x01(\x03\"\x91\x01\n\x18\x44iscretizedNumericalSpec\x12\x16\n\nboundaries\x18\x01 \x03(\x02\x42\x02\x10\x01\x12\"\n\x1aoriginal_num_unique_values\x18\x02 \x01(\x03\x12\x1d\n\x10maximum_num_bins\x18\x03 \x01(\x03:\x03\x32\x35\x35\x12\x1a\n\x0fmin_obs_in_bins\x18\x04 \x01(\x05:\x01\x33\"\xb2\x03\n\tTokenizer\x12Y\n\x08splitter\x18\x01 \x01(\x0e\x32<.yggdrasil_decision_forests.dataset.proto.Tokenizer.Splitter:\tSEPARATOR\x12\x16\n\tseparator\x18\x02 \x01(\t:\x03 ;,\x12\x16\n\x05regex\x18\x03 \x01(\t:\x07([\\S]+)\x12\x1b\n\rto_lower_case\x18\x04 \x01(\x08:\x04true\x12N\n\x08grouping\x18\x05 \x01(\x0b\x32<.yggdrasil_decision_forests.dataset.proto.Tokenizer.Grouping\x1aS\n\x08Grouping\x12\x16\n\x08unigrams\x18\x01 \x01(\x08:\x04true\x12\x16\n\x07\x62igrams\x18\x02 \x01(\x08:\x05\x66\x61lse\x12\x17\n\x08trigrams\x18\x03 \x01(\x08:\x05\x66\x61lse\"X\n\x08Splitter\x12\x0b\n\x07INVALID\x10\x00\x12\r\n\tSEPARATOR\x10\x01\x12\x0f\n\x0bREGEX_MATCH\x10\x02\x12\r\n\tCHARACTER\x10\x03\x12\x10\n\x0cNO_SPLITTING\x10\x04\"\x97\x01\n\tUnstacked\x12\x15\n\roriginal_name\x18\x01 \x01(\t\x12\x18\n\x10\x62\x65gin_column_idx\x18\x02 \x01(\x05\x12\x0c\n\x04size\x18\x03 \x01(\x05\x12K\n\x04type\x18\x04 \x01(\x0e\x32\x34.yggdrasil_decision_forests.dataset.proto.ColumnType:\x07UNKNOWN\"\xde\x04\n\x16\x44\x61taSpecificationGuide\x12L\n\rcolumn_guides\x18\x01 \x03(\x0b\x32\x35.yggdrasil_decision_forests.dataset.proto.ColumnGuide\x12S\n\x14\x64\x65\x66\x61ult_column_guide\x18\x02 \x01(\x0b\x32\x35.yggdrasil_decision_forests.dataset.proto.ColumnGuide\x12,\n\x1dignore_columns_without_guides\x18\x03 \x01(\x08:\x05\x66\x61lse\x12\x30\n\"max_num_scanned_rows_to_guess_type\x18\x04 \x01(\x03:\x04\x31\x30\x30\x30\x12*\n\x1b\x64\x65tect_boolean_as_numerical\x18\x05 \x01(\x08:\x05\x66\x61lse\x12\x38\n)detect_numerical_as_discretized_numerical\x18\x06 \x01(\x08:\x05\x66\x61lse\x12\x39\n-max_num_scanned_rows_to_accumulate_statistics\x18\x07 \x01(\x03:\x02-1\x12\x31\n#unstack_numerical_set_as_numericals\x18\x08 \x01(\x08:\x04true\x12*\n\x1bignore_unknown_type_columns\x18\t \x01(\x08:\x05\x66\x61lse\x12\x41\n3allow_tokenization_for_inference_as_categorical_set\x18\n \x01(\x08:\x04true\"\xfc\x03\n\x0b\x43olumnGuide\x12\x1b\n\x13\x63olumn_name_pattern\x18\x01 \x01(\t\x12\x42\n\x04type\x18\x02 \x01(\x0e\x32\x34.yggdrasil_decision_forests.dataset.proto.ColumnType\x12N\n\ncategorial\x18\x03 \x01(\x0b\x32:.yggdrasil_decision_forests.dataset.proto.CategoricalGuide\x12K\n\tnumerical\x18\x04 \x01(\x0b\x32\x38.yggdrasil_decision_forests.dataset.proto.NumericalGuide\x12K\n\ttokenizer\x18\x05 \x01(\x0b\x32\x38.yggdrasil_decision_forests.dataset.proto.TokenizerGuide\x12 \n\x11\x61llow_multi_match\x18\x06 \x01(\x08:\x05\x66\x61lse\x12\x62\n\x15\x64iscretized_numerical\x18\x07 \x01(\x0b\x32\x43.yggdrasil_decision_forests.dataset.proto.DiscretizedNumericalGuide\x12\x1c\n\rignore_column\x18\x08 \x01(\x08:\x05\x66\x61lse\"\xc8\x02\n\x10\x43\x61tegoricalGuide\x12\x1e\n\x13min_vocab_frequency\x18\x01 \x01(\x05:\x01\x35\x12\x1d\n\x0fmax_vocab_count\x18\x02 \x01(\x05:\x04\x32\x30\x30\x30\x12\x1e\n\x16is_already_integerized\x18\x03 \x01(\x08\x12,\n$number_of_already_integerized_values\x18\x04 \x01(\x03\x12x\n\x1boverride_most_frequent_item\x18\x05 \x01(\x0b\x32S.yggdrasil_decision_forests.dataset.proto.CategoricalGuide.OverrideMostFrequentItem\x1a-\n\x18OverrideMostFrequentItem\x12\x11\n\tstr_value\x18\x05 \x01(\t\"\x10\n\x0eNumericalGuide\"X\n\x0eTokenizerGuide\x12\x46\n\ttokenizer\x18\x01 \x01(\x0b\x32\x33.yggdrasil_decision_forests.dataset.proto.Tokenizer\"V\n\x19\x44iscretizedNumericalGuide\x12\x1d\n\x10maximum_num_bins\x18\x01 \x01(\x03:\x03\x32\x35\x35\x12\x1a\n\x0fmin_obs_in_bins\x18\x02 \x01(\x05:\x01\x33\"\xe1\x03\n\x1c\x44\x61taSpecificationAccumulator\x12^\n\x07\x63olumns\x18\x01 \x03(\x0b\x32M.yggdrasil_decision_forests.dataset.proto.DataSpecificationAccumulator.Column\x1a\xe0\x02\n\x06\x43olumn\x12\x11\n\tkahan_sum\x18\x01 \x01(\x01\x12\x17\n\x0fkahan_sum_error\x18\x02 \x01(\x01\x12\x11\n\tmin_value\x18\x03 \x01(\x01\x12\x11\n\tmax_value\x18\x04 \x01(\x01\x12\x1b\n\x13kahan_sum_of_square\x18\x06 \x01(\x01\x12!\n\x19kahan_sum_of_square_error\x18\x07 \x01(\x01\x12\x86\x01\n\x15\x64iscretized_numerical\x18\x05 \x03(\x0b\x32g.yggdrasil_decision_forests.dataset.proto.DataSpecificationAccumulator.Column.DiscretizedNumericalEntry\x1a;\n\x19\x44iscretizedNumericalEntry\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01*\xc9\x01\n\nColumnType\x12\x0b\n\x07UNKNOWN\x10\x00\x12\r\n\tNUMERICAL\x10\x01\x12\x11\n\rNUMERICAL_SET\x10\x02\x12\x12\n\x0eNUMERICAL_LIST\x10\x03\x12\x0f\n\x0b\x43\x41TEGORICAL\x10\x04\x12\x13\n\x0f\x43\x41TEGORICAL_SET\x10\x05\x12\x14\n\x10\x43\x41TEGORICAL_LIST\x10\x06\x12\x0b\n\x07\x42OOLEAN\x10\x07\x12\n\n\x06STRING\x10\x08\x12\x19\n\x15\x44ISCRETIZED_NUMERICAL\x10\t\x12\x08\n\x04HASH\x10\n')
18 _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
19 _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'yggdrasil_decision_forests.dataset.data_spec_pb2', globals())
TypeError: Couldn't build proto file into descriptor pool: duplicate file name yggdrasil_decision_forests/dataset/data_spec.proto