trainproof 0.1.0__tar.gz → 0.2.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 (25) hide show
  1. trainproof-0.2.0/PKG-INFO +138 -0
  2. trainproof-0.2.0/README.md +126 -0
  3. {trainproof-0.1.0 → trainproof-0.2.0}/pyproject.toml +1 -1
  4. {trainproof-0.1.0 → trainproof-0.2.0}/src/trainproof/epoch.py +10 -0
  5. {trainproof-0.1.0 → trainproof-0.2.0}/src/trainproof/rules.py +10 -0
  6. trainproof-0.2.0/src/trainproof.egg-info/PKG-INFO +138 -0
  7. {trainproof-0.1.0 → trainproof-0.2.0}/tests/test_epoch.py +7 -0
  8. trainproof-0.1.0/PKG-INFO +0 -62
  9. trainproof-0.1.0/README.md +0 -50
  10. trainproof-0.1.0/src/trainproof.egg-info/PKG-INFO +0 -62
  11. {trainproof-0.1.0 → trainproof-0.2.0}/setup.cfg +0 -0
  12. {trainproof-0.1.0 → trainproof-0.2.0}/src/trainproof/__init__.py +0 -0
  13. {trainproof-0.1.0 → trainproof-0.2.0}/src/trainproof/adapters.py +0 -0
  14. {trainproof-0.1.0 → trainproof-0.2.0}/src/trainproof/cli.py +0 -0
  15. {trainproof-0.1.0 → trainproof-0.2.0}/src/trainproof/report.py +0 -0
  16. {trainproof-0.1.0 → trainproof-0.2.0}/src/trainproof/speech/__init__.py +0 -0
  17. {trainproof-0.1.0 → trainproof-0.2.0}/src/trainproof/speech/data.py +0 -0
  18. {trainproof-0.1.0 → trainproof-0.2.0}/src/trainproof/speech/tokenizer.py +0 -0
  19. {trainproof-0.1.0 → trainproof-0.2.0}/src/trainproof.egg-info/SOURCES.txt +0 -0
  20. {trainproof-0.1.0 → trainproof-0.2.0}/src/trainproof.egg-info/dependency_links.txt +0 -0
  21. {trainproof-0.1.0 → trainproof-0.2.0}/src/trainproof.egg-info/entry_points.txt +0 -0
  22. {trainproof-0.1.0 → trainproof-0.2.0}/src/trainproof.egg-info/requires.txt +0 -0
  23. {trainproof-0.1.0 → trainproof-0.2.0}/src/trainproof.egg-info/top_level.txt +0 -0
  24. {trainproof-0.1.0 → trainproof-0.2.0}/tests/test_adapters.py +0 -0
  25. {trainproof-0.1.0 → trainproof-0.2.0}/tests/test_data.py +0 -0
