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

Support dump and load timm and hf_text models on MultiModalPredictor #2682

Merged
merged 6 commits into from
Jan 18, 2023

Conversation

suzhoum
Copy link
Contributor

@suzhoum suzhoum commented Jan 12, 2023

Issue #, if available:

Description of changes:

  1. Added APIs to dump timm_image and hf_text models
  2. Added support to load model from path for timm_image

Usage:

To dump models from fine-tuned MultiModalPredictor:

  MultiModalPredictor.dump_timm_image(PATH_TO_MODEL)
  MultiModalPredictor.dump_hf_text(PATH_TO_MODEL)

To load models from saved model path:

hyperparameters = {
     "model.hf_text.checkpoint_name": PATH_TO_SAVED_HF_TEXT_MODEL,
     "model.timm_image.checkpoint_name": PATH_TO_SAVED_TIMM_IMAGE_MODEL,
} 

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@github-actions
Copy link

Job PR-2682-1adf0a6 is done.
Docs are uploaded to http://autogluon-staging.s3-website-us-west-2.amazonaws.com/PR-2682/1adf0a6/index.html

Comment on lines 2835 to 2841
if isinstance(self._model, MultimodalFusionMLP) and isinstance(
self._model.model, torch.nn.modules.container.ModuleList
):
for per_model in self._model.model:
if isinstance(per_model, TimmAutoModelForImagePrediction):
model = per_model
break
Copy link
Contributor

Choose a reason for hiding this comment

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

Saving a timm image backbone from a fusion model seems not useful since it can't work individually. We can consider only deal with single timm model for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We considered the scenario for fusion model because there might be a use case that a user wants to save specifically timm_image or hf_text from the fusion model trained to use on other downstream tasks which only use a single model. Do you feel that would be useful?

Copy link
Collaborator

Choose a reason for hiding this comment

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

For example, people trained on the mixture of image, text, tabular data, and like to extract the image part from the fusion model. The API “predictor.dump_timm_image” should still work in this case.

Copy link
Contributor

Choose a reason for hiding this comment

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

This logic has the limitation that, If multiple timm image models are available, it would only dump the first one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've updated the logic to support saving multiple models under timm_image and hf_text.

Comment on lines 2868 to 2875
model = None
if isinstance(self._model, MultimodalFusionMLP) and isinstance(
self._model.model, torch.nn.modules.container.ModuleList
):
for per_model in self._model.model:
if isinstance(per_model, HFAutoModelForTextPrediction):
model = per_model
break
Copy link
Contributor

Choose a reason for hiding this comment

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

Ditto. We can consider only the single huggingface text model for now.

os.makedirs(path)
model.model.save_pretrained(path)
logger.info(f"Model saved to {path}.")
if TEXT in self._data_processors.keys():
Copy link
Contributor

Choose a reason for hiding this comment

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

For hf_text model, we can assert self._data_processors have only one text processor.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you mean there is no need to check the prefix of the data processor to get the tokenizer?

Copy link
Contributor

Choose a reason for hiding this comment

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

Since we consider dumping a hf model from a fusion model, this logic is OK.

Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need raise error if there is no hf model available?

