Skip to content

Commit ed5dcaf

Browse files
committed
docs(core_concepts): fix cmd output and update install instructions
1 parent 611a7e7 commit ed5dcaf

6 files changed

Lines changed: 116 additions & 92 deletions

File tree

docs/core_concepts/custom_models.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -213,13 +213,15 @@ class MyEmbeddedModel(BaseModel):
213213

214214
## Checklist
215215

216-
- [ ] Config is a `@dataclass` subclassing `BaseModelConfig`.
217-
- [ ] Mutable config defaults use `field(default_factory=...)`.
218-
- [ ] Architecture subclasses `BaseModel` and calls `super().__init__(config=config, **kwargs)`.
219-
- [ ] Constructor calls `self.save_hyperparameters(ignore=["feature_information"])`.
220-
- [ ] Input width comes from `get_feature_dimensions(...)` or an `EmbeddingLayer`, never a hard-coded value.
221-
- [ ] `forward` returns raw outputs (no final softmax/sigmoid).
222-
- [ ] Each estimator sets `_model_cls` and `_config_cls`.
216+
| Piece | Requirement |
217+
| ------------ | ---------------------------------------------------------------------------------------------- |
218+
| Config | A `@dataclass` subclassing `BaseModelConfig`. |
219+
| Config | Mutable defaults use `field(default_factory=...)`. |
220+
| Architecture | Subclasses `BaseModel` and calls `super().__init__(config=config, **kwargs)`. |
221+
| Architecture | Constructor calls `self.save_hyperparameters(ignore=["feature_information"])`. |
222+
| Architecture | Input width comes from `get_feature_dimensions(...)` or an `EmbeddingLayer`, never hard-coded. |
223+
| Architecture | `forward` returns raw outputs (no final softmax/sigmoid). |
224+
| Estimator | Each estimator sets `_model_cls` and `_config_cls`. |
223225

224226
## Next Steps
225227

