tensorless 0.2.0__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. tensorless-0.3.0/PKG-INFO +77 -0
  2. tensorless-0.3.0/README.md +63 -0
  3. {tensorless-0.2.0 → tensorless-0.3.0}/docs/automatic_mode.md +10 -1
  4. {tensorless-0.2.0 → tensorless-0.3.0}/docs/checkpointing.md +4 -0
  5. {tensorless-0.2.0 → tensorless-0.3.0}/docs/configuration.md +1 -1
  6. {tensorless-0.2.0 → tensorless-0.3.0}/docs/roadmap.md +0 -13
  7. {tensorless-0.2.0 → tensorless-0.3.0}/docs/training.md +10 -3
  8. {tensorless-0.2.0 → tensorless-0.3.0}/pyproject.toml +4 -1
  9. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/__init__.py +2 -1
  10. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/api.py +17 -1
  11. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/auto/config.py +27 -10
  12. tensorless-0.3.0/tensorless/data/english_grammar.txt +262 -0
  13. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/data/tabular.py +48 -14
  14. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/serialization/tl_format.py +31 -1
  15. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/tokenization/bpe_tokenizer.py +11 -6
  16. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/training/data_prep.py +44 -28
  17. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/training/early_stopping.py +1 -1
  18. tensorless-0.3.0/tensorless.egg-info/PKG-INFO +77 -0
  19. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless.egg-info/SOURCES.txt +2 -0
  20. {tensorless-0.2.0 → tensorless-0.3.0}/tests/test_checkpoint_resume.py +18 -0
  21. {tensorless-0.2.0 → tensorless-0.3.0}/tests/test_serialization.py +42 -0
  22. {tensorless-0.2.0 → tensorless-0.3.0}/tests/test_train_tabular.py +39 -0
  23. {tensorless-0.2.0 → tensorless-0.3.0}/tests/test_train_text_generation.py +29 -0
  24. tensorless-0.2.0/PKG-INFO +0 -13
  25. tensorless-0.2.0/tensorless.egg-info/PKG-INFO +0 -13
  26. {tensorless-0.2.0 → tensorless-0.3.0}/LICENSE +0 -0
  27. {tensorless-0.2.0 → tensorless-0.3.0}/MANIFEST.in +0 -0
  28. {tensorless-0.2.0 → tensorless-0.3.0}/docs/api_reference.md +0 -0
  29. {tensorless-0.2.0 → tensorless-0.3.0}/docs/architecture.md +0 -0
  30. {tensorless-0.2.0 → tensorless-0.3.0}/docs/cli.md +0 -0
  31. {tensorless-0.2.0 → tensorless-0.3.0}/docs/contributing.md +0 -0
  32. {tensorless-0.2.0 → tensorless-0.3.0}/docs/examples.md +0 -0
  33. {tensorless-0.2.0 → tensorless-0.3.0}/docs/inference.md +0 -0
  34. {tensorless-0.2.0 → tensorless-0.3.0}/docs/installation.md +0 -0
  35. {tensorless-0.2.0 → tensorless-0.3.0}/docs/limitations.md +0 -0
  36. {tensorless-0.2.0 → tensorless-0.3.0}/docs/quickstart.md +0 -0
  37. {tensorless-0.2.0 → tensorless-0.3.0}/docs/tl_format.md +0 -0
  38. {tensorless-0.2.0 → tensorless-0.3.0}/docs/troubleshooting.md +0 -0
  39. {tensorless-0.2.0 → tensorless-0.3.0}/docs/tutorial.md +0 -0
  40. {tensorless-0.2.0 → tensorless-0.3.0}/examples/tabular_classification_example.py +0 -0
  41. {tensorless-0.2.0 → tensorless-0.3.0}/examples/tabular_regression_example.py +0 -0
  42. {tensorless-0.2.0 → tensorless-0.3.0}/examples/text_classification_example.py +0 -0
  43. {tensorless-0.2.0 → tensorless-0.3.0}/examples/text_generation_example.py +0 -0
  44. {tensorless-0.2.0 → tensorless-0.3.0}/setup.cfg +0 -0
  45. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/_version.py +0 -0
  46. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/auto/__init__.py +0 -0
  47. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/auto/detector.py +0 -0
  48. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/checkpoint/__init__.py +0 -0
  49. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/checkpoint/manager.py +0 -0
  50. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/cli/__init__.py +0 -0
  51. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/cli/main.py +0 -0
  52. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/config.py +0 -0
  53. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/data/__init__.py +0 -0
  54. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/data/fingerprint.py +0 -0
  55. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/data/inspector.py +0 -0
  56. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/data/loader.py +0 -0
  57. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/devices/__init__.py +0 -0
  58. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/devices/device.py +0 -0
  59. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/errors.py +0 -0
  60. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/models/__init__.py +0 -0
  61. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/models/mlp.py +0 -0
  62. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/models/registry.py +0 -0
  63. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/models/transformer.py +0 -0
  64. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/runtime.py +0 -0
  65. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/serialization/__init__.py +0 -0
  66. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/tokenization/__init__.py +0 -0
  67. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/tokenization/char_tokenizer.py +0 -0
  68. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/training/__init__.py +0 -0
  69. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless/training/trainer.py +0 -0
  70. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless.egg-info/dependency_links.txt +0 -0
  71. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless.egg-info/entry_points.txt +0 -0
  72. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless.egg-info/requires.txt +0 -0
  73. {tensorless-0.2.0 → tensorless-0.3.0}/tensorless.egg-info/top_level.txt +0 -0
  74. {tensorless-0.2.0 → tensorless-0.3.0}/tests/test_auto_detection.py +0 -0
  75. {tensorless-0.2.0 → tensorless-0.3.0}/tests/test_cli.py +0 -0
  76. {tensorless-0.2.0 → tensorless-0.3.0}/tests/test_data_loading.py +0 -0
  77. {tensorless-0.2.0 → tensorless-0.3.0}/tests/test_end_to_end.py +0 -0
  78. {tensorless-0.2.0 → tensorless-0.3.0}/tests/test_fingerprint.py +0 -0
  79. {tensorless-0.2.0 → tensorless-0.3.0}/tests/test_train_text_classification.py +0 -0