@@ -0,0 +1,138 @@
1
+ Metadata-Version: 2.4
2
+ Name: trainproof
3
+ Version: 0.2.0
4
+ Summary: A deterministic linter for ML training runs: dataset, tokenizer, and epoch logs.
5
+ Author-email: "Panagiotis (Panos) Gkilis" <bedvibe@bedvibe.studio>
6
+ License: MIT
7
+ Requires-Python: >=3.10
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: numpy
10
+ Requires-Dist: soundfile
11
+ Requires-Dist: ttsproof
12
+
13
+ # trainproof
14
+
15
+ [![PyPI](https://img.shields.io/pypi/v/trainproof)](https://pypi.org/project/trainproof/)
16
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
17
+
18
+ **A deterministic linter for ML training runs.** Point it at your dataset, your
19
+ tokenizer, or your first-epoch logs — it returns a PASS / WARN / FAIL verdict
20
+ with named findings and cited evidence, before you burn days of GPU time on a
21
+ run that was doomed at step 50.
22
+
23
+ No ML judging ML. No invented "confidence 97%". Every rule is a deterministic
24
+ threshold in [one auditable module](src/trainproof/rules.py), and every finding
25
+ cites the numbers that triggered it.
26
+
27
+ ```bash
28
+ pip install trainproof
29
+ ```
30
+
31
+ ## See a verdict in 60 seconds
32
+
33
+ This repo ships the real logs of five QLoRA fine-tuning runs (Qwen2.5-3B,
34
+ RTX 5080 — see the gallery below). Judge one right now:
35
+
36
+ ```bash
37
+ trainproof epoch examples/gallery/lr_hot/trainer_state.json --format hf
38
+ ```
39
+
40
+ ```text
41
+ [FAIL] Critical checks failed:
42
+ [FAIL] Loss curve is diverging.
43
+ Evidence: End loss 7.492 vs Min loss 1.398
44
+ [FAIL] Loss never improved over the run (dead run).
45
+ [WARN] Gradient norm spikes detected.
46
+ Evidence: Max gn 2649.75 > 10.0x median (0.55)
47
+ ```
48
+
49
+ ## Why this exists
50
+
51
+ The author lost a real 11-hour fine-tune to a failure nothing warned about.
52
+ Pointed retroactively at that run's 1MB Coqui Trainer log (2,501 logged steps),
53
+ trainproof's verdict: **FAIL — diverging**. The loss reached its minimum at 82%
54
+ of the run and ended 1.9x above it. Translation: the final two hours of GPU
55
+ time made the model measurably worse, and the checkpoint worth keeping had
56
+ already existed for hours. No tool in the stack said a word.
57
+
58
+ ## The fault-injection gallery
59
+
60
+ To validate the rules, the same QLoRA fine-tune (Qwen2.5-3B-Instruct, 4-bit,
61
+ LoRA r=16, 300 steps on Alpaca-cleaned) was run five times — once healthy, four
62
+ times with exactly one knob deliberately broken. Real runs, real logs, all
63
+ shipped in [`examples/gallery/`](examples/gallery/):
64
+
65
+ | Run | Sabotage | Verdict | Key evidence |
66
+ |---|---|---|---|
67
+ | `healthy` | none | **PASS** | loss 1.52 → 0.94, stable gradients |
68
+ | `lr_hot` | LR x100 (2e-2) | **FAIL** | diverging: end 7.49 vs min 1.40; grad spike 2650 vs median 0.55 |
69
+ | `lr_zero` | LR = 0 | **FAIL** | dead run: first-5 median 1.52 vs last-5 1.49 (<5% improvement); lr=0 on 100% of steps |
70
+ | `fp16_nan` | fp16 + hot LR, no clipping | **FAIL** | diverging: end 7.21 vs min 1.09 (grad scaling absorbed the intended NaN — the run diverged instead; reported as observed) |
71
+ | `bad_labels` | labels shuffled per-sequence | **WARN only** — see below | grad spike 23.3 vs median 1.09 |
72
+
73
+ ### The honest finding: loss curves cannot see corrupted data
74
+
75
+ The `bad_labels` run — whose shuffled labels make real learning impossible —
76
+ *reduced its loss by 62%* (18.9 → 5.75). The model was genuinely learning: not
77
+ the task, but the marginal token statistics of the garbage. From its own loss
78
+ curve, that is indistinguishable from healthy training (neural networks
79
+ famously fit random labels). **No single-run, loss-only rule can catch this
80
+ class of failure** — its real signature is *relative*: a loss floor ~6x higher
81
+ than a known-good run of the same task (5.59 vs 0.94).
82
+
83
+ That finding sets the roadmap: v0.3 is `trainproof compare <run> <baseline>` —
84
+ deterministic ratio rules against the healthy baseline you already have.
85
+ See [ROADMAP.md](ROADMAP.md). (The gallery also improved v0.2 itself: the
86
+ dead-run rule exists because `lr_zero` initially escaped with only a WARN.)
87
+
88
+ ## The three commands
89
+
90
+ ```bash
91
+ # 1. Dataset preflight (speech/TTS pack): audio integrity, transcript quality,
92
+ # duplicates, text-vs-audio duration mismatches
93
+ trainproof data /path/to/dataset_or_manifest.jsonl
94
+
95
+ # 2. Tokenizer preflight: vocabulary coverage, OOV rate, sequence blowouts,
96
+ # suspicious splits on numbers/dates
97
+ trainproof tokenizer my_tokenizer.model transcripts.txt
98
+
99
+ # 3. Training-run verdict: NaN/divergence/dead-run detection, gradient spikes,
100
+ # LR sanity, throughput — from log files, any framework
101
+ trainproof epoch logs/run.jsonl # exit code 1 on FAIL: CI-ready
102
+ ```
103
+
104
+ Each command prints the verdict, writes a self-contained HTML report, and sets
105
+ the process exit code — so it works as a CI gate out of the box.
106
+
107
+ ## Supported log formats
108
+
109
+ - HuggingFace Trainer (`trainer_state.json`)
110
+ - Coqui Trainer text logs (ANSI-colored `trainer_0_log.txt`)
111
+ - Generic JSONL / CSV (columns: step, loss, lr, grad_norm, time — all optional)
112
+
113
+ Auto-detected; override with `--format hf|coqui|jsonl|csv`. TensorBoard event
114
+ files are planned (Lightning console captures are TTY dumps, not logs, and
115
+ will not be supported).
116
+
117
+ ## Philosophy
118
+
119
+ 1. **Deterministic.** A rule fires or it doesn't. Thresholds live in one
120
+ module, commented, tunable.
121
+ 2. **Evidence-cited.** Every finding names the steps and values that triggered
122
+ it.
123
+ 3. **Honest about limits.** What the tool cannot detect is documented in the
124
+ README, not discovered by the user in production.
125
+
126
+ ## Family
127
+
128
+ trainproof judges training runs. Its sibling [ttsproof](https://github.com/Mormolykos/ttsproof)
129
+ judges TTS model *outputs* (structural audio checks, equivalence-aware WER/CER,
130
+ published method with DOI) — and trainproof builds on it for the speech
131
+ dataset checks.
132
+
133
+ ## Author
134
+
135
+ Panagiotis (Panos) Gkilis — [portfolio](https://tts.bedvibe.studio/portfolio/) ·
136
+ [bedvibe.studio](https://bedvibe.studio/)
137
+
138
+ MIT license.
@@ -0,0 +1,126 @@
1
+ # trainproof
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/trainproof)](https://pypi.org/project/trainproof/)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
5
+
6
+ **A deterministic linter for ML training runs.** Point it at your dataset, your
7
+ tokenizer, or your first-epoch logs — it returns a PASS / WARN / FAIL verdict
8
+ with named findings and cited evidence, before you burn days of GPU time on a
9
+ run that was doomed at step 50.
10
+
11
+ No ML judging ML. No invented "confidence 97%". Every rule is a deterministic
12
+ threshold in [one auditable module](src/trainproof/rules.py), and every finding
13
+ cites the numbers that triggered it.
14
+
15
+ ```bash
16
+ pip install trainproof
17
+ ```
18
+
19
+ ## See a verdict in 60 seconds
20
+
21
+ This repo ships the real logs of five QLoRA fine-tuning runs (Qwen2.5-3B,
22
+ RTX 5080 — see the gallery below). Judge one right now:
23
+
24
+ ```bash
25
+ trainproof epoch examples/gallery/lr_hot/trainer_state.json --format hf
26
+ ```
27
+
28
+ ```text
29
+ [FAIL] Critical checks failed:
30
+ [FAIL] Loss curve is diverging.
31
+ Evidence: End loss 7.492 vs Min loss 1.398
32
+ [FAIL] Loss never improved over the run (dead run).
33
+ [WARN] Gradient norm spikes detected.
34
+ Evidence: Max gn 2649.75 > 10.0x median (0.55)
35
+ ```
36
+
37
+ ## Why this exists
38
+
39
+ The author lost a real 11-hour fine-tune to a failure nothing warned about.
40
+ Pointed retroactively at that run's 1MB Coqui Trainer log (2,501 logged steps),
41
+ trainproof's verdict: **FAIL — diverging**. The loss reached its minimum at 82%
42
+ of the run and ended 1.9x above it. Translation: the final two hours of GPU
43
+ time made the model measurably worse, and the checkpoint worth keeping had
44
+ already existed for hours. No tool in the stack said a word.
45
+
46
+ ## The fault-injection gallery
47
+
48
+ To validate the rules, the same QLoRA fine-tune (Qwen2.5-3B-Instruct, 4-bit,
49
+ LoRA r=16, 300 steps on Alpaca-cleaned) was run five times — once healthy, four
50
+ times with exactly one knob deliberately broken. Real runs, real logs, all
51
+ shipped in [`examples/gallery/`](examples/gallery/):
52
+
53
+ | Run | Sabotage | Verdict | Key evidence |
54
+ |---|---|---|---|
55
+ | `healthy` | none | **PASS** | loss 1.52 → 0.94, stable gradients |
56
+ | `lr_hot` | LR x100 (2e-2) | **FAIL** | diverging: end 7.49 vs min 1.40; grad spike 2650 vs median 0.55 |
57
+ | `lr_zero` | LR = 0 | **FAIL** | dead run: first-5 median 1.52 vs last-5 1.49 (<5% improvement); lr=0 on 100% of steps |
58
+ | `fp16_nan` | fp16 + hot LR, no clipping | **FAIL** | diverging: end 7.21 vs min 1.09 (grad scaling absorbed the intended NaN — the run diverged instead; reported as observed) |
59
+ | `bad_labels` | labels shuffled per-sequence | **WARN only** — see below | grad spike 23.3 vs median 1.09 |
60
+
61
+ ### The honest finding: loss curves cannot see corrupted data
62
+
63
+ The `bad_labels` run — whose shuffled labels make real learning impossible —
64
+ *reduced its loss by 62%* (18.9 → 5.75). The model was genuinely learning: not
65
+ the task, but the marginal token statistics of the garbage. From its own loss
66
+ curve, that is indistinguishable from healthy training (neural networks
67
+ famously fit random labels). **No single-run, loss-only rule can catch this
68
+ class of failure** — its real signature is *relative*: a loss floor ~6x higher
69
+ than a known-good run of the same task (5.59 vs 0.94).
70
+
71
+ That finding sets the roadmap: v0.3 is `trainproof compare <run> <baseline>` —
72
+ deterministic ratio rules against the healthy baseline you already have.
73
+ See [ROADMAP.md](ROADMAP.md). (The gallery also improved v0.2 itself: the
74
+ dead-run rule exists because `lr_zero` initially escaped with only a WARN.)
75
+
76
+ ## The three commands
77
+
78
+ ```bash
79
+ # 1. Dataset preflight (speech/TTS pack): audio integrity, transcript quality,
80
+ # duplicates, text-vs-audio duration mismatches
81
+ trainproof data /path/to/dataset_or_manifest.jsonl
82
+
83
+ # 2. Tokenizer preflight: vocabulary coverage, OOV rate, sequence blowouts,
84
+ # suspicious splits on numbers/dates
85
+ trainproof tokenizer my_tokenizer.model transcripts.txt
86
+
87
+ # 3. Training-run verdict: NaN/divergence/dead-run detection, gradient spikes,
88
+ # LR sanity, throughput — from log files, any framework
89
+ trainproof epoch logs/run.jsonl # exit code 1 on FAIL: CI-ready
90
+ ```
91
+
92
+ Each command prints the verdict, writes a self-contained HTML report, and sets
93
+ the process exit code — so it works as a CI gate out of the box.
94
+
95
+ ## Supported log formats
96
+
97
+ - HuggingFace Trainer (`trainer_state.json`)
98
+ - Coqui Trainer text logs (ANSI-colored `trainer_0_log.txt`)
99
+ - Generic JSONL / CSV (columns: step, loss, lr, grad_norm, time — all optional)
100
+
101
+ Auto-detected; override with `--format hf|coqui|jsonl|csv`. TensorBoard event
102
+ files are planned (Lightning console captures are TTY dumps, not logs, and
103
+ will not be supported).
104
+
105
+ ## Philosophy
106
+
107
+ 1. **Deterministic.** A rule fires or it doesn't. Thresholds live in one
108
+ module, commented, tunable.
109
+ 2. **Evidence-cited.** Every finding names the steps and values that triggered
110
+ it.
111
+ 3. **Honest about limits.** What the tool cannot detect is documented in the
112
+ README, not discovered by the user in production.
113
+
114
+ ## Family
115
+
116
+ trainproof judges training runs. Its sibling [ttsproof](https://github.com/Mormolykos/ttsproof)
117
+ judges TTS model *outputs* (structural audio checks, equivalence-aware WER/CER,
118
+ published method with DOI) — and trainproof builds on it for the speech
119
+ dataset checks.
120
+
121
+ ## Author
122
+
123
+ Panagiotis (Panos) Gkilis — [portfolio](https://tts.bedvibe.studio/portfolio/) ·
124
+ [bedvibe.studio](https://bedvibe.studio/)
125
+
126
+ MIT license.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "trainproof"
3
- version = "0.1.0"
3
+ version = "0.2.0"
4
4
  description = "A deterministic linter for ML training runs: dataset, tokenizer, and epoch logs."
5
5
  authors = [{name = "Panagiotis (Panos) Gkilis", email = "bedvibe@bedvibe.studio"}]
6
6
  readme = "README.md"
@@ -67,6 +67,16 @@ def check_epoch(log_path: str | Path, fmt: str = "auto") -> dict[str, Any]:
67
67
  findings.append({"level": "FAIL", "message": "Loss curve is diverging.", "evidence": f"End loss {valid_losses[-1]:.3f} vs Min loss {min_loss:.3f}"})
68
68
  verdict = "FAIL"
69
69
 
70
+ # Check no-improvement (dead run): robust start-vs-end median comparison
71
+ if len(valid_losses) >= rules.MIN_POINTS_FOR_IMPROVEMENT_CHECK:
72
+ w = rules.LOSS_IMPROVEMENT_WINDOW
73
+ start_med = sorted(valid_losses[:w])[w // 2]
74
+ end_med = sorted(valid_losses[-w:])[w // 2]
75
+ if start_med > 0 and end_med >= start_med * (1 - rules.MIN_LOSS_IMPROVEMENT):
76
+ findings.append({"level": "FAIL", "message": "Loss never improved over the run (dead run).",
77
+ "evidence": f"median of first {w} losses {start_med:.3f} vs last {w} {end_med:.3f} (needs >={rules.MIN_LOSS_IMPROVEMENT*100:.0f}% improvement)"})
78
+ verdict = "FAIL"
79
+
70
80
  # Check Grad Norm
71
81
  valid_gns = [g for g in grad_norms if not math.isnan(g) and not math.isinf(g)]
72
82
  if valid_gns and len(valid_gns) > 5:
@@ -51,3 +51,13 @@ MAX_GRAD_NORM_SPIKE_RATIO = 10.0
51
51
 
52
52
  # If the learning rate is strictly zero for more than this fraction of the epoch, it's a warning.
53
53
  MAX_ZERO_LR_FRACTION = 0.1
54
+
55
+ # Dead-run detection (added in v0.2 after fault-injection testing showed that
56
+ # zero-LR and garbage-label runs — which can never learn — only earned WARNs):
57
+ # the median of the last LOSS_IMPROVEMENT_WINDOW losses must be at least
58
+ # MIN_LOSS_IMPROVEMENT (relative) below the median of the first window, else
59
+ # the run never learned. Note: this targets FIRST-EPOCH linting; a model
60
+ # resumed at its convergence floor would also trip it.
61
+ MIN_LOSS_IMPROVEMENT = 0.05
62
+ LOSS_IMPROVEMENT_WINDOW = 5
63
+ MIN_POINTS_FOR_IMPROVEMENT_CHECK = 10
@@ -0,0 +1,138 @@
1
+ Metadata-Version: 2.4
2
+ Name: trainproof
3
+ Version: 0.2.0
4
+ Summary: A deterministic linter for ML training runs: dataset, tokenizer, and epoch logs.
5
+ Author-email: "Panagiotis (Panos) Gkilis" <bedvibe@bedvibe.studio>
6
+ License: MIT
7
+ Requires-Python: >=3.10
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: numpy
10
+ Requires-Dist: soundfile
11
+ Requires-Dist: ttsproof
12
+
13
+ # trainproof
14
+
15
+ [![PyPI](https://img.shields.io/pypi/v/trainproof)](https://pypi.org/project/trainproof/)
16
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
17
+
18
+ **A deterministic linter for ML training runs.** Point it at your dataset, your
19
+ tokenizer, or your first-epoch logs — it returns a PASS / WARN / FAIL verdict
20
+ with named findings and cited evidence, before you burn days of GPU time on a
21
+ run that was doomed at step 50.
22
+
23
+ No ML judging ML. No invented "confidence 97%". Every rule is a deterministic
24
+ threshold in [one auditable module](src/trainproof/rules.py), and every finding
25
+ cites the numbers that triggered it.
26
+
27
+ ```bash
28
+ pip install trainproof
29
+ ```
30
+
31
+ ## See a verdict in 60 seconds
32
+
33
+ This repo ships the real logs of five QLoRA fine-tuning runs (Qwen2.5-3B,
34
+ RTX 5080 — see the gallery below). Judge one right now:
35
+
36
+ ```bash
37
+ trainproof epoch examples/gallery/lr_hot/trainer_state.json --format hf
38
+ ```
39
+
40
+ ```text
41
+ [FAIL] Critical checks failed:
42
+ [FAIL] Loss curve is diverging.
43
+ Evidence: End loss 7.492 vs Min loss 1.398
44
+ [FAIL] Loss never improved over the run (dead run).
45
+ [WARN] Gradient norm spikes detected.
46
+ Evidence: Max gn 2649.75 > 10.0x median (0.55)
47
+ ```
48
+
49
+ ## Why this exists
50
+
51
+ The author lost a real 11-hour fine-tune to a failure nothing warned about.
52
+ Pointed retroactively at that run's 1MB Coqui Trainer log (2,501 logged steps),
53
+ trainproof's verdict: **FAIL — diverging**. The loss reached its minimum at 82%
54
+ of the run and ended 1.9x above it. Translation: the final two hours of GPU
55
+ time made the model measurably worse, and the checkpoint worth keeping had
56
+ already existed for hours. No tool in the stack said a word.
57
+
58
+ ## The fault-injection gallery
59
+
60
+ To validate the rules, the same QLoRA fine-tune (Qwen2.5-3B-Instruct, 4-bit,
61
+ LoRA r=16, 300 steps on Alpaca-cleaned) was run five times — once healthy, four
62
+ times with exactly one knob deliberately broken. Real runs, real logs, all
63
+ shipped in [`examples/gallery/`](examples/gallery/):
64
+
65
+ | Run | Sabotage | Verdict | Key evidence |
66
+ |---|---|---|---|
67
+ | `healthy` | none | **PASS** | loss 1.52 → 0.94, stable gradients |
68
+ | `lr_hot` | LR x100 (2e-2) | **FAIL** | diverging: end 7.49 vs min 1.40; grad spike 2650 vs median 0.55 |
69
+ | `lr_zero` | LR = 0 | **FAIL** | dead run: first-5 median 1.52 vs last-5 1.49 (<5% improvement); lr=0 on 100% of steps |
70
+ | `fp16_nan` | fp16 + hot LR, no clipping | **FAIL** | diverging: end 7.21 vs min 1.09 (grad scaling absorbed the intended NaN — the run diverged instead; reported as observed) |
71
+ | `bad_labels` | labels shuffled per-sequence | **WARN only** — see below | grad spike 23.3 vs median 1.09 |
72
+
73
+ ### The honest finding: loss curves cannot see corrupted data
74
+
75
+ The `bad_labels` run — whose shuffled labels make real learning impossible —
76
+ *reduced its loss by 62%* (18.9 → 5.75). The model was genuinely learning: not
77
+ the task, but the marginal token statistics of the garbage. From its own loss
78
+ curve, that is indistinguishable from healthy training (neural networks
79
+ famously fit random labels). **No single-run, loss-only rule can catch this
80
+ class of failure** — its real signature is *relative*: a loss floor ~6x higher
81
+ than a known-good run of the same task (5.59 vs 0.94).
82
+
83
+ That finding sets the roadmap: v0.3 is `trainproof compare <run> <baseline>` —
84
+ deterministic ratio rules against the healthy baseline you already have.
85
+ See [ROADMAP.md](ROADMAP.md). (The gallery also improved v0.2 itself: the
86
+ dead-run rule exists because `lr_zero` initially escaped with only a WARN.)
87
+
88
+ ## The three commands
89
+
90
+ ```bash
91
+ # 1. Dataset preflight (speech/TTS pack): audio integrity, transcript quality,
92
+ # duplicates, text-vs-audio duration mismatches
93
+ trainproof data /path/to/dataset_or_manifest.jsonl
94
+
95
+ # 2. Tokenizer preflight: vocabulary coverage, OOV rate, sequence blowouts,
96
+ # suspicious splits on numbers/dates
97
+ trainproof tokenizer my_tokenizer.model transcripts.txt
98
+
99
+ # 3. Training-run verdict: NaN/divergence/dead-run detection, gradient spikes,
100
+ # LR sanity, throughput — from log files, any framework
101
+ trainproof epoch logs/run.jsonl # exit code 1 on FAIL: CI-ready
102
+ ```
103
+
104
+ Each command prints the verdict, writes a self-contained HTML report, and sets
105
+ the process exit code — so it works as a CI gate out of the box.
106
+
107
+ ## Supported log formats
108
+
109
+ - HuggingFace Trainer (`trainer_state.json`)
110
+ - Coqui Trainer text logs (ANSI-colored `trainer_0_log.txt`)
111
+ - Generic JSONL / CSV (columns: step, loss, lr, grad_norm, time — all optional)
112
+
113
+ Auto-detected; override with `--format hf|coqui|jsonl|csv`. TensorBoard event
114
+ files are planned (Lightning console captures are TTY dumps, not logs, and
115
+ will not be supported).
116
+
117
+ ## Philosophy
118
+
119
+ 1. **Deterministic.** A rule fires or it doesn't. Thresholds live in one
120
+ module, commented, tunable.
121
+ 2. **Evidence-cited.** Every finding names the steps and values that triggered
122
+ it.
123
+ 3. **Honest about limits.** What the tool cannot detect is documented in the
124
+ README, not discovered by the user in production.
125
+
126
+ ## Family
127
+
128
+ trainproof judges training runs. Its sibling [ttsproof](https://github.com/Mormolykos/ttsproof)
129
+ judges TTS model *outputs* (structural audio checks, equivalence-aware WER/CER,
130
+ published method with DOI) — and trainproof builds on it for the speech
131
+ dataset checks.
132
+
133
+ ## Author
134
+
135
+ Panagiotis (Panos) Gkilis — [portfolio](https://tts.bedvibe.studio/portfolio/) ·
136
+ [bedvibe.studio](https://bedvibe.studio/)
137
+
138
+ MIT license.
@@ -34,3 +34,10 @@ def test_epoch_flat():
34
34
  report = check_epoch(FIXTURES_DIR / "flat.jsonl")
35
35
  assert report["verdict"] == "FAIL"
36
36
  assert any("completely flat" in str(f) for f in report["findings"])
37
+
38
+ def test_epoch_dead_noisy():
39
+ # noisy-but-never-improving loss with healthy lr: only the no-improvement
40
+ # rule (v0.2) can catch this dead run
41
+ report = check_epoch(FIXTURES_DIR / "dead_noisy.jsonl")
42
+ assert report["verdict"] == "FAIL"
43
+ assert any("never improved" in str(f) for f in report["findings"])
trainproof-0.1.0/PKG-INFO DELETED
@@ -1,62 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: trainproof
3
- Version: 0.1.0
4
- Summary: A deterministic linter for ML training runs: dataset, tokenizer, and epoch logs.
5
- Author-email: "Panagiotis (Panos) Gkilis" <bedvibe@bedvibe.studio>
6
- License: MIT
7
- Requires-Python: >=3.10
8
- Description-Content-Type: text/markdown
9
- Requires-Dist: numpy
10
- Requires-Dist: soundfile
11
- Requires-Dist: ttsproof
12
-
13
- # Trainproof
14
-
15
- A deterministic linter for ML training runs. Run it on your dataset, tokenizer, and first-epoch logs — it gives a deterministic PASS/WARN/FAIL verdict with named findings and suggested fixes, BEFORE you burn weeks of GPU time.
16
-
17
- ## Installation
18
- ```bash
19
- pip install .
20
- ```
21
-
22
- ## Usage
23
-
24
- Exactly three subcommands:
25
-
26
- ### 1. Dataset Preflight
27
- ```bash
28
- trainproof data /path/to/dataset
29
- ```
30
- Checks audio integrity (clipping, silence, duration distribution) and transcript quality (unnormalized text, charset audit, duration correlation).
31
-
32
- ### 2. Tokenizer Preflight
33
- ```bash
34
- trainproof tokenizer my_model.model transcripts.txt
35
- ```
36
- Checks vocabulary coverage, tokens-per-second, and suspicious splits on numbers/dates.
37
-
38
- ### 3. First-Epoch Verification
39
- ```bash
40
- trainproof epoch logs/epoch1.jsonl
41
- ```
42
- Analyzes loss curves (divergence, flatlines, NaN), grad norms, learning rate response, and throughput.
43
-
44
- ## Supported log formats
45
- - **Generic JSONL / CSV**
46
- - **HuggingFace** (`trainer_state.json`)
47
- - **Coqui TTS Trainer** (plain text `trainer_0_log.txt`)
48
-
49
- *Roadmap: TensorBoard event files planned (v0.2) — Lightning console captures are TTY dumps, not logs, and will not be supported.*
50
-
51
- ## Verdict Rules
52
- All verdict rules are deterministic thresholds defined centrally in `src/trainproof/rules.py`. Examples include:
53
- - `MAX_CLIPPING_PEAK = 0.99`
54
- - `MAX_LOSS_DIVERGENCE_RATIO = 1.5`
55
- - `MIN_VOCAB_COVERAGE = 0.999`
56
-
57
- ## Explicit Non-Goals
58
- - No live learning-rate auto-adjustment.
59
- - No PyTorch/Lightning callbacks or framework hooks (log files only).
60
- - No MCP server, no LLM integration.
61
- - No dashboards/wandb-style UI.
62
- - No extra features beyond this spec.
@@ -1,50 +0,0 @@
1
- # Trainproof
2
-
3
- A deterministic linter for ML training runs. Run it on your dataset, tokenizer, and first-epoch logs — it gives a deterministic PASS/WARN/FAIL verdict with named findings and suggested fixes, BEFORE you burn weeks of GPU time.
4
-
5
- ## Installation
6
- ```bash
7
- pip install .
8
- ```
9
-
10
- ## Usage
11
-
12
- Exactly three subcommands:
13
-
14
- ### 1. Dataset Preflight
15
- ```bash
16
- trainproof data /path/to/dataset
17
- ```
18
- Checks audio integrity (clipping, silence, duration distribution) and transcript quality (unnormalized text, charset audit, duration correlation).
19
-
20
- ### 2. Tokenizer Preflight
21
- ```bash
22
- trainproof tokenizer my_model.model transcripts.txt
23
- ```
24
- Checks vocabulary coverage, tokens-per-second, and suspicious splits on numbers/dates.
25
-
26
- ### 3. First-Epoch Verification
27
- ```bash
28
- trainproof epoch logs/epoch1.jsonl
29
- ```
30
- Analyzes loss curves (divergence, flatlines, NaN), grad norms, learning rate response, and throughput.
31
-
32
- ## Supported log formats
33
- - **Generic JSONL / CSV**
34
- - **HuggingFace** (`trainer_state.json`)
35
- - **Coqui TTS Trainer** (plain text `trainer_0_log.txt`)
36
-
37
- *Roadmap: TensorBoard event files planned (v0.2) — Lightning console captures are TTY dumps, not logs, and will not be supported.*
38
-
39
- ## Verdict Rules
40
- All verdict rules are deterministic thresholds defined centrally in `src/trainproof/rules.py`. Examples include:
41
- - `MAX_CLIPPING_PEAK = 0.99`
42
- - `MAX_LOSS_DIVERGENCE_RATIO = 1.5`
43
- - `MIN_VOCAB_COVERAGE = 0.999`
44
-
45
- ## Explicit Non-Goals
46
- - No live learning-rate auto-adjustment.
47
- - No PyTorch/Lightning callbacks or framework hooks (log files only).
48
- - No MCP server, no LLM integration.
49
- - No dashboards/wandb-style UI.
50
- - No extra features beyond this spec.
@@ -1,62 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: trainproof
3
- Version: 0.1.0
4
- Summary: A deterministic linter for ML training runs: dataset, tokenizer, and epoch logs.
5
- Author-email: "Panagiotis (Panos) Gkilis" <bedvibe@bedvibe.studio>
6
- License: MIT
7
- Requires-Python: >=3.10
8
- Description-Content-Type: text/markdown
9
- Requires-Dist: numpy
10
- Requires-Dist: soundfile
11
- Requires-Dist: ttsproof
12
-
13
- # Trainproof
14
-
15
- A deterministic linter for ML training runs. Run it on your dataset, tokenizer, and first-epoch logs — it gives a deterministic PASS/WARN/FAIL verdict with named findings and suggested fixes, BEFORE you burn weeks of GPU time.
16
-
17
- ## Installation
18
- ```bash
19
- pip install .
20
- ```
21
-
22
- ## Usage
23
-
24
- Exactly three subcommands:
25
-
26
- ### 1. Dataset Preflight
27
- ```bash
28
- trainproof data /path/to/dataset
29
- ```
30
- Checks audio integrity (clipping, silence, duration distribution) and transcript quality (unnormalized text, charset audit, duration correlation).
31
-
32
- ### 2. Tokenizer Preflight
33
- ```bash
34
- trainproof tokenizer my_model.model transcripts.txt
35
- ```
36
- Checks vocabulary coverage, tokens-per-second, and suspicious splits on numbers/dates.
37
-
38
- ### 3. First-Epoch Verification
39
- ```bash
40
- trainproof epoch logs/epoch1.jsonl
41
- ```
42
- Analyzes loss curves (divergence, flatlines, NaN), grad norms, learning rate response, and throughput.
43
-
44
- ## Supported log formats
45
- - **Generic JSONL / CSV**
46
- - **HuggingFace** (`trainer_state.json`)
47
- - **Coqui TTS Trainer** (plain text `trainer_0_log.txt`)
48
-
49
- *Roadmap: TensorBoard event files planned (v0.2) — Lightning console captures are TTY dumps, not logs, and will not be supported.*
50
-
51
- ## Verdict Rules
52
- All verdict rules are deterministic thresholds defined centrally in `src/trainproof/rules.py`. Examples include:
53
- - `MAX_CLIPPING_PEAK = 0.99`
54
- - `MAX_LOSS_DIVERGENCE_RATIO = 1.5`
55
- - `MIN_VOCAB_COVERAGE = 0.999`
56
-
57
- ## Explicit Non-Goals
58
- - No live learning-rate auto-adjustment.
59
- - No PyTorch/Lightning callbacks or framework hooks (log files only).
60
- - No MCP server, no LLM integration.
61
- - No dashboards/wandb-style UI.
62
- - No extra features beyond this spec.
File without changes