Ten Minutes, One Command: The First Screen a Hiring Manager Sees
A reviewer opens forty repositories in an afternoon. Yours gets the first screen — the README above the fold — and roughly ten minutes of attention. Everything in that screen exists to answer one question: can I trust this person's numbers, and can I run them myself? Structure the page for that question and nothing else.
| README section | Question it answers | The common failure |
|---|---|---|
| One-paragraph summary | What problem, what approach, what result? | "advanced LSTM project" with no number anywhere |
| Result table | Headline metric vs baseline, on which split? | a lone 0.93 with nothing to compare against |
| Quickstart | What do I type first? | notebook-first, manual downloads, "adjust paths" |
| Data | Source, license, fetch instructions, checksum? | "contact me for data" |
| Repository layout | Where does the code actually live? | thirty flat files at the root |
| Trade-offs | What did you give up, and why? | absent entirely |
| Reproduce | Expected output and tolerance? | absent entirely |
The quickstart is the load-bearing section. Lay the repository out so the commands map to the pipeline stages:
amz-churn/
├── configs/v1.yaml # full experiment config, committed
├── data/ # empty; fetch_data.py fills it and verifies hashes
├── src/{ingest,train,evaluate,serve}.py
├── reports/expected_metrics.json # what a rerun should print
├── requirements.lock # pinned, not floating
└── README.md
make reproduce
# equivalent to:
python scripts/fetch_data.py --verify-checksum
python -m src.train --config configs/v1.yaml --seed 42
python -m src.evaluate --expect reports/expected_metrics.json --tolerance 0.005
The first command a reviewer runs must not require a decision — no version choices, no manual downloads, no editing paths in a notebook. Every decision you push to the reader is a reader who leaves. Data instructions deserve the same rigor: a fetch script that validates a checksum, a note on licensing and size, and a fallback sample so someone on a slow connection can still run the smoke config.
Test the screen the way a reviewer experiences it: open the repository in a fresh session — or hand it to a friend who owes you nothing — start a timer, and note where the ten minutes go. Every pause spent hunting for the run command, guessing at data provenance, or waiting on an unpinned install is a design defect, not a reader problem. Two cheap fixes cover most of them: a make help target listing the four commands that matter, and a committed reports/ directory holding your outputs (result table, slice report, one training curve) so a reader can inspect the evidence before running anything. Where the data cannot be redistributed, say so plainly and offer the alternative — a public mirror, a synthetic generator committed as a script, or the exact query against an open dataset — because "available on request" converts an interested reviewer into someone who closes the tab.
Two paragraphs then do more credibility work than any badge wall. First, the result: model versus baselines, per-slice, on a time-based split. Second, the trade-offs: what you sacrificed and what it bought you. A reviewer who reaches "I chose precision over recall because the review queue holds 4,000 items a day, so recall 0.80 at precision 0.60 beats recall 0.95 at precision 0.20" already understands how you think — that is the whole screening purpose of the page, and it is precisely the reasoning you will be asked to defend live in ML Interview Question Patterns.
The Rerun Test: Seeds, Pins, Data Snapshots, and the Tolerance You Declare
You reported 0.871. The reviewer reruns and gets 0.864. Is that a contradiction? Without a declared tolerance, you have no idea — and neither do they. Reproducibility is not bitwise equality; it is a published expectation with a stated variance, plus the controls that keep the variance small.
Work through the sources of surprise before someone else does:
| Source of nondeterminism | Symptom | Fix |
|---|---|---|
| Unseeded shuffling | different batches every run | seed Python, NumPy, and the framework at startup |
| Nondeterministic GPU kernels | jitter on GPU, stable on CPU | deterministic ops flags, or declare the tolerance |
| Floating-point reduction order | small drift with thread count | fix thread counts; accept ±0.005 |
| Unpinned libraries | behavior changes after an upgrade | lockfile with exact versions |
| Upstream data file changed | wholesale score shift | frozen snapshot + checksum |
| Hyperparameter search rerun | a different winning config | commit the chosen config; reproduction never re-searches |
Seed everything in one place, and let the framework fail loudly rather than silently fall back to fast nondeterministic kernels:
import os, random, numpy as np, torch
def seed_everything(seed: int = 42):
random.seed(seed)
np.random.seed(seed)
torch.manual_seed(seed)
os.environ["PYTHONHASHSEED"] = str(seed)
torch.use_deterministic_algorithms(True) # raises instead of quietly varying
Pin the environment with a generated lockfile rather than a hand-edited requirements file, and record the command that produced it so pins change deliberately instead of drifting:
pip-compile pyproject.toml -o requirements.lock # or: uv lock && uv export --frozen > requirements.lock
pip install -r requirements.lock # installs the exact resolved graph
Configuration is part of the contract as much as code: commit configs/v1.yaml holding every hyperparameter, the seed, and the data hash it was trained against, so a rerun that differs can be diffed field by field — code, config, or data, the same three-way localization an interviewer will ask you to perform on a production regression.
Then make the rerun an automated check, not a favor you perform manually. A CI job on every push proves the claim continuously:
name: reproduce
on: [push]
jobs:
rerun:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install -r requirements.lock
- run: python scripts/fetch_data.py --verify-checksum
- run: python -m src.train --config configs/smoke.yaml --seed 42
- run: python -m src.evaluate --expect reports/expected_metrics.json --tolerance 0.005
Two details decide whether that job is useful or theater. First, the smoke config: two epochs on a 5% data slice that finishes in minutes, which proves the pipeline executes end to end — while the full run stays a documented local command. State the distinction in the README, or a reviewer will judge your project by a run it never claimed to reproduce. Second, the failure message is a user interface: print expected and actual metrics side by side with the tolerance, so whoever opens the log knows immediately whether the pipeline broke or the tolerance is too tight.
Finally, report honestly. A single number is a claim; a mean over three seeds with a declared tolerance is a result. Write 0.871 ± 0.004 across 3 seeds in the README, commit the expected-metrics file the CI compares against, and a reviewer whose rerun prints 0.868 concludes the pipeline is sound instead of concluding you got lucky. That sentence — mean, spread, seed count, tolerance — is the cheapest credibility you will ever buy, and it is the same contract the capstone's rerun test enforces at ship time in End-to-End Capstone Project.
Baselines, Error Slices, and the Trade-off Paragraph That Beats a Framework List
Anyone can list tools. What separates a portfolio that survives technical review from one that does not is evidence of comparison: against baselines, across slices, and against the alternatives you rejected. Rigor is a table of comparisons, not a list of tools.
Start with the baseline table — same split, same code path, same evaluation script:
| Model | PR-AUC | Params | What it proves |
|---|---|---|---|
| Majority class | 0.003 | 0 | the base rate itself |
| Domain heuristic rule | 0.18 | — | what an analyst does today |
| Logistic regression, 2 features | 0.31 | ~3 | the problem is learnable at all |
| Gradient boosting, all features | 0.63 | ~400k | your contribution: +0.32 over the simple model |
Each row answers a question a reviewer is silently asking. Skipping the logistic regression row is the most common gap: without it, nobody can tell whether your 0.63 came from gradient boosting or from the features, and your effort is unattributable. Include the domain heuristic even when it embarrasses you — beating a rule your grandmother could apply is the most legible kind of evidence.
Then show where the model fails, because error analysis is the interview answer your repo proves you can do. Two moves suffice:
# slice-wise metrics: same metric, segmented — not a new metric per segment
slices = df.groupby(["device_tier", "tenure_band"]).apply(
lambda g: pd.Series({"pr_auc": pr_auc(g.y, g.p), "n": len(g)})
)
# then read the 100 worst errors by hand and cluster them by cause
Publish the resulting table — it is shorter than it looks:
| Slice | PR-AUC | n | Read |
|---|---|---|---|
| desktop | 0.71 | 180k | strong |
| mobile, mid-tier | 0.62 | 140k | acceptable |
| mobile, low-end | 0.44 | 60k | investigate: timeout label noise |
A reviewer who sees 0.71 versus 0.44 next to a paragraph noting timeout-related label noise on low-memory devices learns more about your engineering judgment than 500 more notebook cells would. Hand-clustering a hundred errors usually reveals the cause is label noise or a missing feature rather than model capacity — a finding worth committing to reports/error_analysis.md so it survives the interview.
Close with the trade-off paragraph — three or four sentences, explicit about what you gave up:
I optimized precision@4,000 over recall because the review team cannot staff more queue, accepting ~600 missed fraud cases a day as the cost of keeping analyst idle time near zero. Inference runs at 38 ms p99 on CPU, which rules out the larger ensemble that gained +0.02 PR-AUC; the latency budget mattered more than the leaderboard.
That paragraph is the payload. It demonstrates that you know metrics are decision rules, that constraints drive architecture, and that every choice has a price — the exact reasoning you rehearsed in ML Interview Question Patterns. What to delete while you edit: badge walls, twenty-framework stack lists, unedited notebooks with dead kernel outputs, and screenshots of loss curves with no comparison drawn. A page of tooling logos next to a single unexplained number reads as compensation. A short, specific trade-off section reads as depth — and depth is what the reviewer came to find.
One last discipline: replace each deletion with a sentence of reasoning. The reviewer's question never changes — compared to what, and can I run it? — so every element on the page either answers that question or competes with the ones that do. Read your repository once with that sentence as the only lens, and cut whatever fails to answer it.
Quiz
1. A reviewer wants to verify your claimed PR-AUC of 0.63. Which repository property lets them do it fastest?
2. Training prints 0.871 on your laptop and 0.864 on a teammate's identically configured GPU machine. What is the most likely explanation?
3. What does "0.871 ± 0.004 across 3 seeds" communicate that "0.871" does not?
4. Which addition most raises a reviewer's confidence in your results section?
Flashcards
Question
What must the first screen of a portfolio README contain?
Click to reveal answer
Answer
A one-paragraph problem-and-result summary, a result table with baselines on a named split, a one-command quickstart, data source with license and checksum, repository layout, a trade-offs paragraph, and the expected rerun output with its tolerance — arranged so no decision is pushed onto the reader.
Question
Name the top sources of rerun nondeterminism and their fixes.
Click to reveal answer
Answer
Unseeded shuffling (seed Python/NumPy/framework at startup), nondeterministic GPU kernels (deterministic ops flags or a declared tolerance), floating-point reduction order (fix thread counts), unpinned libraries (exact lockfile), changed upstream data (frozen snapshot + checksum), and rerunning hyperparameter search (commit the chosen config instead of searching again).
Question
What is the rerun contract, and how is it enforced?
Click to reveal answer
Answer
Report metrics as a mean with spread over at least three seeds, declare the tolerance in the README, commit the expected-metrics file, and run a CI job that installs pins, fetches checksummed data, trains with a fixed seed, and fails if evaluation drifts outside tolerance. Reproducibility becomes an automated check, not a manual favor.
Question
Why does a portfolio need a logistic regression row in its baseline table?
Click to reveal answer
Answer
Without a simple model on the same split and evaluation script, reviewers cannot attribute your gain: the improvement might come from better features rather than a better model. Baselines turn "my model scores 0.63" into "gradient boosting added +0.32 over a linear model and beat the analyst's heuristic by +0.45" — evidence instead of a claim.
Question
What does the trade-off paragraph prove that a stack list cannot?
Click to reveal answer
Answer
That you treat metrics as decision rules under constraints: which axis you optimized, what it cost, which rejected alternative would have won on one metric and lost on another, and which budget (latency, data, review capacity) overruled it. It shows judgment; a list of tools only shows exposure.
Revision Notes
Key Takeaways
- 1. The README's job is trust and execution: result vs baselines up top, one command below it, no reader-side decisions anywhere
- 2. Reproducibility means a declared expectation with variance — `0.871 ± 0.004 across 3 seeds` — not bitwise equality across hardware
- 3. Nondeterminism has a short list of causes (seeds, kernels, threads, pins, data, re-searched configs); fix what you can and publish the tolerance for the rest
- 4. Baselines and slice tables attribute your gain; without a logistic regression row, a reviewer cannot tell whether the model or the features did the work
- 5. A three-sentence trade-off paragraph outperforms a wall of framework badges, because it proves you understand constraints — the exact reasoning interviews reward
Interview Tips
- • "Walk me through your repository" — narrate the quickstart: one command, pinned environment, checksummed data, metrics compared against committed expectations; narrating the rerun is stronger than describing the architecture
- • "How reproducible is your work?" — answer with the contract: seeds, lockfile, data hash, config plus git SHA, mean over three seeds, tolerance in the README, CI enforces it; naming the tolerance shows you understand nondeterminism rather than fearing it
- • "What would you do differently?" — reach for a real trade-off from the write-up: a metric you optimized at the cost of another, a budget that ruled out a better model; concrete sacrifices read as experience, generic hindsight reads as preparation
- • "Why is your model better than the baseline?" — walk the baseline table row by row (heuristic, logistic regression, your model) on the same split, then name the slice where the gain is smallest; volunteering the weak slice is what senior candidates do
Cheat Sheet
Portfolio and Reproducibility
README skeleton (above the fold):
| Section | Must show |
|---|---|
| Summary | problem + approach + one result number |
| Results | model vs baselines, per slice, named split |
| Quickstart | one command, zero reader decisions |
| Data | source, license, size, checksum fetch |
| Layout | where each pipeline stage lives |
| Trade-offs | what you gave up and why |
| Reproduce | expected output + tolerance |
Rerun contract:
python scripts/fetch_data.py --verify-checksum
python -m src.train --config configs/v1.yaml --seed 42
python -m src.evaluate --expect reports/expected_metrics.json --tolerance 0.005
# report: 0.871 ± 0.004 across 3 seeds
Nondeterminism fixes: seed all RNGs · torch.use_deterministic_algorithms(True) · fixed thread counts · lockfile pins · frozen data snapshot + hash · commit the chosen config, never re-search.
Baseline ladder: majority class → domain heuristic → logistic regression → your model, all on the same split with the same evaluation script.
Edit out: badge walls, framework lists, dead-kernel notebooks, unexplained lone metrics.