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

Machine Learning & Artificial Intelligence Plugin #995

Merged
merged 51 commits into from
Mar 3, 2022
Merged
Changes from 1 commit
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
1ee728c
ML_AI plugin first draft
bpaul4 Oct 27, 2021
6ba10cf
Updated init/run methods, updated nodePanel/Ui for new model type
bpaul4 Oct 28, 2021
5f4044c
Fixed typing error
bpaul4 Oct 29, 2021
5c98bbc
Updated nodePanel and session methods for pymodel search
bpaul4 Oct 29, 2021
a0a55eb
Addressed pytest errors
bpaul4 Oct 29, 2021
937d02d
Added modelType, modelName and load_model connections to UI
bpaul4 Nov 1, 2021
5f75eff
Keras object and layer import, redefined pymodel local variables
bpaul4 Nov 1, 2021
760dced
Fixed output variable indexing
bpaul4 Nov 2, 2021
43f2c03
Allow plugin to import models with new name, no custom layer or no la…
bpaul4 Dec 1, 2021
22f695c
Resolving merge conflicts from master
bpaul4 Dec 1, 2021
987de2a
ML AI Plugin documentation first draft
bpaul4 Dec 6, 2021
913775b
Added normalization functionality, examples, updated documentation
bpaul4 Dec 15, 2021
a993b53
Minor documentation fixes
bpaul4 Dec 15, 2021
d426155
Merge branch 'CCSI-Toolset:master' into ml_ai_plugin
bpaul4 Jan 4, 2022
a7140be
Merge branch 'master' of https://github.com/CCSI-Toolset/FOQUS into m…
bpaul4 Jan 5, 2022
064fd28
Improvements from testing
bpaul4 Jan 10, 2022
696ec0c
Running black from main directory
bpaul4 Jan 10, 2022
a24f624
Minor fixes for pylint checks
bpaul4 Jan 10, 2022
b8614da
Merge branch 'ml_ai_plugin' of https://github.com/bpaul4/FOQUS into m…
bpaul4 Jan 10, 2022
3dd03c8
Minor formatting fix
bpaul4 Jan 12, 2022
182a526
Merge branch 'master' into ml_ai_plugin
bpaul4 Jan 20, 2022
2ddd67f
Renaming image files and extensions
bpaul4 Feb 8, 2022
06fafd4
Merge branch 'ml_ai_plugin' of https://github.com/bpaul4/FOQUS into m…
bpaul4 Feb 8, 2022
3be6605
Add GUI tests for ML/AI plugin
lbianchi-lbl Feb 11, 2022
eaf6b0b
Skip ML/AI tests if tensorflow is not installed
lbianchi-lbl Feb 11, 2022
f2e4099
Run Black
lbianchi-lbl Feb 11, 2022
0942f95
Add pylint directives around import guard for tensorflow
lbianchi-lbl Feb 11, 2022
bc2877f
Install tensorflow in a subset of the environments
lbianchi-lbl Feb 11, 2022
8a21625
Fix args for pytest.importorskip()
lbianchi-lbl Feb 11, 2022
4f62e2f
Install tensorflow from conda-forge for Python>3.7 on macOS
lbianchi-lbl Feb 11, 2022
90e7370
Use pip instead of conda to install tensorflow
lbianchi-lbl Feb 12, 2022
ae5f75a
Move copying of ML/AI model files out of pytest
lbianchi-lbl Feb 12, 2022
3cac6c4
Run Black
lbianchi-lbl Feb 12, 2022
0aa924d
Disable pytest job dependency while WIP
lbianchi-lbl Feb 12, 2022
4b0fec3
Try if the matrix syntax is causing the job to be ignored
lbianchi-lbl Feb 12, 2022
0f184b3
Try narrowing scope of `foqus_session` fixture to "module"
lbianchi-lbl Feb 12, 2022
867ce73
Try creating a separate session and working dir for each test module
lbianchi-lbl Feb 12, 2022
141995c
Try waiting for signals instead of dealing with modals
lbianchi-lbl Feb 15, 2022
db01acc
Avoid showing UQ dialog
lbianchi-lbl Feb 15, 2022
f96d09b
Try using open() instead of show() for analysis dialog issue on macOS
lbianchi-lbl Feb 15, 2022
a46fa00
Revert "Try waiting for signals instead of dealing with modals"
lbianchi-lbl Feb 15, 2022
dd9beb8
Try using open() instead of exec() for modal dialog
lbianchi-lbl Feb 16, 2022
b9a8d39
Merge branch 'master' into ml_ai_plugin
bpaul4 Feb 22, 2022
359f1d9
Merge branch 'master' into ml_ai_plugin
bpaul4 Feb 22, 2022
98af321
Merge remote-tracking branch 'bpaul4/ml_ai_plugin' into ml_ai_plugin
lbianchi-lbl Feb 23, 2022
45cd78d
Restore job dependency
lbianchi-lbl Feb 23, 2022
bc32a0c
Merge pull request #1 from lbianchi-lbl/ml_ai_plugin
bpaul4 Feb 24, 2022
a4799af
Improving exception handling
bpaul4 Mar 2, 2022
285df23
Running black again
bpaul4 Mar 2, 2022
25c6226
Minor changes
bpaul4 Mar 2, 2022
71e9586
Merge branch 'master' into ml_ai_plugin
bpaul4 Mar 2, 2022
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
81 changes: 67 additions & 14 deletions foqus_lib/framework/graph/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,12 @@
import tensorflow as tf

