Skip to content

MinGram downstream: bnd_w, and the placement ablation - #13

Merged
sanderland merged 1 commit into
sanderland:claude/fineweb-space-neighbors-k10ufwfrom
cimeister:claude/mingram-five-arms
Aug 4, 2026
Merged

MinGram downstream: bnd_w, and the placement ablation#13
sanderland merged 1 commit into
sanderland:claude/fineweb-space-neighbors-k10ufwfrom
cimeister:claude/mingram-five-arms

Conversation

@cimeister

Copy link
Copy Markdown

Nine runs, three arms by three seeds, jobs 2998893-95, every setting matched to the committed BPE and MinGram runs. results_mingram.tsv goes from 6 rows to 15, so the main table's MinGram column for bnd_w is filled in rather than blank.

Cut from 6b6ba63 and fast-forwards.

scheme BPE MinGram
plain 0.8853 ± 0.0003 0.8837 ± 0.0008
bnd_w 0.8768 ± 0.0008 0.8763 ± 0.0003
bnd_wpd 0.8800 ± 0.0005 0.8805 ± 0.0006

One number worth a look before the placement ablation stays dropped. 90cbf37 took it out of the downstream tables, so bnd_wpd_caps and bnd_wpd_extcaps appear here only in the TSV. Paired by seed, positive meaning the second arm is lower:

comparison MinGram BPE
bnd_wpd_caps vs bnd_wpd_extcaps +0.004034, t(2) = 26.5 +0.000247, t(2) = 1.1

Indistinguishable under BPE, and under MinGram larger than the whole plain-to-bnd_wpd effect. There is a mechanism: with the code outside the markers the lower-cased span is a suffix of the cased form, so one word entry serves both, and MinGram prunes an overshot vocabulary with EM rather than growing greedily. Your commit adding the arm said the probe corpus could not answer this. Entirely your call whether it earns a place back.

bnd_w at 0.876321 is close to extcaps but confounded: its byte factor is 0.8630 against plain's 1.0006, so it emits more tokens per byte. caps against extcaps is not, 0.8426 against 0.8444.

Three seeds per arm. The t values are large because the seed spread is small.

Checked before reporting, since three earlier sweeps here produced plausible numbers that were wrong: the gain is in the raw bpb (1.0375 against 1.0444), not the byte-factor correction, whose two values differ by 0.21%; each arm has its own token_bytes.pt; every run evaluated --step 2553, the checkpoint it had just trained; each tokenizer's sha256 matches what the in-job gate recorded; and the per-seed data permutations differ while being shared across arms, which is what makes the pairing valid. The tables regenerate byte for byte with your current generator.

One change outside the results. smoke_test.py takes --corpus, so --require-matched-vocab compares within one corpus and trainer. Without it the pattern matched all 75 MinGram tokenizers and demanded a single vocabulary across every corpus, so fineweb_ru_5gb_plain_mingram at 34,684 aborted all nine runs before any training. Verified both ways: the English arms pass, and asking for fineweb_ru_5gb still refuses. That Russian cell is one token short because the MinGram trainer checks the target outside its inner EM loop (script_bpe/tokenizers/mingram/trainer.py:57-64), so pruning continues after the target is reached; manifest.json here is merged with --no-check and the check still reports it.

Nine runs, three arms by three seeds, jobs 2998893-95, every setting matched to the
committed BPE and MinGram runs. results_mingram.tsv goes from 6 rows to 15, and the main
table's MinGram column for bnd_w is filled in rather than blank.

Validation bits per true byte, seeds 0 to 2:

    plain             0.883694  (sd 0.000808)
    bnd_wpd           0.880507  (sd 0.000625)
    bnd_wpd_caps      0.880076  (sd 0.000105)
    bnd_w             0.876321  (sd 0.000251)
    bnd_wpd_extcaps   0.876042  (sd 0.000232)

Paired by seed, positive meaning the second arm is lower, MinGram against BPE:

    plain vs bnd_wpd           +0.003187 t(2)=15.2   |  +0.005317 t(2)=16.7
    plain vs bnd_wpd_caps      +0.003618 t(2)= 7.8   |  +0.005779 t(2)=23.6
    plain vs bnd_wpd_extcaps   +0.007652 t(2)=12.8   |  +0.006026 t(2)=47.0
    caps vs extcaps            +0.004034 t(2)=26.5   |  +0.000247 t(2)= 1.1

