Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keras file format updates #1401

Merged
merged 27 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
473a118
omlt import fix
rundxdi Apr 18, 2024
890dd47
updated main surrogate code; baseline tests fixed with re-run NNs
rundxdi Apr 25, 2024
ca0a0d7
black and filename option
rundxdi May 8, 2024
a0f947e
remove version restriction on tensorflow
rundxdi May 8, 2024
76bf172
removing unused vars
rundxdi May 8, 2024
bd446de
testing model format fixes
rundxdi May 8, 2024
bde687f
updating additional tests
rundxdi May 8, 2024
a53970c
rerun black
rundxdi May 8, 2024
fa96615
setup.py fixes
rundxdi May 8, 2024
9868c04
black on setup.py
rundxdi May 8, 2024
7ebd238
expected test failures
rundxdi Jun 13, 2024
17016a3
rerun black
rundxdi Jun 13, 2024
b58c71b
correct version of black
rundxdi Jun 13, 2024
30d3470
Merge branch 'main' into keras_file_format_updates
rundxdi Jun 13, 2024
cfd338d
deprecation warning
rundxdi Jun 13, 2024
e527e7f
update deprecation status
rundxdi Jun 13, 2024
a19926e
skip testing on keras_surrogates for python 3.8
rundxdi Jun 14, 2024
72a3b04
black
rundxdi Jun 14, 2024
7832c07
Merge branch 'main' into keras_file_format_updates
rundxdi Jul 17, 2024
3f40a24
remove old keras files
bpaul4 Jul 17, 2024
03d5438
remove more old keras files
bpaul4 Jul 17, 2024
98adbe6
Merge branch 'main' of https://github.com/IDAES/idaes-pse into keras_…
bpaul4 Aug 16, 2024
7e4e87e
try removing xfails from keras surrogate tests
bpaul4 Aug 16, 2024
eb39315
add comments explaining xfailing sofc surrogate tests
bpaul4 Aug 16, 2024
efbe7c7
Merge branch 'main' into keras_file_format_updates
Aug 16, 2024
1113057
Try removing workaround for TensorFlow failures for Python 3.11
lbianchi-lbl Aug 16, 2024
0c2775e
Add .keras suffix to package_data
lbianchi-lbl Aug 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions idaes/core/surrogate/keras_surrogate.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@