load = tf.keras.models.load_model
except:
pass # errors will be thrown if tensorflow is called but not installed,
# otherwise no error should be thrown so passing is fine
except ImportError:
# if TensorFlow is not available, create a proxy function that will raise
# an exception whenever code tries to use `load()` at runtime
def load(*args, **kwargs):
raise RuntimeError(f"`load()` was called with args={args},"
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor suggestion, but in retrospective ModuleNotFoundError would be a better fit than RuntimeError here.

"kwargs={kwargs} but `tensorflow` is not available")
# pylint: enable=import-error


Expand Down Expand Up @@ -106,15 +109,33 @@ def __init__(self, model):
for i in range(np.shape(self.model.inputs[0])[1]):
try:
input_label = self.model.layers[1].input_labels[i]
except:
except AttributeError:
logging.getLogger("foqus." + __name__).info(
Copy link
Contributor

Choose a reason for hiding this comment

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

I think these extended messages are great, they add lots of useful context both for users and other developers.

One minor suggestion: instead of repeating the logging.getLogger("foqus." + __name__) each time, you could create a logger object at the module level, e.g. _logger = logging.getLogger("foqus." + __name__) after the import statements on Line 40, and then use that object throughout the rest of the module, i.e. _logger.info(...)

"Model has no attribute input_label, using default x"
+ str(i + 1) + ". If attribute should exist, check that "
+ "Tensorflow Keras model was correctly saved with "
+ "CustomLayer. Otherwise, this is not an error and model "
+ "will load " + "as expected using default attributes.")
input_label = "x" + str(i + 1)
try:
input_min = self.model.layers[1].input_bounds[input_label][0]
except:
except AttributeError:
logging.getLogger("foqus." + __name__).info(
"Model has no attribute input_min, using default 0"
+ ". If attribute should exist, check that "
+ "Tensorflow Keras model was correctly saved with "
+ "CustomLayer. Otherwise, this is not an error and model "
+ "will load as expected using default attributes.")
input_min = 0 # not necessarily a good default
try:
input_max = self.model.layers[1].input_bounds[input_label][1]
except:
except AttributeError:
logging.getLogger("foqus." + __name__).info(
"Model has no attribute input_max, using default 1E5"
+ ". If attribute should exist, check that "
+ "Tensorflow Keras model was correctly saved with "
+ "CustomLayer. Otherwise, this is not an error and model "
+ "will load as expected using default attributes.")
input_max = 1e5 # not necessarily a good default