docs/core_concepts/model_operations.md

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,23 @@ predictions = loaded.predict(X_test)
2424
```
2525

2626
```{tip}
27-
Use the class that matches the saved model type. Using the wrong class will raise an error with a clear message pointing to the mismatch.
27+
`load()` reconstructs whatever model type was saved, regardless of which estimator class you call it on. Calling `MLPRegressor.load("classifier.deeptab")` still returns an `MLPClassifier`. Calling `load()` from the matching class keeps the intent clear, but the returned object always has the saved type.
2828
```
2929

3030
### What is inside the artifact
3131

3232
The bundle saved to disk is a PyTorch-serialised dictionary containing:
3333

34-
| Key | Contents |
35-
| ----------------------- | ------------------------------------------------------------------------- |
36-
| `task_model_state_dict` | Neural network weights (Lightning module state dict) |
37-
| `preprocessor` | Fitted `pretab.Preprocessor` object |
38-
| `feature_info` | Numerical, categorical, and embedding feature metadata |
39-
| `config` | Model config dataclass used during training |
40-
| `artifact_metadata` | Architecture, schema, preprocessing, task, and version sub-blocks |
41-
| `input_columns` | Ordered list of column names, for feature-name validation at predict time |
42-
| `classes_` | Class labels for classifiers |
43-
| `versions` | Python, PyTorch, Lightning, NumPy, pandas, scikit-learn versions |
34+
| Key | Contents |
35+
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
36+
| `task_model_state_dict` | Neural network weights (Lightning module state dict) |
37+
| `preprocessor` | Fitted `pretab.Preprocessor` object |
38+
| `feature_info` | Numerical, categorical, and embedding feature metadata |
39+
| `config` | Model config dataclass used during training |
40+
| `artifact_metadata` | Architecture, schema, preprocessing, task, and version sub-blocks |
41+
| `input_columns` | Ordered list of column names, for feature-name validation at predict time |
42+
| `classes_` | Class labels for classifiers |
43+
| `versions` | Python, platform, and key package versions (`deeptab`, `torch`, `lightning`, `numpy`, `pandas`, `scikit-learn`, `pretab`, ...) |
4444

4545
### Why everything lives in one bundle
4646

@@ -142,7 +142,7 @@ The schema grows with the number of features, not the number of rows. It is the
142142

143143
## Model Inspection
144144

145-
All DeepTab estimators inherit `InspectionMixin`, which provides four read-only methods and one dry-run profiler. They are safe to call before or after fitting.
145+
All DeepTab estimators inherit `InspectionMixin`, which provides four read-only methods and one dry-run profiler. `describe()`, `summary()`, and `runtime_info()` are safe to call before or after fitting; `parameter_table()` requires a built model and raises otherwise.
146146

147147
### `describe()`: structured dict
148148

@@ -151,15 +151,19 @@ Returns a structured snapshot of the estimator and its fitted state:
151151
```python
152152
info = model.describe()
153153
# {
154-
# "estimator": "MLPClassifier",
155-
# "architecture": "MLP",
156-
# "task": "classification",
157-
# "built": True,
158-
# "fitted": True,
159-
# "model_config": "MLPConfig",
160-
# "feature_counts": {"numerical": 8, "categorical": 2, "embedding": 0, "total": 10},
161-
# "num_classes": 2,
162-
# "parameters": {"total": 45312, "trainable": 45312, "non_trainable": 0},
154+
# "estimator": "MLPClassifier",
155+
# "architecture": "MLP",
156+
# "task": "classification",
157+
# "built": True,
158+
# "fitted": True,
159+
# "model_config": "MLPConfig",
160+
# "preprocessing_config": "PreprocessingConfig",
161+
# "trainer_config": "TrainerConfig",
162+
# "feature_counts": {"numerical": 8, "categorical": 2, "embedding": 0, "total": 10},
163+
# "num_classes": 3,
164+
# "family": None,
165+
# "returns_ensemble": False,
166+
# "parameters": {"total": 45312, "trainable": 45312, "non_trainable": 0},
163167
# }
164168
```
165169

@@ -180,10 +184,12 @@ print(model.summary())
180184
# Features: 10 total (8 numerical, 2 categorical, 0 embedding)
181185
# Parameters: 45,312 total, 45,312 trainable, 0 non-trainable
182186
# Device: cpu
183-
# Precision: None
184-
# Accelerator: None
187+
# Precision: 32-true
188+
# Accelerator: CPUAccelerator
185189
```
186190

191+
The `Device`, `Precision`, and `Accelerator` lines appear only once a trainer is attached (after building or fitting); they are omitted when the value is unknown.
192+
187193
### `parameter_table()`: per-parameter DataFrame
188194

189195
Returns one row per parameter:
@@ -208,8 +214,8 @@ info = model.runtime_info()
208214
# "fitted": True,
209215
# "device": "cpu",
210216
# "dtype": "float32",
211-
# "precision": None,
212-
# "accelerator": None,
217+
# "precision": "32-true",
218+
# "accelerator": "CPUAccelerator",
213219
# "max_epochs": 100,
214220
# "current_epoch": 87,
215221
# "batch_size": 64,

docs/core_concepts/model_tiers.md

Lines changed: 12 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -49,38 +49,20 @@ guide.
4949

5050
## Choosing a Tier
5151