The placement ablation is out of the downstream tables by your choice in 90cbf37, so those
two arms appear only in results_mingram.tsv. The number is worth a look before it stays
dropped: the caps-code placement is indistinguishable under BPE, t(2)=1.1, and under
MinGram placing the code outside the markers is better by 0.004034 at t(2)=26.5, larger
than the whole plain-to-bnd_wpd effect. With the code outside, the lower-cased span is a
suffix of the cased form, so one word entry serves both, and MinGram prunes an overshot
vocabulary with EM rather than growing greedily.

bnd_w lands at 0.876321, close to extcaps, but its byte factor is 0.8630 against plain's
1.0006, so it emits more tokens per byte and buys part of that with extra forward passes.
caps against extcaps is not confounded that way: 0.8426 against 0.8444.

Three seeds per arm. The t values are large because the seed spread is small.

Checked before reporting, since three earlier sweeps produced plausible numbers that were
wrong: the gain is in the raw bpb (1.0375 against 1.0444), not the byte-factor correction,
whose values differ by 0.21%; each arm has its own token_bytes.pt; every run evaluated
--step 2553, the checkpoint it had just trained; each tokenizer's sha256 matches what the
in-job gate recorded; and the per-seed data permutations differ while being shared across
arms, which is what makes the pairing valid.

smoke_test.py takes --corpus so that --require-matched-vocab compares within one corpus and
trainer. Without it the pattern matched all 75 MinGram tokenizers and demanded a single
vocabulary across every corpus, so fineweb_ru_5gb_plain_mingram at 34,684 aborted all nine
runs before any training. Verified both ways: the English arms pass, and asking for
fineweb_ru_5gb still refuses.

manifest.json is merged with --no-check so the two new tokenizers appear; the check still
reports that Russian cell.
@sanderland
sanderland merged commit 43886d6 into sanderland:claude/fineweb-space-neighbors-k10ufw Aug 4, 2026
1 check passed
sanderland added a commit that referenced this pull request Aug 5, 2026
A reproduction directory in the shape of the other three papers, and one
pretokenizer configured by options instead of three classes.

    ./paper_utils/boundary/run_all_experiments.sh

regenerates every table from the caches committed under paper/generated/ -- no
GPU, no trained tokenizer, about a second. GRID=1 retrains the tokenizer grid,
DOWNSTREAM=1 reruns the LM sweep and exits with a usable message where there is
no CUDA.

The pretokenizer

  BoundaryScriptPretokenizer is the only class. Case codes always sit outside
  the span's markers and are applied only to a span that carries case; the
  inside-the-markers placement and the version with no case test are gone.
  Options replace the subclasses:

    boundary_targets  ("punct",) by default -- "word" is not a member, since
                      word spans are always delimited
    shift_code        <^>  title case
    caps_code         <^^> all caps
    min_caps_length   shortest span <^^> may cover, 2
    single_char_shift whether "A" is shift-coded, True

  The defaults reproduce the reported arm exactly, so the committed caches keep
  describing the default configuration. Verified before converting anything:
  encode and decode agree with the old classes on 263 texts x 6 variants x 3
  digit_handling settings, 0 mismatches. All 164 trained tokenizers embed their
  config, so they were rewritten in place -- 84 converted, 56 deleted as cells
  of the two removed schemes, 24 baselines untouched -- and each converted file
  was checked by loading it and hash-matching the freshly built variant.

  tests/test_boundary.py merges the two old suites and covers each option, 1412
  tests.

The tables

  table_intrinsic_main.tex and table_downstream_main.tex regenerate
  byte-identical apart from the header naming the new script path.

  bnd_wpd_extcapsfix is renamed bnd_wpd_caps across every cache. The
  full-corpus cells are dropped: the paper reports the quick sample, the full
  grid was 48 of a possible 108, and one cell (fineweb_ru_5gb_plain_mingram)
  had landed at 34,684 against 34,685 everywhere else, which made
  merge_manifests refuse to write. That cell is one token short because the
  MinGram trainer tests the target outside its inner EM loop
  (script_bpe/tokenizers/mingram/trainer.py:57-64), which is not fixed here.

  make_tex_tables reads round-trip failures from eval_goldfish.json, which
  measures every cell, rather than from manifest entries only a cell trained
  with an --eval-texts slice ever had.

  make_example_table.py generates the worked pre-tokenization example. It runs
  the pretokenizers directly, before any vocabulary is learned, so it needs no
  trained tokenizer and no corpus, and it reproduces the paper's table byte for
  byte with the counts computed rather than typed.