self.inputs[input_label] = NodeVars(
Expand All @@ -132,15 +153,33 @@ def __init__(self, model):
for j in range(np.shape(self.model.outputs[0])[1]):
try:
output_label = self.model.layers[1].output_labels[j]
except:
except AttributeError:
logging.getLogger("foqus." + __name__).info(
"Model has no attribute output_label, using default z"
+ str(j + 1) + ". If attribute should exist, check that "
+ "Tensorflow Keras model was correctly saved with "
+ "CustomLayer. Otherwise, this is not an error and model "
+ "will load as expected using default attributes.")
output_label = "z" + str(j + 1)
try:
output_min = self.model.layers[1].output_bounds[output_label][0]
except:
except AttributeError:
logging.getLogger("foqus." + __name__).info(
"Model has no attribute output_min, using default 0"
+ ". If attribute should exist, check that "
+ "Tensorflow Keras model was correctly saved with "
+ "CustomLayer. Otherwise, this is not an error and model "
+ "will load as expected using default attributes.")
output_min = 0 # not necessarily a good default
try:
output_max = self.model.layers[1].output_bounds[output_label][1]
except:
except AttributeError:
logging.getLogger("foqus." + __name__).info(
"Model has no attribute output_max, using default 1E5"
+ ". If attribute should exist, check that "
+ "Tensorflow Keras model was correctly saved with "
+ "CustomLayer. Otherwise, this is not an error and model "
+ "will load as expected using default attributes.")
output_max = 1e5 # not necessarily a good default

self.outputs[output_label] = NodeVars(
Expand All @@ -158,7 +197,13 @@ def __init__(self, model):
# check if user passed a model for normalized data - FOQUS will automatically scale/un-scale
try: # if attribute exists, user has specified a model form
self.normalized = self.model.layers[1].normalized
except: # otherwise user did not pass a normalized model
except AttributeError: # otherwise user did not pass a normalized model
logging.getLogger("foqus." + __name__).info(
"Model has no attribute normalized, using default False"
+ ". If attribute should exist, check that "
+ "Tensorflow Keras model was correctly saved with "
+ "CustomLayer. Otherwise, this is not an error and model "
+ "will load as expected using default attributes.")
self.normalized = False

def run(self):
Expand Down Expand Up @@ -604,9 +649,13 @@ def setSim(self, newType=None, newModel=None, force=False, ids=None):
str(self.modelName): getattr(module, str(self.modelName))
},
)
except: # try to load model without custom layer
except ImportError: # try to load model without custom layer
logging.getLogger("foqus." + __name__).info(
"Cannot detect CustomLayer object to import, FOQUS "
+ "will import model without custom attributes.")
self.model = load(str(self.modelName) + ".h5")
os.chdir(cwd) # reset to original working directory
finally:
os.chdir(cwd) # reset to original working directory
inst = pymodel_ml_ai(self.model)
for vkey, v in inst.inputs.items():
self.gr.input[self.name][vkey] = v
Expand Down Expand Up @@ -1106,9 +1155,13 @@ def runPymodelMLAI(self):
str(self.modelName): getattr(module, str(self.modelName))
},
)
except: # try to load model without custom layer
except ImportError: # try to load model without custom layer
logging.getLogger("foqus." + __name__).info(
"Cannot detect CustomLayer object to import, FOQUS "
+ "will import model without custom attributes.")
self.model = load(str(self.modelName) + ".h5")
os.chdir(cwd) # reset to original working directory
finally:
os.chdir(cwd) # reset to original working directory
self.pyModel = pymodel_ml_ai(self.model)
# set the instance inputs
for vkey, v in self.gr.input[self.name].items():
Expand Down