mlrun 1.9.0rc12__py3-none-any.whl → 1.9.0rc13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of mlrun might be problematic. Click here for more details.

@@ -14,7 +14,7 @@
14
14
 
15
15
  from typing import Any, Optional, Union
16
16
 
17
- from tensorflow import keras
17
+ import tensorflow as tf
18
18
 
19
19
  import mlrun
20
20
  import mlrun.common.constants as mlrun_constants
@@ -27,11 +27,11 @@ from .utils import TFKerasTypes, TFKerasUtils
27
27
 
28
28
 
29
29
  def apply_mlrun(
30
- model: keras.Model = None,
30
+ model: tf.keras.Model = None,
31
31
  model_name: Optional[str] = None,
32
32
  tag: str = "",
33
33
  model_path: Optional[str] = None,
34
- model_format: str = TFKerasModelHandler.ModelFormats.SAVED_MODEL,
34
+ model_format: Optional[str] = None,
35
35
  save_traces: bool = False,
36
36
  modules_map: Optional[Union[dict[str, Union[None, str, list[str]]], str]] = None,
37
37
  custom_objects_map: Optional[Union[dict[str, Union[str, list[str]]], str]] = None,
@@ -54,7 +54,7 @@ def apply_mlrun(
54
54
  :param model_path: The model's store object path. Mandatory for evaluation (to know which model to
55
55
  update). If model is not provided, it will be loaded from this path.
56
56
  :param model_format: The format to use for saving and loading the model. Should be passed as a
57
- member of the class 'ModelFormats'. Default: 'ModelFormats.SAVED_MODEL'.
57
+ member of the class 'ModelFormats'.
58
58
  :param save_traces: Whether or not to use functions saving (only available for the 'SavedModel'
59
59
  format) for loading the model later without the custom objects dictionary. Only
60
60
  from tensorflow version >= 2.4.0. Using this setting will increase the model
@@ -16,14 +16,14 @@ from typing import Callable, Optional, Union
16
16
 
17
17
  import numpy as np
18
18
  import tensorflow as tf
19
- from tensorflow import Tensor, Variable
19
+ from tensorflow import keras
20
20
  from tensorflow.python.keras.callbacks import Callback
21
21
 
22
22
  import mlrun
23
23
 
24
24
  from ..._common import LoggingMode
25
25
  from ..._dl_common.loggers import Logger
26
- from ..utils import TFKerasTypes
26
+ from ..utils import TFKerasTypes, is_keras_3
27
27
 
28
28
 
29
29
  class LoggingCallback(Callback):
@@ -70,7 +70,7 @@ class LoggingCallback(Callback):
70
70
  {
71
71
  "epochs": 7
72
72
  }
73
- :param auto_log: Whether or not to enable auto logging, trying to track common static and dynamic
73
+ :param auto_log: Whether to enable auto logging, trying to track common static and dynamic
74
74
  hyperparameters.
75
75
  """
76
76
  super().__init__()
@@ -385,18 +385,24 @@ class LoggingCallback(Callback):
385
385
  self._logger.log_context_parameters()
386
386
 
387
387
  # Add learning rate:
388
- learning_rate_key = "lr"
389
- learning_rate_key_chain = ["optimizer", "lr"]
390
- if learning_rate_key not in self._dynamic_hyperparameters_keys and hasattr(
391
- self.model, "optimizer"
392
- ):
393
- try:
394
- self._get_hyperparameter(key_chain=learning_rate_key_chain)
388
+ learning_rate_keys = [
389
+ "learning_rate",
390
+ "lr",
391
+ ] # "lr" is for backward compatibility in older keras versions.
392
+ if all(
393
+ learning_rate_key not in self._dynamic_hyperparameters_keys
394
+ for learning_rate_key in learning_rate_keys
395
+ ) and hasattr(self.model, "optimizer"):
396
+ for learning_rate_key in learning_rate_keys:
397
+ learning_rate_key_chain = ["optimizer", learning_rate_key]
398
+ try:
399
+ self._get_hyperparameter(key_chain=learning_rate_key_chain)
400
+ except (KeyError, IndexError, AttributeError, ValueError):
401
+ continue
395
402
  self._dynamic_hyperparameters_keys[learning_rate_key] = (
396
403
  learning_rate_key_chain
397
404
  )
398
- except (KeyError, IndexError, ValueError):
399
- pass
405
+ break
400
406
 
401
407
  def _get_hyperparameter(
402
408
  self,
@@ -427,7 +433,7 @@ class LoggingCallback(Callback):
427
433
  value = value[key]
428
434
  else:
429
435
  value = getattr(value, key)
430
- except KeyError or IndexError as KeyChainError:
436
+ except KeyError or IndexError or AttributeError as KeyChainError:
431
437
  raise KeyChainError(
432
438
  f"Error during getting a hyperparameter value with the key chain {key_chain}. "
433
439
  f"The {value.__class__} in it does not have the following key/index from the key provided: "
@@ -435,7 +441,9 @@ class LoggingCallback(Callback):
435
441
  )
436
442
 
437
443
  # Parse the value:
438
- if isinstance(value, Tensor) or isinstance(value, Variable):
444
+ if isinstance(value, (tf.Tensor, tf.Variable)) or (
445
+ is_keras_3() and isinstance(value, (keras.KerasTensor, keras.Variable))
446
+ ):
439
447
  if int(tf.size(value)) == 1:
440
448
  value = float(value)
441
449
  else:
@@ -451,12 +459,7 @@ class LoggingCallback(Callback):
451
459
  f"The parameter with the following key chain: {key_chain} is a numpy.ndarray with {value.size} "
452
460
  f"elements. numpy arrays are trackable only if they have 1 element."
453
461
  )
454
- elif not (
455
- isinstance(value, float)
456
- or isinstance(value, int)
457
- or isinstance(value, str)
458
- or isinstance(value, bool)
459
- ):
462
+ elif not (isinstance(value, (float, int, str, bool))):
460
463
  raise mlrun.errors.MLRunInvalidArgumentError(
461
464
  f"The parameter with the following key chain: {key_chain} is of type '{type(value)}'. The only "
462
465
  f"trackable types are: float, int, str and bool."
@@ -29,7 +29,7 @@ from mlrun.features import Feature
29
29
  from .._common import without_mlrun_interface
30
30
  from .._dl_common import DLModelHandler
31
31
  from .mlrun_interface import TFKerasMLRunInterface
32
- from .utils import TFKerasUtils
32
+ from .utils import TFKerasUtils, is_keras_3
33
33
 
34
34
 
35
35
  class TFKerasModelHandler(DLModelHandler):
@@ -40,8 +40,8 @@ class TFKerasModelHandler(DLModelHandler):
40
40
  # Framework name:
41
41
  FRAMEWORK_NAME = "tensorflow.keras"
42
42
 
43
- # Declare a type of an input sample:
44
- IOSample = Union[tf.Tensor, tf.TensorSpec, np.ndarray]
43
+ # Declare a type of input sample (only from keras v3 there is a KerasTensor type):
44
+ IOSample = Union[tf.Tensor, tf.TensorSpec, "keras.KerasTensor", np.ndarray]
45
45
 
46
46
  class ModelFormats:
47
47
  """
@@ -49,9 +49,19 @@ class TFKerasModelHandler(DLModelHandler):
49
49
  """
50
50
 
51
51
  SAVED_MODEL = "SavedModel"
52
+ KERAS = "keras"
52
53
  H5 = "h5"
53
54
  JSON_ARCHITECTURE_H5_WEIGHTS = "json_h5"
54
55
 
56
+ @classmethod
57
+ def default(cls) -> str:
58
+ """
59
+ Get the default model format to use for saving and loading the model based on the keras version.
60
+
61
+ :return: The default model format to use.
62
+ """
63
+ return cls.KERAS if is_keras_3() else cls.SAVED_MODEL
64
+
55
65
  class _LabelKeys:
56
66
  """
57
67
  Required labels keys to log with the model.
@@ -65,7 +75,7 @@ class TFKerasModelHandler(DLModelHandler):
65
75
  model: keras.Model = None,
66
76
  model_path: Optional[str] = None,
67
77
  model_name: Optional[str] = None,
68
- model_format: str = ModelFormats.SAVED_MODEL,
78
+ model_format: Optional[str] = None,
69
79
  context: mlrun.MLClientCtx = None,
70
80
  modules_map: Optional[
71
81
  Union[dict[str, Union[None, str, list[str]]], str]
@@ -98,7 +108,7 @@ class TFKerasModelHandler(DLModelHandler):
98
108
  * If given a loaded model object and the model name is None, the name will be
99
109
  set to the model's object name / class.
100
110
  :param model_format: The format to use for saving and loading the model. Should be passed as a
101
- member of the class 'ModelFormats'. Default: 'ModelFormats.SAVED_MODEL'.
111
+ member of the class 'ModelFormats'.
102
112
  :param context: MLRun context to work with for logging the model.
103
113
  :param modules_map: A dictionary of all the modules required for loading the model. Each key
104
114
  is a path to a module and its value is the object name to import from it. All
@@ -144,8 +154,11 @@ class TFKerasModelHandler(DLModelHandler):
144
154
  * 'save_traces' parameter was miss-used.
145
155
  """
146
156
  # Validate given format:
157
+ if not model_format:
158
+ model_format = TFKerasModelHandler.ModelFormats.default()
147
159
  if model_format not in [
148
160
  TFKerasModelHandler.ModelFormats.SAVED_MODEL,
161
+ TFKerasModelHandler.ModelFormats.KERAS,
149
162
  TFKerasModelHandler.ModelFormats.H5,
150
163
  TFKerasModelHandler.ModelFormats.JSON_ARCHITECTURE_H5_WEIGHTS,
151
164
  ]:
@@ -153,6 +166,22 @@ class TFKerasModelHandler(DLModelHandler):
153
166
  f"Unrecognized model format: '{model_format}'. Please use one of the class members of "
154
167
  "'TFKerasModelHandler.ModelFormats'"
155
168
  )
169
+ if not is_keras_3():
170
+ if model_format == TFKerasModelHandler.ModelFormats.KERAS:
171
+ raise mlrun.errors.MLRunInvalidArgumentError(
172
+ "The 'keras' model format is only supported in Keras 3.0.0 and above. "
173
+ f"Current version is {keras.__version__}."
174
+ )
175
+ else:
176
+ if (
177
+ model_format == TFKerasModelHandler.ModelFormats.SAVED_MODEL
178
+ or model_format
179
+ == TFKerasModelHandler.ModelFormats.JSON_ARCHITECTURE_H5_WEIGHTS
180
+ ):
181
+ raise mlrun.errors.MLRunInvalidArgumentError(
182
+ f"The '{model_format}' model format is not supported in Keras 3.0.0 and above. "
183
+ f"Current version is {keras.__version__}."
184
+ )
156
185
 
157
186
  # Validate 'save_traces':
158
187
  if save_traces:
@@ -239,11 +268,19 @@ class TFKerasModelHandler(DLModelHandler):
239
268
  self._model_file = f"{self._model_name}.h5"
240
269
  self._model.save(self._model_file)
241
270
 
271
+ # ModelFormats.keras - Save as a keras file:
272
+ elif self._model_format == self.ModelFormats.KERAS:
273
+ self._model_file = f"{self._model_name}.keras"
274
+ self._model.save(self._model_file)
275
+
242
276
  # ModelFormats.SAVED_MODEL - Save as a SavedModel directory and zip its file:
243
277
  elif self._model_format == TFKerasModelHandler.ModelFormats.SAVED_MODEL:
244
278
  # Save it in a SavedModel format directory:
279
+ # Note: Using keras>=3.0.0 can save in this format via `model.export` but then it won't be able to load it
280
+ # back, only for inference. So, we use the `save` method instead for keras 2 and validate the user won't use
281
+ # keras 3 and this model format.
245
282
  if self._save_traces is True:
246
- # Save traces can only be used in versions >= 2.4, so only if its true we use it in the call:
283
+ # Save traces can only be used in versions >= 2.4, so only if it's true, we use it in the call:
247
284
  self._model.save(self._model_name, save_traces=self._save_traces)
248
285
  else:
249
286
  self._model.save(self._model_name)
@@ -303,6 +340,12 @@ class TFKerasModelHandler(DLModelHandler):
303
340
  self._model_file, custom_objects=self._custom_objects
304
341
  )
305
342
 
343
+ # ModelFormats.KERAS - Load from a keras file:
344
+ elif self._model_format == TFKerasModelHandler.ModelFormats.KERAS:
345
+ self._model = keras.models.load_model(
346
+ self._model_file, custom_objects=self._custom_objects
347
+ )
348
+
306
349
  # ModelFormats.SAVED_MODEL - Load from a SavedModel directory:
307
350
  elif self._model_format == TFKerasModelHandler.ModelFormats.SAVED_MODEL:
308
351
  self._model = keras.models.load_model(
@@ -434,7 +477,10 @@ class TFKerasModelHandler(DLModelHandler):
434
477
  )
435
478
 
436
479
  # Read the inputs:
437
- input_signature = [input_layer.type_spec for input_layer in self._model.inputs]
480
+ input_signature = [
481
+ getattr(input_layer, "type_spec", input_layer)
482
+ for input_layer in self._model.inputs
483
+ ]
438
484
 
439
485
  # Set the inputs:
440
486
  self.set_inputs(from_sample=input_signature)
@@ -453,7 +499,8 @@ class TFKerasModelHandler(DLModelHandler):
453
499
 
454
500
  # Read the outputs:
455
501
  output_signature = [
456
- output_layer.type_spec for output_layer in self._model.outputs
502
+ getattr(output_layer, "type_spec", output_layer)
503
+ for output_layer in self._model.outputs
457
504
  ]
458
505
 
459
506
  # Set the outputs:
@@ -509,6 +556,17 @@ class TFKerasModelHandler(DLModelHandler):
509
556
  f"'{self._model_path}'"
510
557
  )
511
558
 
559
+ # ModelFormats.KERAS - Get the keras model file:
560
+ elif self._model_format == TFKerasModelHandler.ModelFormats.KERAS:
561
+ self._model_file = os.path.join(
562
+ self._model_path, f"{self._model_name}.keras"
563
+ )
564
+ if not os.path.exists(self._model_file):
565
+ raise mlrun.errors.MLRunNotFoundError(
566
+ f"The model file '{self._model_name}.keras' was not found within the given 'model_path': "
567
+ f"'{self._model_path}'"
568
+ )
569
+
512
570
  # ModelFormats.SAVED_MODEL - Get the zip file and extract it, or simply locate the directory:
513
571
  elif self._model_format == TFKerasModelHandler.ModelFormats.SAVED_MODEL:
514
572
  self._model_file = os.path.join(self._model_path, f"{self._model_name}.zip")
@@ -559,7 +617,9 @@ class TFKerasModelHandler(DLModelHandler):
559
617
  # Supported types:
560
618
  if isinstance(sample, np.ndarray):
561
619
  return super()._read_sample(sample=sample)
562
- elif isinstance(sample, tf.TensorSpec):
620
+ elif isinstance(sample, tf.TensorSpec) or (
621
+ is_keras_3() and isinstance(sample, keras.KerasTensor)
622
+ ):
563
623
  return Feature(
564
624
  name=sample.name,
565
625
  value_type=TFKerasUtils.convert_tf_dtype_to_value_type(
@@ -11,8 +11,8 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
- #
15
14
  import tensorflow as tf
15
+ from packaging import version
16
16
  from tensorflow import keras
17
17
 
18
18
  import mlrun
@@ -117,3 +117,14 @@ class TFKerasUtils(DLUtils):
117
117
  raise mlrun.errors.MLRunInvalidArgumentError(
118
118
  f"MLRun value type is not supporting the given tensorflow data type: '{tf_dtype}'."
119
119
  )
120
+
121
+
122
+ def is_keras_3() -> bool:
123
+ """
124
+ Check if the current Keras version is 3.x.
125
+
126
+ :return: True if Keras version is 3.x, False otherwise.
127
+ """
128
+ return hasattr(keras, "__version__") and version.parse(
129
+ keras.__version__
130
+ ) >= version.parse("3.0.0")
@@ -1,4 +1,4 @@
1
1
  {
2
- "git_commit": "c1b0e9b2b7750c40fbb25d1cad52c24c9fa14652",
3
- "version": "1.9.0-rc12"
2
+ "git_commit": "b7122fc963d47705091026ecd96d6321291b400a",
3
+ "version": "1.9.0-rc13"
4
4
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mlrun
3
- Version: 1.9.0rc12
3
+ Version: 1.9.0rc13
4
4
  Summary: Tracking and config of machine learning runs
5
5
  Home-page: https://github.com/mlrun/mlrun
6
6
  Author: Yaron Haviv
@@ -198,13 +198,13 @@ mlrun/frameworks/sklearn/metrics_library.py,sha256=PVPNpljaGglXcw7THLHX-XU0cA8Nu
198
198
  mlrun/frameworks/sklearn/mlrun_interface.py,sha256=JzHMBQM4sPBJqzb8P-rsG_2RQ_QrXrb8KFj6GNfwrJ0,14339
199
199
  mlrun/frameworks/sklearn/model_handler.py,sha256=n0vpsQznva_WVloz7GTnfMGcMDQU_f1bHhUAJ_qxjfE,4753
200
200
  mlrun/frameworks/sklearn/utils.py,sha256=Cg_pSxUMvKe8vBSLQor6JM8u9_ccKJg4Rk5EPDzTsVo,1209
201
- mlrun/frameworks/tf_keras/__init__.py,sha256=OIHqn6Y1_lcB2j5O3hKea4cp0uVtF4Lv96lvAkm_9x4,10553
201
+ mlrun/frameworks/tf_keras/__init__.py,sha256=M2sMbYHLrlF-KFR5kvA9mevRo3Nf8U0B5a_DM9rzwCY,10484
202
202
  mlrun/frameworks/tf_keras/mlrun_interface.py,sha256=1xPUv8YAqxrY3CmkMfWMdp2yEAvk5viiMH6qw41ytSk,16617
203
- mlrun/frameworks/tf_keras/model_handler.py,sha256=K99NF7WxqmGpzXXssO9mdQb_Swaek_g3aIhZ4GW-k1k,28276
203
+ mlrun/frameworks/tf_keras/model_handler.py,sha256=CquUawDowzZgbQtphFbdz1QBzNlOfnnePSHkHDS9Iqg,31102
204
204
  mlrun/frameworks/tf_keras/model_server.py,sha256=PZW6OBGTJ6bSfHedAhhW8HATbJyp2VaAzSDC02zjyKk,9653
205
- mlrun/frameworks/tf_keras/utils.py,sha256=_QWk1YmdRybbUB54vsQFE2_WMuAK0g7eR1ozVbMk0Go,4284
205
+ mlrun/frameworks/tf_keras/utils.py,sha256=Z8hA1CgpSJWLC_T6Ay7xZKVyWlX9B85MSmQr2biXRag,4582
206
206
  mlrun/frameworks/tf_keras/callbacks/__init__.py,sha256=sd8aWG2jO9mO_noZca0ReVf8X6fSCqO_di1Z-mT8FH8,742
207
- mlrun/frameworks/tf_keras/callbacks/logging_callback.py,sha256=QGgCDAVtoixy94NdrbCfQLsV0kQlv4b535pVv47RRRw,22029
207
+ mlrun/frameworks/tf_keras/callbacks/logging_callback.py,sha256=0-cwQU-GIPUnHRqez9MX4_Gwgb6OgdcPRjU6E2Xo5JE,22323
208
208
  mlrun/frameworks/tf_keras/callbacks/mlrun_logging_callback.py,sha256=O63ZL_04wqxDHhDsNhGX880dUmIUPt5bKnSgTUTbduw,8838
209
209
  mlrun/frameworks/tf_keras/callbacks/tensorboard_logging_callback.py,sha256=Z0Qgea9-G0-9gq3OPH3Cre7f8zMWX0bWyBQPgxxemYQ,28616
210
210
  mlrun/frameworks/xgboost/__init__.py,sha256=NyFRxu5v5z8oegbJP05PFUmfJL3I3JeN1PYHjIbfXpo,10335
@@ -341,11 +341,11 @@ mlrun/utils/notifications/notification/mail.py,sha256=ZyJ3eqd8simxffQmXzqd3bgbAq
341
341
  mlrun/utils/notifications/notification/slack.py,sha256=kfhogR5keR7Zjh0VCjJNK3NR5_yXT7Cv-x9GdOUW4Z8,7294
342
342
  mlrun/utils/notifications/notification/webhook.py,sha256=zxh8CAlbPnTazsk6r05X5TKwqUZVOH5KBU2fJbzQlG4,5330
343
343
  mlrun/utils/version/__init__.py,sha256=7kkrB7hEZ3cLXoWj1kPoDwo4MaswsI2JVOBpbKgPAgc,614
344
- mlrun/utils/version/version.json,sha256=kOsyMz4GxGK18ykYqrSfKIGAN0S7-B714pDtwchOhXw,89
344
+ mlrun/utils/version/version.json,sha256=zjuQ3-Y7SvQEjGRKbLzsak_e6yT1bpjT24CV5mhXx9c,89
345
345
  mlrun/utils/version/version.py,sha256=eEW0tqIAkU9Xifxv8Z9_qsYnNhn3YH7NRAfM-pPLt1g,1878
346
- mlrun-1.9.0rc12.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
347
- mlrun-1.9.0rc12.dist-info/METADATA,sha256=PgnnDUVkPwm0tw-X0eLAIJodefUMwF46yPREhEB4CnU,25760
348
- mlrun-1.9.0rc12.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
349
- mlrun-1.9.0rc12.dist-info/entry_points.txt,sha256=1Owd16eAclD5pfRCoJpYC2ZJSyGNTtUr0nCELMioMmU,46
350
- mlrun-1.9.0rc12.dist-info/top_level.txt,sha256=NObLzw3maSF9wVrgSeYBv-fgnHkAJ1kEkh12DLdd5KM,6
351
- mlrun-1.9.0rc12.dist-info/RECORD,,
346
+ mlrun-1.9.0rc13.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
347
+ mlrun-1.9.0rc13.dist-info/METADATA,sha256=VyM22mAVHzdNF0LxqFtM-uF_2qhHlQ-A8SevmxUMrcY,25760
348
+ mlrun-1.9.0rc13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
349
+ mlrun-1.9.0rc13.dist-info/entry_points.txt,sha256=1Owd16eAclD5pfRCoJpYC2ZJSyGNTtUr0nCELMioMmU,46
350
+ mlrun-1.9.0rc13.dist-info/top_level.txt,sha256=NObLzw3maSF9wVrgSeYBv-fgnHkAJ1kEkh12DLdd5KM,6
351
+ mlrun-1.9.0rc13.dist-info/RECORD,,