[PR #1617] [MERGED] fix(tinytorch): perceptron weights deterministic across runs (#1611) #9223

Closed
opened 2026-05-03 01:29:20 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/harvard-edge/cs249r_book/pull/1617
Author: @profvjreddi
Created: 4/30/2026
Status: Merged
Merged: 4/30/2026
Merged by: @profvjreddi

Base: devHead: fix/perceptron-seed


📝 Commits (1)

  • 6220345 fix(tinytorch): perceptron weights deterministic across runs (#1611)

📊 Changes

2 files changed (+7 additions, -2 deletions)

View changed files

📝 tinytorch/milestones/01_1958_perceptron/01_rosenblatt_forward.py (+3 -1)
📝 tinytorch/src/03_layers/03_layers.py (+4 -1)

📄 Description

Summary

Fixes the bug reported in #1611: every run of Milestone 1 produced the same Perceptron weights, even though the on-screen text promises "No random seed - each run will be different!".

Root cause

tinytorch/src/03_layers/03_layers.py had a module-level

rng = np.random.default_rng(7)

just under the imports (line 65). Linear.__init__ reused this single seeded RNG for every weight init via rng.standard_normal(...), so every freshly-constructed Linear produced identical weights across processes. The milestone script 01_rosenblatt_forward.py had its own seeded rng = np.random.default_rng(7) (line 88) used for the data clusters too, contradicting the displayed message.

Fix

Drop the seed in two places:

  1. tinytorch/src/03_layers/03_layers.py - module-level rng is now unseeded (np.random.default_rng()). Local seeded RNGs inside test/demo blocks (lines ~829, 848, 981) are intentionally left alone since those want determinism for reproducible self-tests.
  2. tinytorch/milestones/01_1958_perceptron/01_rosenblatt_forward.py - the data-generation rng is also unseeded so cluster points vary too.
-rng = np.random.default_rng(7)
+rng = np.random.default_rng()

Verification

After re-exporting tinytorch/core/layers.py via nbdev.export.nb_export, ran the milestone twice and compared (excerpt of diff /tmp/run1.txt /tmp/run2.txt):

< │ Predictions │ [1 1 1 1 1 0 0 0 0 0] │
< │ Matches     │ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓   │
< │ Accuracy    │ 100.0% 🎲 Got Lucky!  │
---
> │ Predictions │ [0 0 0 0 0 1 1 1 1 1]    │
> │ Matches     │ ✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗      │
> │ Accuracy    │ 0.0% ❌ Random Guessing! │

Cluster points, predictions, and final accuracy all differ between runs — exactly what the milestone advertises. Independent Linear(8,4) constructions within the same process also produce distinct weight matrices (np.array_equal(a, b) == False).

Relates to #1611

Test plan

  • Re-export Module 03 (tito dev export 03) and confirm tinytorch/core/layers.py now has unseeded rng = np.random.default_rng()
  • Run the milestone twice (python3 tinytorch/milestones/01_1958_perceptron/01_rosenblatt_forward.py < /dev/null) and verify accuracy/cluster output differs
  • python3 -m pytest tinytorch/tests/03_layers/ -k "linear or layers_core" -v (after exporting full package)
  • Spot-check that pedagogical reproducibility tests further down 03_layers.py (lines ~829, 848, 981) still see deterministic output thanks to their local rng = np.random.default_rng(7) — those were left intact

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/harvard-edge/cs249r_book/pull/1617 **Author:** [@profvjreddi](https://github.com/profvjreddi) **Created:** 4/30/2026 **Status:** ✅ Merged **Merged:** 4/30/2026 **Merged by:** [@profvjreddi](https://github.com/profvjreddi) **Base:** `dev` ← **Head:** `fix/perceptron-seed` --- ### 📝 Commits (1) - [`6220345`](https://github.com/harvard-edge/cs249r_book/commit/6220345038670778106c483eb12d317ad6d2b9b4) fix(tinytorch): perceptron weights deterministic across runs (#1611) ### 📊 Changes **2 files changed** (+7 additions, -2 deletions) <details> <summary>View changed files</summary> 📝 `tinytorch/milestones/01_1958_perceptron/01_rosenblatt_forward.py` (+3 -1) 📝 `tinytorch/src/03_layers/03_layers.py` (+4 -1) </details> ### 📄 Description ## Summary Fixes the bug reported in #1611: every run of Milestone 1 produced the same Perceptron weights, even though the on-screen text promises *"No random seed - each run will be different!"*. ### Root cause `tinytorch/src/03_layers/03_layers.py` had a module-level ```python rng = np.random.default_rng(7) ``` just under the imports (line 65). `Linear.__init__` reused this single seeded RNG for every weight init via `rng.standard_normal(...)`, so every freshly-constructed `Linear` produced identical weights across processes. The milestone script `01_rosenblatt_forward.py` had its own seeded `rng = np.random.default_rng(7)` (line 88) used for the data clusters too, contradicting the displayed message. ### Fix Drop the seed in two places: 1. **`tinytorch/src/03_layers/03_layers.py`** - module-level `rng` is now unseeded (`np.random.default_rng()`). Local seeded RNGs inside test/demo blocks (lines ~829, 848, 981) are intentionally left alone since those want determinism for reproducible self-tests. 2. **`tinytorch/milestones/01_1958_perceptron/01_rosenblatt_forward.py`** - the data-generation `rng` is also unseeded so cluster points vary too. ```diff -rng = np.random.default_rng(7) +rng = np.random.default_rng() ``` ### Verification After re-exporting `tinytorch/core/layers.py` via `nbdev.export.nb_export`, ran the milestone twice and compared (excerpt of `diff /tmp/run1.txt /tmp/run2.txt`): ``` < │ Predictions │ [1 1 1 1 1 0 0 0 0 0] │ < │ Matches │ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ │ < │ Accuracy │ 100.0% 🎲 Got Lucky! │ --- > │ Predictions │ [0 0 0 0 0 1 1 1 1 1] │ > │ Matches │ ✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗ ✗ │ > │ Accuracy │ 0.0% ❌ Random Guessing! │ ``` Cluster points, predictions, and final accuracy all differ between runs — exactly what the milestone advertises. Independent `Linear(8,4)` constructions within the same process also produce distinct weight matrices (`np.array_equal(a, b) == False`). Relates to #1611 ## Test plan - [ ] Re-export Module 03 (`tito dev export 03`) and confirm `tinytorch/core/layers.py` now has unseeded `rng = np.random.default_rng()` - [ ] Run the milestone twice (`python3 tinytorch/milestones/01_1958_perceptron/01_rosenblatt_forward.py < /dev/null`) and verify accuracy/cluster output differs - [ ] `python3 -m pytest tinytorch/tests/03_layers/ -k "linear or layers_core" -v` (after exporting full package) - [ ] Spot-check that pedagogical reproducibility tests further down `03_layers.py` (lines ~829, 848, 981) still see deterministic output thanks to their local `rng = np.random.default_rng(7)` — those were left intact --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-05-03 01:29:20 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/cs249r_book#9223