@@ -0,0 +1,77 @@
1
+ Metadata-Version: 2.4
2
+ Name: tensorless
3
+ Version: 0.3.0
4
+ Summary: ML with maximum automation and minimum setup.
5
+ Author: Tensorless Contributors
6
+ License: MIT
7
+ Requires-Python: >=3.9
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: torch>=2.0
11
+ Provides-Extra: dev
12
+ Requires-Dist: pytest>=7.0; extra == "dev"
13
+ Dynamic: license-file
14
+
15
+ # Tensorless
16
+
17
+ Tensorless trains small PyTorch models with sensible defaults. It supports
18
+ text generation, text classification, tabular classification, and regression.
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ pip install -e .
24
+ ```
25
+
26
+ ## Train on your data
27
+
28
+ ```python
29
+ import tensorless as tl
30
+
31
+ model = tl.train("./corpus.txt", task="text-generation")
32
+ print(model.generate("The", max_new_tokens=40))
33
+ ```
34
+
35
+ Text files are trained as next-token language models. BPE is the default
36
+ tokenizer; use `tokenizer="char"` for a character-level model. Tensorless
37
+ derives model size, batch size, epochs, validation, device, and BPE vocabulary
38
+ size from the data, while every setting can be overridden.
39
+
40
+ Long text is tokenized lazily and fed through PyTorch in fixed-size batches.
41
+ The automatic batch size uses a token budget; reduce `batch_size` if your
42
+ available memory is limited.
43
+
44
+ ## English starter pretraining
45
+
46
+ ```python
47
+ import tensorless as tl
48
+
49
+ model = tl.pretrain(out="english.tl", epochs=20, max_seq_len=128)
50
+ print(model.generate("A complete sentence", max_new_tokens=30))
51
+ ```
52
+
53
+ This offline starter corpus contains English prose and grammar examples. It is
54
+ for demos and smoke tests, not a replacement for a large language dataset. For
55
+ real pretraining, pass your own `.txt` corpus to `tl.train()` and increase the
56
+ training settings as your hardware allows.
57
+
58
+ ## Other tasks
59
+
60
+ ```python
61
+ tl.train("reviews/", task="text-classification")
62
+ tl.train("housing.csv", task="regression")
63
+ ```
64
+
65
+ Tabular preprocessing automatically handles numeric values, ISO dates, and
66
+ high-cardinality categories. Missing and rare values are handled using the
67
+ fitted training data, and the same preprocessing is stored in the `.tl` file.
68
+
69
+ Models are saved as `.tl` files and can be loaded later:
70
+
71
+ ```python
72
+ model = tl.load("model.tl")
73
+ print(model.info())
74
+ ```
75
+
76
+ See the [documentation](docs/quickstart.md) for data formats, configuration,
77
+ checkpointing, and the command-line interface.
@@ -0,0 +1,63 @@
1
+ # Tensorless
2
+
3
+ Tensorless trains small PyTorch models with sensible defaults. It supports
4
+ text generation, text classification, tabular classification, and regression.
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ pip install -e .
10
+ ```
11
+
12
+ ## Train on your data
13
+
14
+ ```python
15
+ import tensorless as tl
16
+
17
+ model = tl.train("./corpus.txt", task="text-generation")
18
+ print(model.generate("The", max_new_tokens=40))
19
+ ```
20
+
21
+ Text files are trained as next-token language models. BPE is the default
22
+ tokenizer; use `tokenizer="char"` for a character-level model. Tensorless
23
+ derives model size, batch size, epochs, validation, device, and BPE vocabulary
24
+ size from the data, while every setting can be overridden.
25
+
26
+ Long text is tokenized lazily and fed through PyTorch in fixed-size batches.
27
+ The automatic batch size uses a token budget; reduce `batch_size` if your
28
+ available memory is limited.
29
+
30
+ ## English starter pretraining
31
+
32
+ ```python
33
+ import tensorless as tl
34
+
35
+ model = tl.pretrain(out="english.tl", epochs=20, max_seq_len=128)
36
+ print(model.generate("A complete sentence", max_new_tokens=30))
37
+ ```
38
+
39
+ This offline starter corpus contains English prose and grammar examples. It is
40
+ for demos and smoke tests, not a replacement for a large language dataset. For
41
+ real pretraining, pass your own `.txt` corpus to `tl.train()` and increase the
42
+ training settings as your hardware allows.
43
+
44
+ ## Other tasks
45
+
46
+ ```python
47
+ tl.train("reviews/", task="text-classification")
48
+ tl.train("housing.csv", task="regression")
49
+ ```
50
+
51
+ Tabular preprocessing automatically handles numeric values, ISO dates, and
52
+ high-cardinality categories. Missing and rare values are handled using the
53
+ fitted training data, and the same preprocessing is stored in the `.tl` file.
54
+
55
+ Models are saved as `.tl` files and can be loaded later:
56
+
57
+ ```python
58
+ model = tl.load("model.tl")
59
+ print(model.info())
60
+ ```
61
+
62
+ See the [documentation](docs/quickstart.md) for data formats, configuration,
63
+ checkpointing, and the command-line interface.
@@ -31,14 +31,23 @@ Once the task is known, `tensorless/auto/config.py` picks:
31
31
 