52-
Use stable models when:
53-
54-
- the code will run in production;
55-
- experiments need long-term reproducibility;
56-
- collaborators need a lower-maintenance baseline;
57-
- APIs must remain stable across minor releases.
58-
59-
Use experimental models when:
60-
61-
- you are evaluating recent architectures;
62-
- you can pin DeepTab to an exact version;
63-
- breaking changes are acceptable;
64-
- the goal is research feedback rather than deployment.
65-
66-
## Version Pinning
67-
68-
For stable-only projects, pin a compatible range:
69-
70-
```text
71-
deeptab>=2.0,<3.0
52+
| Consideration | Stable | Experimental |
53+
| ------------------ | -------------------------------------- | ---------------------------------------- |
54+
| Primary use | Production and long-running projects | Prototyping and research comparisons |
55+
| Reproducibility | Stable across minor releases | Requires pinning an exact version |
56+
| API stability | Compatible within a major version | May introduce breaking changes |
57+
| Maintenance burden | Lower; safe baseline for collaborators | Higher; tracks recent, evolving research |
58+
| Goal | Reliable deployment | Early evaluation and research feedback |
59+
60+
```{note}
61+
**Version pinning.** For stable-only projects, pin a compatible range such as
62+
`deeptab>=2.0,<3.0`. For projects that use experimental models, pin the exact
63+
version (`deeptab==2.0.0`), since their APIs may change between releases.
7264
```
7365

74-
For experimental-model projects, pin the exact version:
75-
76-
```text
77-
deeptab==2.0.0
78-
```
79-
80-
## Documentation Policy
81-
82-
Stable model docs should document both the paper idea and the actual DeepTab implementation. Experimental docs should be even more explicit about implementation differences, config limitations, and expected API volatility.
83-
8466
## Next Steps
8567

8668
- [Stable Models](../model_zoo/stable/index)

docs/core_concepts/observability.md

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,20 @@ DeepTab can record what happens during training without you writing a single cal
66
Observability is entirely opt-in. Estimators created without an `ObservabilityConfig` train exactly as before and emit nothing, so notebooks stay quiet by default.
77
```
88

9+
The default `pip install deeptab` does not include the observability backends. Install the extra you need:
10+
11+
```bash
12+
pip install 'deeptab[logs]' # structlog (structured logging)
13+
pip install 'deeptab[tensorboard]' # TensorBoard tracker
14+
pip install 'deeptab[mlflow]' # MLflow tracker
15+
pip install 'deeptab[tracking]' # TensorBoard + MLflow
16+
pip install 'deeptab[all]' # structlog + TensorBoard + MLflow
17+
```
18+
19+
```{note}
20+
Each backend is loaded lazily, so a missing package raises only when you enable the matching feature.
21+
```
22+
923
---
1024

1125
## Attaching observability
@@ -18,7 +32,7 @@ from deeptab.models import MambularClassifier
1832

1933
obs = ObservabilityConfig(
2034
experiment_name="churn_baseline",
21-
structured_logging=True, # human-readable console + JSON event log
35+
structured_logging=True, # console event log (add log_to_file=True for JSONL)
2236
experiment_trackers=["mlflow"], # also supports "tensorboard"
2337
)
2438

@@ -46,12 +60,12 @@ Every output path is derived from `root_dir`, producing a single organised tree
4660