Picked up from #13, which merged after this branch was cut

  results_mingram.tsv gains nine runs, so the MinGram column has no missing
  cell: bnd_w at 0.8763 and the case codes at 0.8760. Its bnd_wpd_extcaps is
  this branch's bnd_wpd_caps; its bnd_wpd_caps was the inside-the-markers
  placement and is dropped as the BPE one was. Also smoke_test.py --corpus,
  without which --require-matched-vocab compares across every corpus at once
  and one short cell anywhere aborts every run.

Deleted

  The superseded FineWiki grids, probes and prototypes; 62 MB of FineWiki 32k
  tokenizers; the root session logs; and the bits-per-byte-against-compression
  figure, which is not in the paper. The 170 MB of matched tokenizers, the
  generated .tex and the per-cell manifest fragments are untracked but kept
  locally -- manifest.json holds exactly the fragments' union, so tracking both
  committed the same 60 entries twice. What stays in git is 480 KB.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W7F6Ac72HbPG15ExjkbFFu
sanderland added a commit that referenced this pull request Aug 5, 2026
A reproduction directory in the shape of the other three papers, and one
pretokenizer configured by options instead of three classes.

    ./paper_utils/boundary/run_all_experiments.sh

regenerates every table from the caches committed under paper/generated/ -- no
GPU, no trained tokenizer, about a second. GRID=1 retrains the tokenizer grid,
DOWNSTREAM=1 reruns the LM sweep and exits with a usable message where there is
no CUDA.

The pretokenizer

  BoundaryScriptPretokenizer is the only class. Case codes always sit outside
  the span's markers and are applied only to a span that carries case; the
  inside-the-markers placement and the version with no case test are gone.
  Options replace the subclasses:

    boundary_targets  ("punct",) by default -- "word" is not a member, since
                      word spans are always delimited
    shift_code        <^>  title case
    caps_code         <^^> all caps
    min_caps_length   shortest span <^^> may cover, 2
    single_char_shift whether "A" is shift-coded, True

  The defaults reproduce the reported arm exactly, so the committed caches keep
  describing the default configuration. Verified before converting anything:
  encode and decode agree with the old classes on 263 texts x 6 variants x 3
  digit_handling settings, 0 mismatches. All 164 trained tokenizers embed their
  config, so they were rewritten in place -- 84 converted, 56 deleted as cells
  of the two removed schemes, 24 baselines untouched -- and each converted file
  was checked by loading it and hash-matching the freshly built variant.

  tests/test_boundary.py merges the two old suites and covers each option, 1412
  tests.

The tables

  table_intrinsic_main.tex and table_downstream_main.tex regenerate
  byte-identical apart from the header naming the new script path.

  bnd_wpd_extcapsfix is renamed bnd_wpd_caps across every cache. The
  full-corpus cells are dropped: the paper reports the quick sample, the full
  grid was 48 of a possible 108, and one cell (fineweb_ru_5gb_plain_mingram)
  had landed at 34,684 against 34,685 everywhere else, which made
  merge_manifests refuse to write. That cell is one token short because the
  MinGram trainer tests the target outside its inner EM loop
  (script_bpe/tokenizers/mingram/trainer.py:57-64), which is not fixed here.

  make_tex_tables reads round-trip failures from eval_goldfish.json, which
  measures every cell, rather than from manifest entries only a cell trained
  with an --eval-texts slice ever had.

  make_example_table.py generates the worked pre-tokenization example. It runs
  the pretokenizers directly, before any vocabulary is learned, so it needs no
  trained tokenizer and no corpus, and it reproduces the paper's table byte for
  byte with the counts computed rather than typed.