if omlt_available:
from omlt import OmltBlock, OffsetScaling
from omlt.neuralnet import (
from omlt.neuralnet.nn_formulation import (
FullSpaceSmoothNNFormulation,
ReducedSpaceSmoothNNFormulation,
ReluBigMFormulation,
Expand Down Expand Up @@ -263,7 +263,7 @@ def save_to_folder(self, keras_folder_name):
The name of the folder to contain the Keras model and additional
IDAES metadata
"""
self._keras_model.save(keras_folder_name)
self._keras_model.save(os.path.join(keras_folder_name, "idaes_keras_model.keras"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the file name be hard-coded here, or should we make this an input from the user (either optional or required).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I support letting users pass a string for the file name, so something like

Suggested change
self._keras_model.save(os.path.join(keras_folder_name, "idaes_keras_model.keras"))
self._keras_model.save(os.path.join(keras_folder_name, keras_file_name + ".keras"))

where keras_file_name is an input to the save method. I don't know if we still need to specify the folder name, or if a single string for the entire path is sufficient.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The folder name is used to save/load some model weights and some idaes specific information separate from the filename. But I think the file name should be rename-able as you say -- making that change now

info = dict()
info["input_scaler"] = None
if self._input_scaler is not None:
Expand Down Expand Up @@ -293,7 +293,9 @@ def load_from_folder(cls, keras_folder_name):

Returns: an instance of KerasSurrogate
"""
keras_model = keras.models.load_model(keras_folder_name)

keras_model = keras.models.load_model(os.path.join(keras_folder_name, "idaes_keras_model.keras"))

with open(os.path.join(keras_folder_name, "idaes_info.json")) as fd:
info = json.load(fd)

Expand All @@ -319,12 +321,14 @@ def save_keras_json_hd5(nn, path, name):
json_model = nn.to_json()
with open(os.path.join(path, "{}.json".format(name)), "w") as json_file:
json_file.write(json_model)
nn.save_weights(os.path.join(path, "{}.h5".format(name)))
nn.save(os.path.join(path, "{}.keras".format(name)))
nn.save_weights(os.path.join(path, "{}.weights.h5".format(name)))


def load_keras_json_hd5(path, name):
with open(os.path.join(path, "{}.json".format(name)), "r") as json_file:
json_model = json_file.read()
nn = keras.models.model_from_json(json_model)
nn.load_weights(os.path.join(path, "{}.h5".format(name)))
nn = keras.models.load_model(os.path.join(path, "{}.keras".format(name)))
nn.load_weights(os.path.join(path, "{}.weights.h5".format(name)))
return nn
8 changes: 4 additions & 4 deletions idaes/core/surrogate/tests/data/create_keras_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def compare_fit(nn, x_test, y_test, input_scaler, output_scaler):
nn.compile(optimizer=Adam(), loss="mse")

mcp_save = ModelCheckpoint(
".mdl_wts.hdf5", save_best_only=True, monitor="val_loss", mode="min"
".mdl_wts.keras", save_best_only=True, monitor="val_loss", mode="min"
)
history = nn.fit(
x=x,
Expand Down Expand Up @@ -111,7 +111,7 @@ def compare_fit(nn, x_test, y_test, input_scaler, output_scaler):
nn.compile(optimizer=Adam(), loss="mse")

mcp_save = ModelCheckpoint(
".mdl_wts.hdf5", save_best_only=True, monitor="val_loss", mode="min"
".mdl_wts.keras", save_best_only=True, monitor="val_loss", mode="min"
)
history = nn.fit(
x=x,
Expand Down Expand Up @@ -161,7 +161,7 @@ def compare_fit(nn, x_test, y_test, input_scaler, output_scaler):
nn.compile(optimizer=Adam(), loss="mse")

mcp_save = ModelCheckpoint(
".mdl_wts.hdf5", save_best_only=True, monitor="val_loss", mode="min"
".mdl_wts.keras", save_best_only=True, monitor="val_loss", mode="min"
)
history = nn.fit(
x=x,
Expand All @@ -188,7 +188,7 @@ def compare_fit(nn, x_test, y_test, input_scaler, output_scaler):
nn.compile(optimizer=Adam(), loss="mse")

mcp_save = ModelCheckpoint(
".mdl_wts.hdf5", save_best_only=True, monitor="val_loss", mode="min"
".mdl_wts.keras", save_best_only=True, monitor="val_loss", mode="min"
)
history = nn.fit(
x=x,
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"class_name": "Sequential", "config": {"name": "PT_data_2_10_10_2_relu", "layers": [{"class_name": "InputLayer", "config": {"batch_input_shape": [null, 2], "dtype": "float32", "sparse": false, "ragged": false, "name": "dense_9_input"}}, {"class_name": "Dense", "config": {"name": "dense_9", "trainable": true, "batch_input_shape": [null, 2], "dtype": "float32", "units": 10, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "Dense", "config": {"name": "dense_10", "trainable": true, "dtype": "float32", "units": 10, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "Dense", "config": {"name": "dense_11", "trainable": true, "dtype": "float32", "units": 2, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}]}, "keras_version": "2.7.0", "backend": "tensorflow"}
{"module": "keras", "class_name": "Sequential", "config": {"name": "PT_data_2_10_10_2_relu", "trainable": true, "dtype": "float32", "layers": [{"module": "keras.layers", "class_name": "InputLayer", "config": {"batch_shape": [null, 2], "dtype": "float32", "sparse": false, "name": "input_layer_3"}, "registered_name": null}, {"module": "keras.layers", "class_name": "Dense", "config": {"name": "dense_9", "trainable": true, "dtype": "float32", "units": 10, "activation": "relu", "use_bias": true, "kernel_initializer": {"module": "keras.initializers", "class_name": "GlorotUniform", "config": {"seed": null}, "registered_name": null}, "bias_initializer": {"module": "keras.initializers", "class_name": "Zeros", "config": {}, "registered_name": null}, "kernel_regularizer": null, "bias_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "registered_name": null, "build_config": {"input_shape": [null, 2]}}, {"module": "keras.layers", "class_name": "Dense", "config": {"name": "dense_10", "trainable": true, "dtype": "float32", "units": 10, "activation": "relu", "use_bias": true, "kernel_initializer": {"module": "keras.initializers", "class_name": "GlorotUniform", "config": {"seed": null}, "registered_name": null}, "bias_initializer": {"module": "keras.initializers", "class_name": "Zeros", "config": {}, "registered_name": null}, "kernel_regularizer": null, "bias_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "registered_name": null, "build_config": {"input_shape": [null, 10]}}, {"module": "keras.layers", "class_name": "Dense", "config": {"name": "dense_11", "trainable": true, "dtype": "float32", "units": 2, "activation": "linear", "use_bias": true, "kernel_initializer": {"module": "keras.initializers", "class_name": "GlorotUniform", "config": {"seed": null}, "registered_name": null}, "bias_initializer": {"module": "keras.initializers", "class_name": "Zeros", "config": {}, "registered_name": null}, "kernel_regularizer": null, "bias_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "registered_name": null, "build_config": {"input_shape": [null, 10]}}], "build_input_shape": [null, 2]}, "registered_name": null, "build_config": {"input_shape": [null, 2]}, "compile_config": {"optimizer": {"module": "keras.optimizers", "class_name": "Adam", "config": {"name": "adam", "learning_rate": 0.0010000000474974513, "weight_decay": null, "clipnorm": null, "global_clipnorm": null, "clipvalue": null, "use_ema": false, "ema_momentum": 0.99, "ema_overwrite_frequency": null, "loss_scale_factor": null, "gradient_accumulation_steps": null, "beta_1": 0.9, "beta_2": 0.999, "epsilon": 1e-07, "amsgrad": false}, "registered_name": null}, "loss": "mse", "loss_weights": null, "metrics": null, "weighted_metrics": null, "run_eagerly": false, "steps_per_execution": 1, "jit_compile": false}}
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"class_name": "Sequential", "config": {"name": "PT_data_2_10_10_2_sigmoid", "layers": [{"class_name": "InputLayer", "config": {"batch_input_shape": [null, 2], "dtype": "float32", "sparse": false, "ragged": false, "name": "dense_6_input"}}, {"class_name": "Dense", "config": {"name": "dense_6", "trainable": true, "batch_input_shape": [null, 2], "dtype": "float32", "units": 10, "activation": "sigmoid", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "Dense", "config": {"name": "dense_7", "trainable": true, "dtype": "float32", "units": 10, "activation": "sigmoid", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "Dense", "config": {"name": "dense_8", "trainable": true, "dtype": "float32", "units": 2, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}]}, "keras_version": "2.7.0", "backend": "tensorflow"}
{"module": "keras", "class_name": "Sequential", "config": {"name": "PT_data_2_10_10_2_sigmoid", "trainable": true, "dtype": "float32", "layers": [{"module": "keras.layers", "class_name": "InputLayer", "config": {"batch_shape": [null, 2], "dtype": "float32", "sparse": false, "name": "input_layer_2"}, "registered_name": null}, {"module": "keras.layers", "class_name": "Dense", "config": {"name": "dense_6", "trainable": true, "dtype": "float32", "units": 10, "activation": "sigmoid", "use_bias": true, "kernel_initializer": {"module": "keras.initializers", "class_name": "GlorotUniform", "config": {"seed": null}, "registered_name": null}, "bias_initializer": {"module": "keras.initializers", "class_name": "Zeros", "config": {}, "registered_name": null}, "kernel_regularizer": null, "bias_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "registered_name": null, "build_config": {"input_shape": [null, 2]}}, {"module": "keras.layers", "class_name": "Dense", "config": {"name": "dense_7", "trainable": true, "dtype": "float32", "units": 10, "activation": "sigmoid", "use_bias": true, "kernel_initializer": {"module": "keras.initializers", "class_name": "GlorotUniform", "config": {"seed": null}, "registered_name": null}, "bias_initializer": {"module": "keras.initializers", "class_name": "Zeros", "config": {}, "registered_name": null}, "kernel_regularizer": null, "bias_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "registered_name": null, "build_config": {"input_shape": [null, 10]}}, {"module": "keras.layers", "class_name": "Dense", "config": {"name": "dense_8", "trainable": true, "dtype": "float32", "units": 2, "activation": "linear", "use_bias": true, "kernel_initializer": {"module": "keras.initializers", "class_name": "GlorotUniform", "config": {"seed": null}, "registered_name": null}, "bias_initializer": {"module": "keras.initializers", "class_name": "Zeros", "config": {}, "registered_name": null}, "kernel_regularizer": null, "bias_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "registered_name": null, "build_config": {"input_shape": [null, 10]}}], "build_input_shape": [null, 2]}, "registered_name": null, "build_config": {"input_shape": [null, 2]}, "compile_config": {"optimizer": {"module": "keras.optimizers", "class_name": "Adam", "config": {"name": "adam", "learning_rate": 0.0010000000474974513, "weight_decay": null, "clipnorm": null, "global_clipnorm": null, "clipvalue": null, "use_ema": false, "ema_momentum": 0.99, "ema_overwrite_frequency": null, "loss_scale_factor": null, "gradient_accumulation_steps": null, "beta_1": 0.9, "beta_2": 0.999, "epsilon": 1e-07, "amsgrad": false}, "registered_name": null}, "loss": "mse", "loss_weights": null, "metrics": null, "weighted_metrics": null, "run_eagerly": false, "steps_per_execution": 1, "jit_compile": false}}
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"class_name": "Sequential", "config": {"name": "T_data_1_10_10_2_relu", "layers": [{"class_name": "InputLayer", "config": {"batch_input_shape": [null, 1], "dtype": "float32", "sparse": false, "ragged": false, "name": "dense_3_input"}}, {"class_name": "Dense", "config": {"name": "dense_3", "trainable": true, "batch_input_shape": [null, 1], "dtype": "float32", "units": 10, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "Dense", "config": {"name": "dense_4", "trainable": true, "dtype": "float32", "units": 10, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "Dense", "config": {"name": "dense_5", "trainable": true, "dtype": "float32", "units": 2, "activation": "linear", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}]}, "keras_version": "2.7.0", "backend": "tensorflow"}
{"module": "keras", "class_name": "Sequential", "config": {"name": "T_data_1_10_10_2_relu", "trainable": true, "dtype": "float32", "layers": [{"module": "keras.layers", "class_name": "InputLayer", "config": {"batch_shape": [null, 1], "dtype": "float32", "sparse": false, "name": "input_layer_1"}, "registered_name": null}, {"module": "keras.layers", "class_name": "Dense", "config": {"name": "dense_3", "trainable": true, "dtype": "float32", "units": 10, "activation": "relu", "use_bias": true, "kernel_initializer": {"module": "keras.initializers", "class_name": "GlorotUniform", "config": {"seed": null}, "registered_name": null}, "bias_initializer": {"module": "keras.initializers", "class_name": "Zeros", "config": {}, "registered_name": null}, "kernel_regularizer": null, "bias_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "registered_name": null, "build_config": {"input_shape": [null, 1]}}, {"module": "keras.layers", "class_name": "Dense", "config": {"name": "dense_4", "trainable": true, "dtype": "float32", "units": 10, "activation": "relu", "use_bias": true, "kernel_initializer": {"module": "keras.initializers", "class_name": "GlorotUniform", "config": {"seed": null}, "registered_name": null}, "bias_initializer": {"module": "keras.initializers", "class_name": "Zeros", "config": {}, "registered_name": null}, "kernel_regularizer": null, "bias_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "registered_name": null, "build_config": {"input_shape": [null, 10]}}, {"module": "keras.layers", "class_name": "Dense", "config": {"name": "dense_5", "trainable": true, "dtype": "float32", "units": 2, "activation": "linear", "use_bias": true, "kernel_initializer": {"module": "keras.initializers", "class_name": "GlorotUniform", "config": {"seed": null}, "registered_name": null}, "bias_initializer": {"module": "keras.initializers", "class_name": "Zeros", "config": {}, "registered_name": null}, "kernel_regularizer": null, "bias_regularizer": null, "kernel_constraint": null, "bias_constraint": null}, "registered_name": null, "build_config": {"input_shape": [null, 10]}}], "build_input_shape": [null, 1]}, "registered_name": null, "build_config": {"input_shape": [null, 1]}, "compile_config": {"optimizer": {"module": "keras.optimizers", "class_name": "Adam", "config": {"name": "adam", "learning_rate": 0.0010000000474974513, "weight_decay": null, "clipnorm": null, "global_clipnorm": null, "clipvalue": null, "use_ema": false, "ema_momentum": 0.99, "ema_overwrite_frequency": null, "loss_scale_factor": null, "gradient_accumulation_steps": null, "beta_1": 0.9, "beta_2": 0.999, "epsilon": 1e-07, "amsgrad": false}, "registered_name": null}, "loss": "mse", "loss_weights": null, "metrics": null, "weighted_metrics": null, "run_eagerly": false, "steps_per_execution": 1, "jit_compile": false}}
Binary file not shown.
Binary file not shown.
Loading
Loading