4761
```text
4862
deeptab_runs/
49-
runs/churn_baseline/20260611_174830_8f3a2c/
63+
runs/churn_baseline/20260611_174830_8f3a2c1d/
5064
config.yaml # estimator hyperparameters
5165
lifecycle.jsonl # structured event log (when log_to_file=True)
5266
summary.json # final metrics
53-
checkpoints/best.ckpt
54-
tensorboard/churn_baseline/20260611_174830_8f3a2c/
67+
checkpoints/best_model.ckpt
68+
tensorboard/churn_baseline/20260611_174830_8f3a2c1d/
5569
events.out.tfevents...
5670
mlflow/
5771
backend/mlflow.db
@@ -66,23 +80,23 @@ The run identifier combines a timestamp and a short hash, so concurrent or repea
6680

6781
`ObservabilityConfig` is a dataclass. All fields are optional and resolve sensible defaults relative to `root_dir`.
6882

69-
| Field | Default | Purpose |
70-
| -------------------------- | ---------------- | ------------------------------------------------------------------------------ |
71-
| `root_dir` | `"deeptab_runs"` | Base directory for all observability outputs. |
72-
| `experiment_name` | `"default"` | Logical label used to group related runs. |
73-
| `structured_logging` | `False` | Enable structured runtime logging via `structlog`. |
74-
| `log_to_console` | `True` | Stream compact human-readable output to stdout. |
75-
| `log_to_file` | `False` | Write a per-run `lifecycle.jsonl` inside the run directory. |
76-
| `verbosity` | `1` | Which lifecycle events are emitted when `structured_logging=True` (see below). |
77-
| `experiment_trackers` | `[]` | Lightning loggers to activate: `"tensorboard"`, `"mlflow"`, or both. |
78-
| `tensorboard_save_dir` | `""` | Resolved to `<root_dir>/tensorboard` when empty. |
79-
| `tensorboard_name` | `"deeptab"` | Sub-directory label inside the TensorBoard save dir. |
80-
| `mlflow_experiment_name` | `"deeptab"` | Name of the MLflow experiment. |
81-
| `mlflow_tracking_uri` | `""` | Resolved to a local SQLite store under `<root_dir>/mlflow` when empty. |
82-
| `mlflow_artifact_location` | `""` | Resolved to `<root_dir>/mlflow/artifacts` when empty. |
83-
| `mlflow_run_name` | `None` | Human-readable label for the MLflow run. |
84-
| `mlflow_log_model` | `True` | Upload model checkpoints as MLflow artifacts. |
85-
| `logger` | `None` | A user-provided Lightning logger appended alongside any built-in trackers. |
83+
| Field | Default | Purpose |
84+
| -------------------------- | ---------------- | ------------------------------------------------------------------------------------- |
85+
| `root_dir` | `"deeptab_runs"` | Base directory for all observability outputs. |
86+
| `experiment_name` | `"default"` | Logical label used to group related runs. |
87+
| `structured_logging` | `False` | Enable structured runtime logging via `structlog`. |
88+
| `log_to_console` | `True` | Stream compact human-readable output to stdout. |
89+
| `log_to_file` | `False` | Write a per-run `lifecycle.jsonl` inside the run directory. |
90+
| `verbosity` | `1` | Which lifecycle events are emitted when `structured_logging=True` (see below). |
91+
| `experiment_trackers` | `[]` | Lightning loggers to activate: `"tensorboard"`, `"mlflow"`, or both. |
92+
| `tensorboard_save_dir` | `""` | Resolved to `<root_dir>/tensorboard` when empty. |
93+
| `tensorboard_name` | `"deeptab"` | Reserved label field; the TensorBoard sub-directory currently uses `experiment_name`. |
94+
| `mlflow_experiment_name` | `"deeptab"` | Name of the MLflow experiment. |
95+
| `mlflow_tracking_uri` | `""` | Resolved to a local SQLite store under `<root_dir>/mlflow` when empty. |
96+
| `mlflow_artifact_location` | `""` | Resolved to `<root_dir>/mlflow/artifacts` when empty. |
97+
| `mlflow_run_name` | `None` | Human-readable label for the MLflow run. |
98+
| `mlflow_log_model` | `True` | Upload model checkpoints as MLflow artifacts. |
99+
| `logger` | `None` | A user-provided Lightning logger appended alongside any built-in trackers. |
86100

87101
```{note}
88102
`experiment_trackers` is a list, not a single string. Pass `["tensorboard"]`, `["mlflow"]`, or `["mlflow", "tensorboard"]` to activate one or both.
@@ -135,13 +149,17 @@ from deeptab.core.observability import ObservabilityConfig
135149

136150
obs = ObservabilityConfig(
137151
logger=WandbLogger(project="churn"), # your existing tracker
138-
experiment_trackers=["tensorboard"], # optional: keep DeepTab trackers too
152+
experiment_trackers=["tensorboard"], # needed for the custom logger to attach
139153
)
140154

141155
model = MambularClassifier(observability_config=obs)
142156
model.fit(X_train, y_train, max_epochs=50)
143157
```
144158

159+
```{warning}
160+
A custom `logger` is only attached when `experiment_trackers` has at least one entry. With an empty `experiment_trackers`, DeepTab suppresses all Lightning loggers (so no stray `lightning_logs/` directory is created) and the `logger` is dropped. Keep at least one tracker active, such as `["tensorboard"]` above, for your logger to be picked up.
161+
```
162+
145163
```{note}
146164
The `logger` field accepts a single Lightning logger instance. To attach several at once, wire them through the trackers you control or compose them in your own framework, then hand DeepTab the one entry point.
147165
```

0 commit comments

Comments
 (0)