Downstream

  run_arms.sh is a plain sequential driver: it trains the matched tokenizers,
  gates them, precomputes the byte factors, and then calls
  run_downstream_eval.py once per arm x seed. Scheduling is left to whoever
  reproduces it -- each model is one invocation of that script, and runs are
  skip-if-done, so cells can be submitted anywhere and a re-run fills in the
  rest. The CSCS Clariden job scripts, their site-specific environment and the
  README describing that flow are deleted, as are the preflight and
  corpus-prebuilding helpers that only existed to pack those jobs.

  results_mingram.tsv takes the nine runs from #13, so the MinGram column has
  no missing cell: bnd_w at 0.8763 and the case codes at 0.8760.

Deleted

  The superseded FineWiki grids, probes and prototypes; 62 MB of FineWiki 32k
  tokenizers; the root session logs; and the bits-per-byte-against-compression
  figure, which is not in the paper. The 170 MB of matched tokenizers, the
  generated .tex and the per-cell manifest fragments are untracked but kept
  locally -- manifest.json holds exactly the fragments' union, so tracking both
  committed the same 60 entries twice. What stays in git is 460 KB.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W7F6Ac72HbPG15ExjkbFFu
sanderland added a commit that referenced this pull request Aug 5, 2026
A reproduction directory in the shape of the other three papers, and one
pretokenizer configured by options instead of three classes.

    ./paper_utils/boundary/run_all_experiments.sh

regenerates every table from the caches committed under paper/generated/ -- no
GPU, no trained tokenizer, about a second. GRID=1 retrains the tokenizer grid,
DOWNSTREAM=1 reruns the LM sweep and exits with a usable message where there is
no CUDA.

The pretokenizer

  BoundaryScriptPretokenizer is the only class. Case codes always sit outside
  the span's markers and are applied only to a span that carries case; the
  inside-the-markers placement and the version with no case test are gone.
  Options replace the subclasses:

    boundary_targets  ("punct",) by default -- "word" is not a member, since
                      word spans are always delimited
    shift_code        <^>  title case
    caps_code         <^^> all caps
    min_caps_length   shortest span <^^> may cover, 2
    single_char_shift whether "A" is shift-coded, True

  The defaults reproduce the reported arm exactly, so the committed caches keep
  describing the default configuration. Verified before converting anything:
  encode and decode agree with the old classes on 263 texts x 6 variants x 3
  digit_handling settings, 0 mismatches. All 164 trained tokenizers embed their
  config, so they were rewritten in place -- 84 converted, 56 deleted as cells
  of the two removed schemes, 24 baselines untouched -- and each converted file
  was checked by loading it and hash-matching the freshly built variant.

  tests/test_boundary.py merges the two old suites and covers each option, 1412
  tests.

The tables

  table_intrinsic_main.tex and table_downstream_main.tex regenerate
  byte-identical apart from the header naming the new script path.

  bnd_wpd_extcapsfix is renamed bnd_wpd_caps across every cache. The
  full-corpus cells are dropped: the paper reports the quick sample, the full
  grid was 48 of a possible 108, and one cell (fineweb_ru_5gb_plain_mingram)
  had landed at 34,684 against 34,685 everywhere else, which made
  merge_manifests refuse to write. That cell is one token short because the
  MinGram trainer tests the target outside its inner EM loop
  (script_bpe/tokenizers/mingram/trainer.py:57-64), which is not fixed here.

  make_tex_tables reads round-trip failures from eval_goldfish.json, which
  measures every cell, rather than from manifest entries only a cell trained
  with an --eval-texts slice ever had.

  make_example_table.py generates the worked pre-tokenization example. It runs
  the pretokenizers directly, before any vocabulary is learned, so it needs no
  trained tokenizer and no corpus, and it reproduces the paper's table byte for
  byte with the counts computed rather than typed.

Downstream

  run_arms.sh is a plain sequential driver: it trains the matched tokenizers,
  gates them, precomputes the byte factors, and then calls
  run_downstream_eval.py once per arm x seed. Scheduling is left to whoever
  reproduces it -- each model is one invocation of that script, and runs are
  skip-if-done, so cells can be submitted anywhere and a re-run fills in the
  rest. The CSCS Clariden job scripts, their site-specific environment and the
  README describing that flow are deleted, as are the preflight and
  corpus-prebuilding helpers that only existed to pack those jobs.

  results_mingram.tsv takes the nine runs from #13, so the MinGram column has
  no missing cell: bnd_w at 0.8763 and the case codes at 0.8760.

