-
Notifications
You must be signed in to change notification settings - Fork 6
fix: Avoid deep copying in ModelContainer to resolve pickling errors #559
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
base: main
Are you sure you want to change the base?
fix: Avoid deep copying in ModelContainer to resolve pickling errors #559
Conversation
Hi @laksi1999 Thanks for the PR contribution. I will take a look at the PR together with the team. |
Hi @laksi1999, can I check if you have sample non-serialisable objects to provide for testing this PR? Also, would like to check if this is run via the Notebook and CLI Standalone Plugin? |
Unit Test for Veritas Passed Veritas CLI Ran Successfully Veritas CLI Docker Ran Successfully Veritas Example Notebooks Ran Successfully |
@imda-benedictlee Thanks for reviewing the PR. I’ve attached a notebook that reproduces the error encountered when calling In this notebook, I used a MOJO model. I’ve also included the corresponding model file and the datasets used. Please see the attached Veritas_artifacts.zip However, since you won’t be able to test the MOJO model in your environment due to authentication restrictions, I’ve also attached a scikit-learn model for testing purposes. Along with that, I’ve included two notebooks:
Please see the attached Veritas_artifacts_scikit_learn.zip for the artifacts. |
Hi @laksi1999, thanks for the help on this. I will take a look and review the PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The leave one out calculation in the feature importance method uses a ThreadPoolExecutor
to run multiple threads concurrently, each analysing a different protected variable. Without deep copying there might be race conditions.
I get that allowing a model_objects
field would bypass the serialization but it introduces other issues:
- How do we know the number of
model_objects
to pass? - The second thread onwards gets a different
model_object
or fallback to deepcopy - There might also be a race condition with multiple threads calling
pop
on the same list.
Open to suggestions on how to avoid serialization but we need to create multiple identical copies for parallel processing, not to manage a pool of different model objects.
model_obj = getattr(model_param, "model_object", None) | ||
if hasattr(model_param, 'model_objects') and model_param.model_objects: | ||
model_object = model_param.model_objects.pop(0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is passed in model_objects
? How do we ensure that there is a sufficient number of model_objects
to for the threads to access?
@timlrx Based on your feedback, I propose using a lightweight ModelObjectsWrapper, which provides a pop() method that loads a new model instance from disk on demand.
For example, We can use it like below:
Why This Approach Solves the Problem:
I’ve attached the notebook with the current solution. veritas_with_iris_dataset_with_success.zip The pop method uses an index because the earlier implementation relied on index. If the current proposal makes sense, I can simplify the code by using pop() and removing the index logic. Please let me know your thoughts on this. |
Description
This pull request introduces a new
model_objects
parameter in theModelContainer
class, allowing users to pass pre-created model objects directly. The primary change eliminates the need for deep copyingmodel_object
, which previously caused"cannot pickle"
errors when dealing with non-serializable objects, such as those from Driverless AI. Instead, the updated implementation checks for amodel_objects
list and assigns a model instance from it, ensuring seamless integration with existing tools.Motivation and Context
The original implementation relied on deep copying experiment objects, leading to serialization issues when handling non-picklable objects. This limitation prevented users from effectively integrating their models, particularly when using community-standard tools. By introducing the
model_objects
parameter, this update resolves the serialization issue while maintaining backward compatibility with the existing singlemodel_object
approach.Type of Change
fix: A bug fix
How to Test
ModelContainer
instance including themodel_object
parameter along with the newmodel_objects
parameter with a pre-created list ofmodel_object
objects.ModelContainer
instance."cannot pickle"
errors occur when interacting with Driverless AI objects.model_object
without themodel_objects
parameter.Checklist
Please check all the boxes that apply to this pull request using "x":
Screenshots (if applicable)
N/A
Additional Notes
This change ensures that non-picklable objects can be utilized without requiring workarounds, improving compatibility with community tools and frameworks.
Developer Certificate of Origin