32
32
  - **model type**: `transformer` for text tasks, `mlp` for tabular tasks
33
33
  - **size** (`d_model`, `layers`, `heads`): scaled to dataset size, from
34
- a tiny 2-layer/64-dim model for a few hundred examples up to an
34
+ a tiny 2-layer/64-dim model for a few hundred effective text examples up to an
35
35
  8-layer/384-dim model for 50,000+ examples
36
36
 
37
+ For text corpora, effective examples include corpus character count, so a
38
+ single large `.txt` file is not treated like one training example. BPE
39
+ vocabulary size is also bounded from corpus character diversity rather than
40
+ always using a fixed oversized vocabulary.
41
+
37
42
  This is a heuristic, not a search — the goal is "a model that trains
38
43
  quickly and doesn't wildly overfit or underfit for typical dataset
39
44
  sizes," not the best possible architecture. Override any of it:
40
45
  `tl.train("./data", d_model=512, layers=6)`.
41
46
 
47
+ For a packaged English grammar starter corpus, use
48
+ `tl.pretrain(out="english.tl")`. It is intended for demos and smoke tests;
49
+ larger local corpora should be passed to `tl.train()`.
50
+
42
51
  ## 3. Hyperparameter selection
43
52
 
44
53
  Batch size, epoch count, learning rate, warmup steps, and the