Deleted

  The superseded FineWiki grids, probes and prototypes; 62 MB of FineWiki 32k
  tokenizers; the root session logs; and the bits-per-byte-against-compression
  figure, which is not in the paper. The 170 MB of matched tokenizers, the
  generated .tex and the per-cell manifest fragments are untracked but kept
  locally -- manifest.json holds exactly the fragments' union, so tracking both
  committed the same 60 entries twice. What stays in git is 460 KB.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W7F6Ac72HbPG15ExjkbFFu
sanderland added a commit that referenced this pull request Aug 5, 2026
A reproduction directory in the shape of the other three papers, and one
pretokenizer configured by options instead of three classes.

    ./paper_utils/boundary/run_all_experiments.sh

regenerates every table from the caches committed under paper/generated/ -- no
GPU, no trained tokenizer, about a second. GRID=1 retrains the tokenizer grid,
DOWNSTREAM=1 reruns the LM sweep and exits with a usable message where there is
no CUDA.

The pretokenizer

  BoundaryScriptPretokenizer is the only class. Case codes always sit outside
  the span's markers and are applied only to a span that carries case; the
  inside-the-markers placement and the version with no case test are gone.
  Options replace the subclasses:

    boundary_targets  ("punct",) by default -- "word" is not a member, since
                      word spans are always delimited
    shift_code        <^>  title case
    caps_code         <^^> all caps
    min_caps_length   shortest span <^^> may cover, 2
    single_char_shift whether "A" is shift-coded, True

  The defaults reproduce the reported arm exactly, so the committed caches keep
  describing the default configuration. Verified before converting anything:
  encode and decode agree with the old classes on 263 texts x 6 variants x 3
  digit_handling settings, 0 mismatches. All 164 trained tokenizers embed their
  config, so they were rewritten in place -- 84 converted, 56 deleted as cells
  of the two removed schemes, 24 baselines untouched -- and each converted file
  was checked by loading it and hash-matching the freshly built variant.

  tests/test_boundary.py merges the two old suites and covers each option, 1412
  tests.

The tables

  table_intrinsic_main.tex and table_downstream_main.tex regenerate
  byte-identical apart from the header naming the new script path.

  bnd_wpd_extcapsfix is renamed bnd_wpd_caps across every cache. The
  full-corpus cells are dropped: the paper reports the quick sample, the full
  grid was 48 of a possible 108, and one cell (fineweb_ru_5gb_plain_mingram)
  had landed at 34,684 against 34,685 everywhere else, which made
  merge_manifests refuse to write. That cell is one token short because the
  MinGram trainer tests the target outside its inner EM loop
  (script_bpe/tokenizers/mingram/trainer.py:57-64), which is not fixed here.

  make_tex_tables reads round-trip failures from eval_goldfish.json, which
  measures every cell, rather than from manifest entries only a cell trained
  with an --eval-texts slice ever had.

  make_example_table.py generates the worked pre-tokenization example. It runs
  the pretokenizers directly, before any vocabulary is learned, so it needs no
  trained tokenizer and no corpus, and it reproduces the paper's table byte for
  byte with the counts computed rather than typed.

Downstream

  run_arms.sh is a plain sequential driver: it trains the matched tokenizers,
  gates them, precomputes the byte factors, and then calls
  run_downstream_eval.py once per arm x seed. Scheduling is left to whoever
  reproduces it -- each model is one invocation of that script, and runs are
  skip-if-done, so cells can be submitted anywhere and a re-run fills in the
  rest. The CSCS Clariden job scripts, their site-specific environment and the
  README describing that flow are deleted, as are the preflight and
  corpus-prebuilding helpers that only existed to pack those jobs.

  results_mingram.tsv takes the nine runs from #13, so the MinGram column has
  no missing cell: bnd_w at 0.8763 and the case codes at 0.8760.

Deleted

  The superseded FineWiki grids, probes and prototypes; 62 MB of FineWiki 32k
  tokenizers; the root session logs; and the bits-per-byte-against-compression
  figure, which is not in the paper. The 170 MB of matched tokenizers, the
  generated .tex and the per-cell manifest fragments are untracked but kept
  locally -- manifest.json holds exactly the fragments' union, so tracking both
  committed the same 60 entries twice. What stays in git is 460 KB.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W7F6Ac72HbPG15ExjkbFFu
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants