autogluon / autogluon/autogluon
[BUG] MultiModalPredictor
- Dominant language
- Python
- Stars
- 10.7k
- Forks
- 1.2k
- Avg merge
- 21h 29m
- Merged PRs (30d)
- 57
Description
**Bug Report Checklist**
- [X] I provided code that demonstrates a minimal reproducible example.
- [X] I confirmed bug exists on the latest mainline of AutoGluon via source install.
- [ ] I confirmed bug exists on the latest stable version of AutoGluon.
**Describe the bug**
When fitting the MultiModalPredictor it fails with ```KeyError: 'document_transformer_text_valid_length'```. Consultation with Haoyang Fang led to a suggested cause that the given input (map images) are being incorrectly classified as documents, hence that model fails. This issue was resolved when avoiding use of the DocumentTransformer by adding hyperparameters ```hyperparameters = {
"model.names": ["hf_text", "timm_image", "ft_transformer", "fusion_mlp"]
}```.
**Expected behavior**
I expected for the DocumentTransformer to be skipped. I expected that the input_vec creation (```input_vec = [batch[k] for k in pure_model.input_keys]```) would be checked for safety since one dictionary could contain keys that are not in the other dictionary. I also expected that the documentation for the MultiModalPredictor and fit function would be able to guide me if I wanted to use hyperparameters to set which models are options (and therefore avoid this issue), but documentation did not have enough detail for that.
**To Reproduce**
```python
from autogluon.multimodal import MultiModalPredictor
import pandas as pd
def make_minimal_df(image_folder_location):
data=pd.DataFrame()
data['title__title']=['hi']*9+['bye']*9
data=data.reset_index(names='counter')
data['map_image']=data['counter'].apply(lambda x: f'{image_folder_location}/test_img_{x}.png')
return data
def failing_code(image_folder_location, path_to_save_model):
mdl=MultiModalPredictor(label='title__title', path=path_to_save_model)
mdl.fit(make_minimal_df(image_folder_location))
failing_code(,)
```
**Screenshots / Logs**
```=================== System Info ===================
AutoGluon Version: 1.4.0
Python Version: 3.11.10
Operating System: Linux
Platform Machine: x86_64
Platform Version: #1 SMP Thu Aug 7 19:38:22 UTC 2025
CPU Count: 64
Pytorch Version: 2.5.1+cu124
CUDA Version: CUDA is not available
GPU Count: 0
Memory Avail: 217.00 GB / 247.71 GB (87.6%)
Disk Space Avail: 1108.90 GB / 1968.52 GB (56.3%)
===================================================
AutoGluon infers your prediction problem is: 'binary' (because only two unique label-values observed).
2 unique label values: ['hi', 'bye']
If 'binary' is not the correct problem_type, please manually specify the problem_type parameter during Predictor init (You may specify problem_type as one of: ['binary', 'multiclass', 'regression', 'quantile'])
AutoMM starts to create your model. ✨✨✨
To track the learning progress, you can open a terminal and launch Tensorboard:
```shell
# Assume you have installed tensorboard
tensorboard --logdir /sleuth/mre/mdl
```
Seed set to 0
The model does not support using an image size that is different from the default size. Provided image size=224. Default size=None. Detailed model configuration=LayoutLMv3Config {
"_name_or_path": "microsoft/layoutlmv3-base",
"attention_probs_dropout_prob": 0.1,
"bos_token_id": 0,
"classifier_dropout": null,
"coordinate_size": 128,
"eos_token_id": 2,
"has_relative_attention_bias": true,
"has_spatial_attention_bias": true,
"hidden_act": "gelu",
"hidden_dropout_prob": 0.1,
"hidden_size": 768,
"initializer_range": 0.02,
"input_size": 224,
"intermediate_size": 3072,
"layer_norm_eps": 1e-05,
"max_2d_position_embeddings": 1024,
"max_position_embeddings": 514,
"max_rel_2d_pos": 256,
"max_rel_pos": 128,
"model_type": "layoutlmv3",
"num_attention_heads": 12,
"num_channels": 3,
"num_hidden_layers": 12,
"pad_token_id": 1,
"patch_size": 16,
"rel_2d_pos_bins": 64,
"rel_pos_bins": 32,
"second_input_size": 112,
"shape_size": 128,
"text_embed": true,
"torch_dtype": "float32",
"transformers_version": "4.49.0",
"type_vocab_size": 1,
"visual_embed": true,
"vocab_size": 50265
}
. We have ignored the provided image size.
GPU Count: 0
GPU Count to be Used: 0
/opt/conda/lib/python3.11/site-packages/autogluon/multimodal/utils/precision.py:71: UserWarning: Only CPU is detected in the instance. This may result in slow speed for MultiModalPredictor. Consider using an instance with GPU support.
warnings.warn(
GPU available: False, used: False
TPU available: False, using: 0 TPU cores
HPU available: False, using: 0 HPUs
| Name | Type | Params | Mode
------------------------------------------------------------------
0 | model | MultimodalFusionMLP | 127 M | train
1 | validation_metric | BinaryAUROC | 0 | train
2 | loss_func | CrossEntropyLoss | 0 | train
------------------------------------------------------------------
127 M Trainable params
0 Non-trainable params
127 M Total params
508.344 Total estimated model params size (MB)
319 Modules in train mode
0 Modules in eval mode
Sanity Checking DataLoader 0: 0%| | 0/1 [00:00 1 failing_code('sleuth/mre/img','sleuth/mre/mdl')
Cell In[10], line 11, in failing_code(image_folder_location, path_to_save_model)
9 def failing_code(image_folder_location, path_to_save_model):
10 mdl=MultiModalPredictor(label='title__title', path=path_to_save_model)
---> 11 mdl.fit(make_minimal_df(image_folder_location))
File /opt/conda/lib/python3.11/site-packages/autogluon/multimodal/predictor.py:540, in MultiModalPredictor.fit(self, train_data, presets, tuning_data, max_num_tuning_data, id_mappings, time_limit, save_path, hyperparameters, column_types, holdout_frac, teacher_predictor, seed, standalone, hyperparameter_tune_kwargs, clean_ckpts, predictions, labels, predictors)
537 assert isinstance(predictors, list)
538 learners = [ele if isinstance(ele, str) else ele._learner for ele in predictors]
--> 540 self._learner.fit(
541 train_data=train_data,
542 presets=presets,
543 tuning_data=tuning_data,
544 max_num_tuning_data=max_num_tuning_data,
545 time_limit=time_limit,
546 save_path=save_path,
547 hyperparameters=hyperparameters,
548 column_types=column_types,
549 holdout_frac=holdout_frac,
550 teacher_learner=teacher_learner,
551 seed=seed,
552 standalone=standalone,
553 hyperparameter_tune_kwargs=hyperparameter_tune_kwargs,
554 clean_ckpts=clean_ckpts,
555 id_mappings=id_mappings,
556 predictions=predictions,
557 labels=labels,
558 learners=learners,
559 )
561 return self
File /opt/conda/lib/python3.11/site-packages/autogluon/multimodal/learners/base.py:665, in BaseLearner.fit(self, train_data, presets, tuning_data, time_limit, save_path, hyperparameters, column_types, holdout_frac, teacher_learner, seed, standalone, hyperparameter_tune_kwargs, clean_ckpts, **kwargs)
658 self.fit_sanity_check()
659 self.prepare_fit_args(
660 time_limit=time_limit,
661 seed=seed,
662 standalone=standalone,
663 clean_ckpts=clean_ckpts,
664 )
--> 665 fit_returns = self.execute_fit()
666 self.on_fit_end(
667 training_start=training_start,
668 strategy=fit_returns.get("strategy", None),
(...) 671 clean_ckpts=clean_ckpts,
672 )
674 return self
File /opt/conda/lib/python3.11/site-packages/autogluon/multimodal/learners/base.py:577, in BaseLearner.execute_fit(self)
575 return dict()
576 else:
--> 577 attributes = self.fit_per_run(**self._fit_args)
578 self.update_attributes(**attributes) # only update attributes for non-HPO mode
579 return attributes
File /opt/conda/lib/python3.11/site-packages/autogluon/multimodal/learners/base.py:1358, in BaseLearner.fit_per_run(self, max_time, save_path, ckpt_path, resume, enable_progress_bar, seed, hyperparameters, advanced_hyperparameters, config, df_preprocessor, data_processors, model, standalone, clean_ckpts)
1339 config = self.post_update_config_per_run(
1340 config=config,
1341 num_gpus=num_gpus,
1342 precision=precision,
1343 strategy=strategy,
1344 )
1345 trainer = self.init_trainer_per_run(
1346 num_gpus=num_gpus,
1347 config=config,
(...) 1355 enable_progress_bar=enable_progress_bar,
1356 )
-> 1358 self.run_trainer(
1359 trainer=trainer,
1360 litmodule=litmodule,
1361 datamodule=datamodule,
1362 ckpt_path=ckpt_path,
1363 resume=resume,
1364 )
1365 self.on_fit_per_run_end(
1366 save_path=save_path,
1367 standalone=standalone,
(...) 1372 model=model,
1373 )
1375 best_score = (
1376 trainer.callback_metrics[f"val_{self._validation_metric_name}"].item()
1377 if f"val_{self._validation_metric_name}" in trainer.callback_metrics
1378 else self._best_score
1379 ) # https://github.com/autogluon/autogluon/issues/4428
File /opt/conda/lib/python3.11/site-packages/autogluon/multimodal/learners/base.py:1211, in BaseLearner.run_trainer(self, trainer, litmodule, datamodule, ckpt_path, resume, pred_writer, is_train)
1209 warnings.filterwarnings("ignore", filter)
1210 if is_train:
-> 1211 trainer.fit(
1212 litmodule,
1213 datamodule=datamodule,
1214 ckpt_path=ckpt_path if resume else None, # this is to resume training that was broken accidentally
1215 )
1216 else:
1217 blacklist_msgs = []
File /opt/conda/lib/python3.11/site-packages/lightning/pytorch/trainer/trainer.py:561, in Trainer.fit(self, model, train_dataloaders, val_dataloaders, datamodule, ckpt_path)
559 self.training = True
560 self.should_stop = False
--> 561 call._call_and_handle_interrupt(
562 self, self._fit_impl, model, train_dataloaders, val_dataloaders, datamodule, ckpt_path
563 )
File /opt/conda/lib/python3.11/site-packages/lightning/pytorch/trainer/call.py:48, in _call_and_handle_interrupt(trainer, trainer_fn, *args, **kwargs)
46 if trainer.strategy.launcher is not None:
47 return trainer.strategy.launcher.launch(trainer_fn, *args, trainer=trainer, **kwargs)
---> 48 return trainer_fn(*args, **kwargs)
50 except _TunerExitException:
51 _call_teardown_hook(trainer)
File /opt/conda/lib/python3.11/site-packages/lightning/pytorch/trainer/trainer.py:599, in Trainer._fit_impl(self, model, train_dataloaders, val_dataloaders, datamodule, ckpt_path)
592 download_model_from_registry(ckpt_path, self)
593 ckpt_path = self._checkpoint_connector._select_ckpt_path(
594 self.state.fn,
595 ckpt_path,
596 model_provided=True,
597 model_connected=self.lightning_module is not None,
598 )
--> 599 self._run(model, ckpt_path=ckpt_path)
601 assert self.state.stopped
602 self.training = False
File /opt/conda/lib/python3.11/site-packages/lightning/pytorch/trainer/trainer.py:1012, in Trainer._run(self, model, ckpt_path)
1007 self._signal_connector.register_signal_handlers()
1009 # ----------------------------
1010 # RUN THE TRAINER
1011 # ----------------------------
-> 1012 results = self._run_stage()
1014 # ----------------------------
1015 # POST-Training CLEAN UP
1016 # ----------------------------
1017 log.debug(f"{self.__class__.__name__}: trainer tearing down")
File /opt/conda/lib/python3.11/site-packages/lightning/pytorch/trainer/trainer.py:1054, in Trainer._run_stage(self)
1052 if self.training:
1053 with isolate_rng():
-> 1054 self._run_sanity_check()
1055 with torch.autograd.set_detect_anomaly(self._detect_anomaly):
1056 self.fit_loop.run()
File /opt/conda/lib/python3.11/site-packages/lightning/pytorch/trainer/trainer.py:1083, in Trainer._run_sanity_check(self)
1080 call._call_callback_hooks(self, "on_sanity_check_start")
1082 # run eval step
-> 1083 val_loop.run()
1085 call._call_callback_hooks(self, "on_sanity_check_end")
1087 # reset logger connector
File /opt/conda/lib/python3.11/site-packages/lightning/pytorch/loops/utilities.py:179, in _no_grad_context.._decorator(self, *args, **kwargs)
177 context_manager = torch.no_grad
178 with context_manager():
--> 179 return loop_run(self, *args, **kwargs)
File /opt/conda/lib/python3.11/site-packages/lightning/pytorch/loops/evaluation_loop.py:145, in _EvaluationLoop.run(self)
143 self.batch_progress.is_last_batch = data_fetcher.done
144 # run step hooks
--> 145 self._evaluation_step(batch, batch_idx, dataloader_idx, dataloader_iter)
146 except StopIteration:
147 # this needs to wrap the `*_step` call too (not just `next`) for `dataloader_iter` support
148 break
File /opt/conda/lib/python3.11/site-packages/lightning/pytorch/loops/evaluation_loop.py:437, in _EvaluationLoop._evaluation_step(self, batch, batch_idx, dataloader_idx, dataloader_iter)
431 hook_name = "test_step" if trainer.testing else "validation_step"
432 step_args = (
433 self._build_step_args_from_hook_kwargs(hook_kwargs, hook_name)
434 if not using_dataloader_iter
435 else (dataloader_iter,)
436 )
--> 437 output = call._call_strategy_hook(trainer, hook_name, *step_args)
439 self.batch_progress.increment_processed()
441 if using_dataloader_iter:
442 # update the hook kwargs now that the step method might have consumed the iterator
File /opt/conda/lib/python3.11/site-packages/lightning/pytorch/trainer/call.py:328, in _call_strategy_hook(trainer, hook_name, *args, **kwargs)
325 return None
327 with trainer.profiler.profile(f"[Strategy]{trainer.strategy.__class__.__name__}.{hook_name}"):
--> 328 output = fn(*args, **kwargs)
330 # restore current_fx when nested context
331 pl_module._current_fx_name = prev_fx_name
File /opt/conda/lib/python3.11/site-packages/lightning/pytorch/strategies/strategy.py:412, in Strategy.validation_step(self, *args, **kwargs)
410 if self.model != self.lightning_module:
411 return self._forward_redirection(self.model, self.lightning_module, "validation_step", *args, **kwargs)
--> 412 return self.lightning_module.validation_step(*args, **kwargs)
File /opt/conda/lib/python3.11/site-packages/autogluon/multimodal/optim/lit_module.py:381, in LitModule.validation_step(self, batch, batch_idx)
365 def validation_step(self, batch, batch_idx):
366 """
367 Per validation step. This function is registered by LightningModule.
368 Refer to https://lightning.ai/docs/pytorch/stable/common/lightning_module.html#validation-loop
(...) 379 Index of mini-batch.
380 """
--> 381 output, loss = self._shared_step(batch)
382 if self.model_postprocess_fn:
383 output = self.model_postprocess_fn(output)
File /opt/conda/lib/python3.11/site-packages/autogluon/multimodal/optim/lit_module.py:305, in LitModule._shared_step(self, batch)
303 self.mixup_fn.mixup_enabled = self.training & (self.current_epoch < self.hparams.mixup_off_epoch)
304 batch, label = multimodel_mixup(batch=batch, model=self.model, mixup_fn=self.mixup_fn)
--> 305 output = run_model(self.model, batch)
306 loss = self._compute_loss(output=output, label=label)
307 return output, loss
File /opt/conda/lib/python3.11/site-packages/autogluon/multimodal/models/utils.py:846, in run_model(model, batch, trt_model)
844 # DocumentTransformer inherited from HFAutoModelForTextPrediction
845 if (not isinstance(pure_model, DocumentTransformer)) and isinstance(pure_model, supported_models):
--> 846 input_vec = [batch[k] for k in pure_model.input_keys]
847 column_names, column_values = [], []
848 for k in batch.keys():
File /opt/conda/lib/python3.11/site-packages/autogluon/multimodal/models/utils.py:846, in (.0)
844 # DocumentTransformer inherited from HFAutoModelForTextPrediction
845 if (not isinstance(pure_model, DocumentTransformer)) and isinstance(pure_model, supported_models):
--> 846 input_vec = [batch[k] for k in pure_model.input_keys]
847 column_names, column_values = [], []
848 for k in batch.keys():
KeyError: 'document_transformer_text_valid_length'```
**Installed Versions**
```python
# Replace this code with the output of the following:
INSTALLED VERSIONS
------------------
date : 2025-09-19
time : 18:32:46.103160
python : 3.11.10.final.0
OS : Linux
OS-release : 5.10.240-218.959.amzn2int.x86_64
Version : #1 SMP Thu Aug 7 19:38:22 UTC 2025
machine : x86_64
processor : x86_64
num_cores : 64
cpu_ram_mb : 253657.2109375
cuda version : None
num_gpus : 0
gpu_ram_mb : []
avail_disk_size_mb : 1135514
accelerate : 1.9.0
autogluon : 1.4.0
autogluon.common : 1.4.0
autogluon.core : 1.4.0
autogluon.features : 1.4.0
autogluon.multimodal : 1.4.0
autogluon.tabular : 1.4.0
autogluon.timeseries : 1.4.0
blis : 1.2.1
boto3 : 1.40.3
catboost : 1.2.8
coreforecast : 0.0.16
defusedxml : 0.7.1
einops : 0.8.1
einx : 0.3.0
evaluate : 0.4.5
fastai : 2.8.2
fsspec : 2025.3.0
fugue : 0.9.1
gluonts : 0.16.2
huggingface-hub : 0.33.4
hyperopt : 0.2.7
imodels : None
jinja2 : 3.1.6
joblib : 1.5.1
jsonschema : 4.23.0
lightgbm : 4.6.0
lightning : 2.5.2
loguru : 0.7.3
matplotlib : 3.10.3
mlforecast : 0.14.0
networkx : 3.5
nlpaug : 1.1.11
nltk : 3.9.1
numpy : 1.26.4
nvidia-ml-py3 : 7.352.0
omegaconf : 2.3.0
onnx : None
onnxruntime : None
onnxruntime-gpu : None
openmim : 0.3.9
orjson : 3.11.1
pandas : 2.3.1
pdf2image : 1.17.0
Pillow : 11.3.0
psutil : 6.1.1
pyarrow : 20.0.0
pytabkit : None
pytesseract : 0.3.13
pytorch-lightning : 2.5.2
pytorch-metric-learning: 2.8.1
ray : 2.44.1
requests : 2.32.4
scikit-image : 0.25.2
scikit-learn : 1.7.1
scikit-learn-intelex : None
scipy : 1.16.0
seqeval : 1.2.2
skl2onnx : None
spacy : 3.8.7
statsforecast : 2.0.1
tabicl : None
tabpfn : None
tensorboard : 2.20.0
text-unidecode : 1.3
timm : 1.0.3
torch : 2.5.1+cu124
torchmetrics : 1.7.4
torchvision : 0.20.1+cu124
tqdm : 4.66.5
transformers : 4.49.0
utilsforecast : 0.2.11
xgboost : 3.0.3
```
Contributor guide
Research direction
Start with the MultiModalPredictor.fit entry point in autogluon/multimodal/predictor.py and follow the BaseLearner fit path shown in the traceback, focusing on input_vec creation and the DocumentTransformer inputs. Reproduce the provided DataFrame example, then verify that fitting no longer raises the missing document_transformer_text_valid_length KeyError and that the fit documentation explains model.names hyperparameters.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- pandas, python, pytorch
- Domain
- computer-vision, machine-learning
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100