@@ -40,6 +40,10 @@ Writes are atomic: Tensorless writes to a temporary file in the same
40
40
  directory and renames it into place, so a crash mid-write never leaves a
41
41
  corrupt checkpoint that would block resumption.
42
42
 
43
+ When loading `.tl` files, Tensorless fills compatible fields introduced by
44
+ older versions with safe defaults. Files created by a newer unsupported format
45
+ version are rejected with an upgrade message instead of being partially read.
46
+
43
47
  ## How resumption works
44
48
 
45
49
  When `tl.train()` finds a checkpoint whose `dataset_fingerprint` matches
@@ -47,7 +47,7 @@ defaults.
47
47
  | Field | Default | Description |
48
48
  |---|---|---|
49
49
  | `val_split` | `0.1` (if ≥50 examples, else `0`) | Fraction of data held out for validation |
50
- | `patience` | `5` | Epochs without improvement before stopping early |
50
+ | `patience` | `3` | Epochs without improvement before stopping early |
51
51
  | `min_delta` | `1e-4` | Minimum improvement to count as "improved" |
52
52
 
53
53
  ## Hardware
@@ -5,18 +5,7 @@ a commitment or timeline.
5
5
 
6
6
  ## Near-term
7
7
 
8
- - **Subword/BPE tokenization** as an alternative to the default
9
- character-level tokenizer, for better efficiency on larger text
10
- corpora
11
- - **`.tl` format migration** — forward-compatible loading of files
12
- written by older Tensorless versions
13
- - **Better tabular preprocessing** — handling of date/datetime columns,
14
- high-cardinality categorical columns, and more robust outlier handling
15
- for regression targets
16
8
  - **Progress bars** for training (currently plain print-based logging)
17
- - **`tl.train(..., resume=False)`** enforcement — currently `resume` is
18
- accepted in `TrainConfig` but the automatic resume decision doesn't
19
- yet fully respect an explicit `False` override in every code path
20
9
  - **Multi-GPU / distributed training** for larger datasets
21
10
 
22
11
  ## Medium-term
@@ -38,8 +27,6 @@ a commitment or timeline.
38
27
 
39
28
  - **Alternate backends** (JAX, a lightweight NumPy-only backend) behind
40
29
  the same `tl.train()`/`tl.load()` API
41
- - **Streaming/out-of-core training** for datasets too large to fit in
42
- memory
43
30
  - **Export to other formats** (ONNX, TorchScript) from a `.tl` file for
44
31
  deployment outside Python
45
32
 
