From 7747f8b0ea3d56aaf7ccf9852febc83514184579 Mon Sep 17 00:00:00 2001 From: Vincent Chau <43220811+vincentczhou@users.noreply.github.com> Date: Sun, 22 Mar 2026 02:39:07 +0000 Subject: [PATCH 1/2] update specification --- SPECIFICATION.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/SPECIFICATION.md b/SPECIFICATION.md index d25d854..05c782a 100644 --- a/SPECIFICATION.md +++ b/SPECIFICATION.md @@ -125,14 +125,16 @@ For example, you may consider going to a new directory, unzipping your submissio ``` mkdir -p output docker build -t cse447-proj/demo -f Dockerfile . -docker run --rm -v $PWD/src:/job/src -v $PWD/work:/job/work -v :/job/data -v $PWD/output:/job/output cse447-proj/demo bash /job/src/predict.sh /job/data/input.txt /job/output/pred.txt +docker run --gpus all --rm -v $PWD/src:/job/src -v $PWD/work:/job/work -v :/job/data -v $PWD/output:/job/output cse447-proj/demo bash /job/src/predict.sh /job/data/input.txt /job/output/pred.txt ``` If you are curious what these flags in `docker run` mean: - +- `--gpus all` assign all available gpus to the container - `--rm` remove container after running - `-v a:b` mount `a` in host machine (e.g. path on your machine outside docker) to the container (e.g. path in the docker container). +If with the `--gpus all` flag your code throws an error that indicates that your submission is incompatible with gpu usage, we will retry without the `--gpus all` flag. This will not affect your runtime; we re-measure from the new docker run command. + Running this command will produce `output/pred.txt`, which we take to be your predictions on the heldout test data. We will then evaluate your success rate against the heldout answer key using `grader/grade.py`. From c9b8bd5921702f9adb831c0fab9910b86d53e695 Mon Sep 17 00:00:00 2001 From: Vincent Chau <43220811+vincentczhou@users.noreply.github.com> Date: Fri, 27 Mar 2026 08:54:08 +0000 Subject: [PATCH 2/2] chore: update readme --- README.md | 8 ++- graph.png | Bin 0 -> 64759 bytes kenlm.md | 158 ------------------------------------------------------ 3 files changed, 7 insertions(+), 159 deletions(-) create mode 100644 graph.png delete mode 100644 kenlm.md diff --git a/README.md b/README.md index e278d1b..b71a219 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,13 @@ Two-stage character-level next-character prediction system for multilingual text. Given a partial string, predicts the three most likely next characters (character autocomplete). -See [SPECIFICATION.md](SPECIFICATION.md) for the original [CSE 447 project](https://minneker.github.io/nlp-26wi/projects/447-project/) specification. +This implementation achieved **1st** out of **75 teams (211 participants)**, achieving a `0.9618` success rate and `167.2117` seconds runtime. + +

+ Success Rate vs Runtime +

+ +See [SPECIFICATION.md](SPECIFICATION.md) for the original [CSE 447 project](https://minneker.github.io/nlp-26wi/projects/447-project/) specification. Also, the closely related [Interstellar Autocomplete Challenge](https://github.com/waterloo-nlp/intro-to-nlp-project). **Stage 1 — KenLM**: An n-gram language model scores all vocabulary tokens and returns the top-K candidates. diff --git a/graph.png b/graph.png new file mode 100644 index 0000000000000000000000000000000000000000..e930ca826dfff9898c53e4cdc07e7ef3d6f868be GIT binary patch literal 64759 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 PKoJH{S3j3^P6`) | -| `model.NullContextWrite(state)` | Mutates `State` | Sets state to empty/null context | -| `model.BaseScore(in_state, word, out_state)` | → `float` | log10 P(word \| in_state), writes to out_state | -| `model.BaseFullScore(in_state, word, out_state)` | → `FullScoreReturn` | Returns `(log_prob, ngram_length, oov)` | -| `word in model` | → `bool` | Checks if word is in vocabulary | -| `State()` | Constructor | Creates a new state object | -| `FullScoreReturn` | Object | `.log_prob`, `.ngram_length`, `.oov` properties | - -**Key detail**: `BaseScore` accepts a **string** for `word` (e.g., `"h"`, `""`). The `in_state` is **not modified** — only `out_state` is written to, so you can reuse `in_state` across multiple candidates. - ---- - -## Optimal Prediction Strategy: State-Based BaseScore - -### Why not `model.score()`? - -`model.score()` takes a full sentence string, retokenizes, and rescores from scratch. Scoring all V candidates = O(V × context_length). **Way too slow.** - -### The right approach: build context state once, score candidates in O(1) each - -```python -import kenlm - -model = kenlm.Model("work/char6.binary") - -# 1. Build context state from input tokens -state = kenlm.State() -model.BeginSentenceWrite(state) - -context_tokens = ["h", "a", "p", "p"] # from input "Happ" (lowercased) -tmp_state = kenlm.State() -for token in context_tokens: - model.BaseScore(state, token, tmp_state) - state, tmp_state = tmp_state, state # swap - -# 2. Score every candidate next token (state is NOT modified) -out_state = kenlm.State() -scores = {} -for candidate in vocab: - log_prob = model.BaseScore(state, candidate, out_state) - scores[candidate] = log_prob - -# 3. Top 3 -top3 = sorted(scores.items(), key=lambda x: x[1], reverse=True)[:3] -``` - -### Complexity Comparison - -| Approach | Time per input | Practical? | -| --------------------------- | ------------------------- | ---------------------------- | -| Naive `model.score()` | O(V × context_length) | ❌ Very slow | -| **State-based `BaseScore`** | **O(context_length + V)** | **✅ Best** | -| `full_scores()` | O(sentence_length) | ❌ Can't enumerate candidates | - -### Performance Estimate - -- 13,685 candidates × ~2µs per `BaseScore` call ≈ **~27ms per input line** -- Even with thousands of test inputs → well under the 30-minute time limit -- **No vocab pruning needed** - ---- - -## Implementation Pseudocode - -```python -class MyModel: - def load(work_dir): - model = kenlm.Model(os.path.join(work_dir, "char6.binary")) - vocab = list(json.load(open("vocab.json")).keys()) # all tokens - # Exclude , from candidates - return model, vocab - - def input_to_tokens(inp): - text = normalize_text(inp) # lowercase, NFC, collapse whitespace - return [SPACE_TOKEN if ch == " " else ch for ch in text] - - def build_state(model, tokens): - state = kenlm.State() - model.BeginSentenceWrite(state) - out = kenlm.State() - for token in tokens: - model.BaseScore(state, token, out) - state, out = out, state - return state - - def predict_top3(model, state, vocab): - out = kenlm.State() - scored = [(model.BaseScore(state, tok, out), tok) for tok in vocab] - top3 = heapq.nlargest(3, scored) - return "".join(" " if t == "" else t for _, t in top3) -``` - ---- - -## Important Gotchas - -1. **Token format must match training**: Tokens are single characters or ``. Must match exactly what was in `train.txt`. - -2. **OOV handling**: Unknown chars get `` score with backoff. `BaseScore` still works — KenLM handles this gracefully. Check with `token in model` → `False` if OOV. - -3. **BOS vs NullContext**: - - `BeginSentenceWrite` → conditions on `` (sentence start). Use for sentence-initial inputs. - - `NullContextWrite` → no context. Use for mid-sentence fragments if needed. - -4. **Case sensitivity**: Our model is lowercased. Always `.lower()` test inputs before tokenizing. - -5. **Exclude `` from candidates**: It's a special KenLM token, not a printable character. - -6. **Space prediction**: If `` is top-scored, output a literal space character `" "`. The grader handles this. - -7. **No trie enumeration**: KenLM has NO method to enumerate valid continuations from a state. Must loop through all candidates explicitly. - -8. **State is compact**: For 6-gram, stores at most 5 word indices. Swapping is cheap. - -9. **Log base 10**: All KenLM scores are log10 (not ln). Doesn't matter for ranking. - -10. **NFC normalization**: Our preprocessing does `unicodedata.normalize("NFC", text)` — apply this to test inputs too for consistency. - ---- - -## Files - -| File | Purpose | -| ------------------------------ | ------------------------------------------------------------ | -| `work/char6.binary` | Binarized KenLM model (probing hash tables) | -| `work/char6_pruned.arpa` | ARPA text-format model | -| `data/.../vocab.json` | `{token: count}` sorted by frequency descending | -| `src/myprogram.py` | Main program (needs KenLM integration) | -| `src/predict.sh` | Entry point: `uv run python src/myprogram.py test ...` | -| `src/data/preprocess.py` | Preprocessing: normalize → char tokenize → train/valid/vocab |