Describe the bug
Umbrella issue: assorted crashes and robustness gaps in public API paths. Individually small, grouped here to keep the tracker manageable; all are independent of each other.
fit() crashes on plain-list X (deeptab/models/_mixins/fit.py:441): the fit.started event computes X.shape[1] if hasattr(X, "shape") else len(X.columns) before ensure_dataframe runs — list input dies with AttributeError: 'list' object has no attribute 'columns' even though the converter supports lists. (Verified.)
log_parameters() always crashes (deeptab/core/base_model.py:102): iterates self.hparams.items() but save_hyperparameters() stores a Namespace, which has no .items() → AttributeError on every call. (Verified.)
__getstate__ nulls the wrong key (deeptab/models/base.py:371): sets state["task_model"] = None but the attribute is _task_model — pickling serializes the full Lightning module, contradicting the documented intent in _mixins/serialization.py. (Verified.)
- All-zero
sample_weight fails with a cryptic mid-training RuntimeError (from torch.multinomial) instead of an upfront ValueError — this is the single failing test in the repo's own suite: test_sklearn_contract.py::...::check_all_zero_sample_weights_error. (Verified.)
- Duplicate column names crash with
ValueError: The truth value of a Series is ambiguous deep in preprocessing — a clear "duplicate column names are not supported" validation at fit would help. (Verified.)
- Binary-vs-multiclass label shape decided from post-split
y_train (deeptab/data/datamodule.py:279) while the model head uses full-y class counts (classifier_base.py:294): with stratify=False and a rare class landing entirely in the val split, fit crashes with RuntimeError: 0D or 1D target tensor expected during sanity check. Should use the task-level class count. (Verified.)
TabularDataModule.__init__(X_val=, y_val=, val_size=) are dead parameters (datamodule.py:76-79 vs 98-166): preprocess_data() consults only its own arguments and overwrites self.X_val/self.y_val with an auto split — a user-provided validation set is silently discarded (the docstring promises otherwise). X_val without y_val is silently ignored too. deeptab's own fit() passes both consistently, so this bites direct users of the data API.
TabularDataset(embeddings_list=None) (the default) is un-collatable (deeptab/data/dataset.py:33, 68-71): __getitem__ embeds None in the sample tuple → stock DataLoader raises TypeError: default_collate: batch must contain tensors ... found NoneType. Internal callers always pass []. (Verified.)
- Default MLflow tracking URI points into a directory that is never created (
deeptab/core/observability.py:174 vs build_lightning_loggers, which only creates the artifact location): ObservabilityConfig(experiment_trackers=["mlflow"]) on a fresh machine → sqlite OperationalError: unable to open database file.
InferenceModel.from_path double-loads the artifact (deeptab/core/inference.py:156-165): torch.loads the full bundle to read _class, then estimator_class.load(path) re-reads everything and the extension warning fires twice. Wasteful rather than wrong.
To Reproduce
Each item above lists its location; the verified ones came from executing e.g.:
MLPRegressor().fit([[1.0], [2.0]], [0.1, 0.2], max_epochs=1) # (1)
model._task_model.log_parameters() # (2)
model.__getstate__()["_task_model"] is not None # (3)
clf.fit(X, y, sample_weight=np.zeros(len(y)), max_epochs=1) # (4) RuntimeError mid-train
Expected behavior
Input validation errors should be raised upfront with actionable messages; documented parameters should either work or be removed; pickling should exclude the Lightning module as documented.
Screenshots
n/a
Desktop (please complete the following information):
- OS: macOS (Darwin 25.5.0, arm64)
- Python version: 3.11.15
- deeptab Version: 2.0.0 (main @ 4e6a359)
Additional context
torch 2.9.1, lightning 2.6.5, scikit-learn 1.9.0, numpy 2.4.6. Found during a systematic bug-hunt of v2.0.0; the higher-severity findings are filed as separate issues.
Describe the bug
Umbrella issue: assorted crashes and robustness gaps in public API paths. Individually small, grouped here to keep the tracker manageable; all are independent of each other.
fit()crashes on plain-listX(deeptab/models/_mixins/fit.py:441): thefit.startedevent computesX.shape[1] if hasattr(X, "shape") else len(X.columns)beforeensure_dataframeruns — list input dies withAttributeError: 'list' object has no attribute 'columns'even though the converter supports lists. (Verified.)log_parameters()always crashes (deeptab/core/base_model.py:102): iteratesself.hparams.items()butsave_hyperparameters()stores aNamespace, which has no.items()→AttributeErroron every call. (Verified.)__getstate__nulls the wrong key (deeptab/models/base.py:371): setsstate["task_model"] = Nonebut the attribute is_task_model— pickling serializes the full Lightning module, contradicting the documented intent in_mixins/serialization.py. (Verified.)sample_weightfails with a cryptic mid-trainingRuntimeError(fromtorch.multinomial) instead of an upfrontValueError— this is the single failing test in the repo's own suite:test_sklearn_contract.py::...::check_all_zero_sample_weights_error. (Verified.)ValueError: The truth value of a Series is ambiguousdeep in preprocessing — a clear "duplicate column names are not supported" validation atfitwould help. (Verified.)y_train(deeptab/data/datamodule.py:279) while the model head uses full-yclass counts (classifier_base.py:294): withstratify=Falseand a rare class landing entirely in the val split, fit crashes withRuntimeError: 0D or 1D target tensor expectedduring sanity check. Should use the task-level class count. (Verified.)TabularDataModule.__init__(X_val=, y_val=, val_size=)are dead parameters (datamodule.py:76-79vs98-166):preprocess_data()consults only its own arguments and overwritesself.X_val/self.y_valwith an auto split — a user-provided validation set is silently discarded (the docstring promises otherwise).X_valwithouty_valis silently ignored too. deeptab's ownfit()passes both consistently, so this bites direct users of the data API.TabularDataset(embeddings_list=None)(the default) is un-collatable (deeptab/data/dataset.py:33, 68-71):__getitem__embedsNonein the sample tuple → stockDataLoaderraisesTypeError: default_collate: batch must contain tensors ... found NoneType. Internal callers always pass[]. (Verified.)deeptab/core/observability.py:174vsbuild_lightning_loggers, which only creates the artifact location):ObservabilityConfig(experiment_trackers=["mlflow"])on a fresh machine → sqliteOperationalError: unable to open database file.InferenceModel.from_pathdouble-loads the artifact (deeptab/core/inference.py:156-165):torch.loads the full bundle to read_class, thenestimator_class.load(path)re-reads everything and the extension warning fires twice. Wasteful rather than wrong.To Reproduce
Each item above lists its location; the verified ones came from executing e.g.:
Expected behavior
Input validation errors should be raised upfront with actionable messages; documented parameters should either work or be removed; pickling should exclude the Lightning module as documented.
Screenshots
n/a
Desktop (please complete the following information):
Additional context
torch 2.9.1, lightning 2.6.5, scikit-learn 1.9.0, numpy 2.4.6. Found during a systematic bug-hunt of v2.0.0; the higher-severity findings are filed as separate issues.