@@ -38,6 +38,11 @@ A directory can mix multiple files of the *same* format (e.g. several
38
38
  plain text files with structured (JSON/CSV) files in the same directory
39
39
  raises a `DataError` asking you to separate them.
40
40
 
41
+ For tabular data, numeric columns are robustly scaled and missing values use
42
+ the training median. ISO-8601 date and datetime columns are converted to
43
+ numeric timestamps. Categorical columns are frequency-ranked and capped at
44
+ 1,000 learned values; rare or unseen values use the `<unk>` category.
45
+
41
46
  Tensorless never modifies, moves, or deletes files in your dataset
42
47
  directory. It only ever reads from `path`; all output goes to the `out`
43
48
  file and `checkpoint_dir`.
@@ -68,7 +73,9 @@ By default, Tensorless holds out `val_split` of the data (10% for
68
73
  datasets with 50+ examples, 0% for smaller ones where a held-out split
69
74
  wouldn't be meaningful) and tracks validation loss after each epoch. If
70
75
  validation loss doesn't improve by at least `min_delta` for `patience`
71
- consecutive epochs, training stops early.
76
+ consecutive epochs, training stops early. The automatic default is 3
77
+ consecutive epochs, and the completed model is still written to the `.tl`
78
+ output file.
72
79
 
73
80
  ## Checkpointing during training
74
81
 
@@ -81,8 +88,8 @@ for resumption.
81
88
 
82
89
  | Task | Model | What's learned |
83
90
  |---|---|---|
84
- | `text-generation` | Small GPT-style decoder transformer, char-level tokenizer | Next-character prediction over your text |
85
- | `text-classification` | Same transformer backbone, classification head on the final token | Text → one of your labeled classes |
91
+ | `text-generation` | Small GPT-style decoder transformer, BPE tokenizer by default | Next-token prediction over your text |
92
+ | `text-classification` | Same transformer backbone, BPE tokenizer by default, classification head on the final token | Text → one of your labeled classes |
86
93
  | `classification` | MLP with per-column categorical embeddings | Row of features → one of your labeled classes |
87
94
  | `regression` | Same MLP, single continuous output | Row of features → a number |
88
95
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tensorless"
7
- version = "0.2.0"
7
+ version = "0.3.0"
8
8
  description = "ML with maximum automation and minimum setup."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -22,3 +22,6 @@ tensorless = "tensorless.cli.main:main"
22
22
 
23
23
  [tool.setuptools.packages.find]
24
24
  include = ["tensorless*"]
25
+
26
+ [tool.setuptools.package-data]
27
+ tensorless = ["data/*.txt"]
@@ -12,7 +12,7 @@ ML with maximum automation and minimum setup.
12
12
  See https://github.com/tensorless/tensorless for full documentation.
13
13
  """
14
14
 
15
- from .api import train, run, load, inspect
15
+ from .api import train, pretrain, run, load, inspect
16
16
  from .config import TrainConfig
17
17
  from .errors import (
18
18
  TensorlessError,
@@ -26,6 +26,7 @@ from ._version import __version__
26
26
 
27
27
  __all__ = [
28
28
  "train",
29
+ "pretrain",
29
30
  "run",
30
31
  "load",
31
32
  "inspect",
@@ -12,6 +12,7 @@
12
12
  from __future__ import annotations
13
13
 
14
14
  import dataclasses
15
+ import importlib.resources
15
16
  import os
16
17
  from typing import Any, Optional
17
18
 
@@ -92,7 +93,7 @@ def train(path: str, **kwargs: Any) -> LoadedModel:
92
93
  return LoadedModel(existing)
93
94
 
94
95
  # 2. Is there an interrupted / matching checkpoint to resume from?
95
- if checkpoint_mgr.exists():
96
+ if checkpoint_mgr.exists() and user_cfg.resume is not False:
96
97
  ckpt = checkpoint_mgr.load()
97
98
  if ckpt.get("dataset_fingerprint") == fingerprint:
98
99
  if ckpt.get("training_complete"):
@@ -119,6 +120,10 @@ def train(path: str, **kwargs: Any) -> LoadedModel:
119
120
  "checkpoint -- retraining from scratch."
120
121
  )
121
122
  checkpoint_mgr.clear()
123
+ elif checkpoint_mgr.exists():
124
+ if user_cfg.verbose:
125
+ print("[tensorless] resume=False -- ignoring the existing checkpoint.")
126
+ checkpoint_mgr.clear()
122
127
  else:
123
128
  checkpoint_mgr.clear()
124
129
 
@@ -162,6 +167,17 @@ def train(path: str, **kwargs: Any) -> LoadedModel:
162
167
  return LoadedModel(payload)
163
168
 
164
169
 
170
+ def pretrain(
171
+ out: str = "english_pretrained.tl", language: str = "english", **kwargs: Any
172
+ ) -> LoadedModel:
173
+ """Pretrain a small language model on the built-in starter corpus."""
174
+ if language.lower() != "english":
175
+ raise ValueError("The built-in pretraining corpus currently supports only 'english'.")
176
+ corpus = importlib.resources.files("tensorless.data").joinpath("english_grammar.txt")
177
+ options = {"task": "text-generation", "out": out, **kwargs}
178
+ return train(str(corpus), **options)
179
+
180
+
165
181
  def _finalize_from_checkpoint(ckpt: dict, out: str, verbose: bool) -> LoadedModel:
166
182
  payload = {
167
183
  "tl_format_version": _tl_format_version,
@@ -43,15 +43,17 @@ def _auto_model_size(n_examples: int, kind: str):
43
43
  return 128, 4, 1, 2
44
44
 
45
45
 
46
- def _auto_batch_size(n_examples: int) -> int:
46
+ def _auto_batch_size(n_examples: int, max_seq_len: int) -> int:
47
+ token_budget = 8192
48
+ sequence_batch = max(1, token_budget // max_seq_len)
47
49
  if n_examples < 200:
48
- return 8
50
+ return min(8, sequence_batch)
49
51
  elif n_examples < 2000:
50
- return 16
52
+ return min(16, sequence_batch)
51
53
  elif n_examples < 20000:
52
- return 32
54
+ return min(32, sequence_batch)
53
55
  else:
54
- return 64
56
+ return min(64, sequence_batch)
55
57
 
56
58
 
57
59
  def _auto_epochs(n_examples: int) -> int:
@@ -65,8 +67,22 @@ def _auto_epochs(n_examples: int) -> int:
65
67
  return 5
66
68
 
67
69
 
70
+ def _effective_text_size(ds: Dataset) -> int:
71
+ """Estimate useful training examples for raw corpora."""
72
+ if ds.kind in ("text", "text_labeled"):
73
+ return max(len(ds), sum(len(text) for text in ds.texts) // 200)
74
+ return len(ds)
75
+
76
+
77
+ def _auto_vocab_size(ds: Dataset) -> int:
78
+ if ds.kind not in ("text", "text_labeled"):
79
+ return 1000
80
+ unique_chars = len(set("".join(ds.texts)))
81
+ return min(4096, max(64, unique_chars * 8))
82
+
83
+
68
84
  def resolve_config(ds: Dataset, user: TrainConfig) -> ResolvedConfig:
69
- n = len(ds)
85
+ n = _effective_text_size(ds)
70
86
  task = user.task or detect_task(ds)
71
87
  model_type = user.model_type or (
72
88
  "transformer" if task in ("text-generation", "text-classification") else "mlp"
@@ -82,6 +98,7 @@ def resolve_config(ds: Dataset, user: TrainConfig) -> ResolvedConfig:
82
98
  out = user.out or "model.tl"
83
99
  checkpoint_dir = user.checkpoint_dir or (out + ".ckpt")
84
100
 
101
+ max_seq_len = user.max_seq_len or (256 if ds.kind in ("text", "text_labeled") else 1)
85
102
  resolved = ResolvedConfig(
86
103
  out=out,
87
104
  force=bool(user.force),
@@ -94,19 +111,19 @@ def resolve_config(ds: Dataset, user: TrainConfig) -> ResolvedConfig:
94
111
  heads=user.heads or heads,
95
112
  ff_mult=user.ff_mult or ff_mult,
96
113
  dropout=user.dropout if user.dropout is not None else 0.1,
97
- max_seq_len=user.max_seq_len or (256 if ds.kind in ("text", "text_labeled") else 1),
114
+ max_seq_len=max_seq_len,
98
115
  tokenizer=tokenizer,
99
- bpe_vocab_size=user.bpe_vocab_size or 1000,
116
+ bpe_vocab_size=user.bpe_vocab_size if user.bpe_vocab_size is not None else _auto_vocab_size(ds),
100
117
  optimizer=user.optimizer or "adamw",
101
118
  learning_rate=user.learning_rate or (3e-4 if model_type == "transformer" else 1e-3),
102
119
  weight_decay=user.weight_decay if user.weight_decay is not None else 0.01,
103
- batch_size=user.batch_size or _auto_batch_size(n),
120
+ batch_size=user.batch_size if user.batch_size is not None else _auto_batch_size(n, max_seq_len),
104
121
  epochs=user.epochs or _auto_epochs(n),
105
122
  max_steps=user.max_steps,
106
123
  grad_clip=user.grad_clip if user.grad_clip is not None else 1.0,
107
124
  warmup_steps=user.warmup_steps if user.warmup_steps is not None else min(100, max(1, n // 10)),
108
125
  val_split=user.val_split if user.val_split is not None else (0.1 if n >= 50 else 0.0),
109
- patience=user.patience or 5,
126
+ patience=user.patience if user.patience is not None else 3,
110
127
  min_delta=user.min_delta if user.min_delta is not None else 1e-4,
111
128
  device=device,
112
129
  precision=precision,