@@ -2812,6 +2817,79 @@ def load(

return predictor

def dump_timm_image(
Copy link
Contributor

Choose a reason for hiding this comment

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

There would be too many APIs if each model has a dump function. How about using only one API dump_model()? Inside the function, we can check the model type is timm image or hf text.

return filtered_cfg


def save_timm_config(
Copy link
Contributor

Choose a reason for hiding this comment

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

docstrings are missing.


model = self._model if model is None else model
if isinstance(model, HFAutoModelForTextPrediction) and model.model is not None:
os.makedirs(path)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Try to use “os.makedirs(path, exist_ok=True)”.

Copy link
Contributor Author

@suzhoum suzhoum Jan 13, 2023

Choose a reason for hiding this comment

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

I originally had this flag set, but after discussing with Zhiqiang offline, he suggested that we might not want to save to an existing (or non-empty) directory to avoid accidentally overwriting the model.

@suzhoum suzhoum force-pushed the continual_learning branch 2 times, most recently from ce8ebb7 to 303d91d Compare January 17, 2023 19:57
@github-actions
Copy link

Job PR-2682-303d91d is done.
Docs are uploaded to http://autogluon-staging.s3-website-us-west-2.amazonaws.com/PR-2682/303d91d/index.html

@github-actions
Copy link

Job PR-2682-b289c4a is done.
Docs are uploaded to http://autogluon-staging.s3-website-us-west-2.amazonaws.com/PR-2682/b289c4a/index.html

@@ -523,3 +524,47 @@ def modify_duplicate_model_names(

def list_timm_models(pretrained=True):
return timm.list_models(pretrained=pretrained)


def _filter_timm_pretrained_cfg(cfg, remove_source=False, remove_null=True):
Copy link
Contributor

Choose a reason for hiding this comment

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

Since _filter_timm_pretrained_cfg and save_timm_config are about config, is it better to put them into utils/config.py?

timm_image_dir = f"{model_dump_path}/timm_image"
assert os.path.exists(hf_text_dir) and (len(os.listdir(hf_text_dir)) > 2) == True
assert os.path.exists(timm_image_dir) and (len(os.listdir(timm_image_dir)) == 2) == True
print("done")
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove print?

path : str
Path to directory where models and configs should be saved.
"""
models = {}
Copy link
Contributor

Choose a reason for hiding this comment

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

models are list and dict in dump_timm_image and dump_hf_text , respectively. Can we use list for both of them?

Path to directory where models and configs should be saved.
"""
models = []
if isinstance(self._model, MultimodalFusionMLP) and isinstance(
Copy link
Contributor

Choose a reason for hiding this comment

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

A fusion model may also be MultimodalFusionTransformer.

@github-actions
Copy link

Job PR-2682-f7801b7 is done.
Docs are uploaded to http://autogluon-staging.s3-website-us-west-2.amazonaws.com/PR-2682/f7801b7/index.html

Copy link
Contributor

@zhiqiangdon zhiqiangdon left a comment

Choose a reason for hiding this comment

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

LGTM! Awesome feature! Consider unifying the dumping functions into one API in follow-up PRs.

Path to directory where models and configs should be saved.
"""
models = []
if isinstance(self._model, (MultimodalFusionMLP, MultimodalFusionTransformer)) and isinstance(
Copy link
Collaborator

Choose a reason for hiding this comment

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

@zhiqiangdon We can later add a BaseMultimodalFusionModel class, and ensure that MultimodalFusionMLP and MultimodalFusionTransformer inherit from this class.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@suzhoum May be we can add a TODO item here

Copy link
Contributor

Choose a reason for hiding this comment

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

Sure. We can add a base class.

@@ -679,3 +681,104 @@ def test_image_bytearray():
npt.assert_array_equal(
[prediction_prob_1, prediction_prob_2, prediction_prob_3, prediction_prob_4], [prediction_prob_1] * 4
)


def test_dump_timm_image():
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we separate these tests to another file? The reason is that test_predictor.py is growing to be too huge and too slow.

We can consider to add it under the following name

unittests/predictor/test_predictor_dump_third_party.py

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea. Done!

Copy link
Collaborator

@sxjscience sxjscience left a comment

Choose a reason for hiding this comment

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

Two minor comments!! Overall LGTM!!!! Thanks!!!

@github-actions
Copy link

Job PR-2682-771fb04 is done.
Docs are uploaded to http://autogluon-staging.s3-website-us-west-2.amazonaws.com/PR-2682/771fb04/index.html

@suzhoum suzhoum merged commit ab0f8cf into autogluon:master Jan 18, 2023
@suzhoum suzhoum added this to the 0.7 Release milestone Feb 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants