fix(tinytorch-pdf): polish targeted Lab Guide rendering issues

Pointed-at fixes from a visual PDF review:

- preface.qmd: drop emojis from the astronaut/rocket-scientist opener
  (XeLaTeX renders them as zero-width glyphs, leaving phantom space
  before the period); split the colored-card grids into HTML-only and
  PDF-only branches via :::{.content-visible} so PDF readers get a
  clean bold-paragraph layout instead of the divs flattening into
  unstyled prose; remove the JIT/Pin compilers footnote.

- modules/04_losses.qmd: blank line before the Case 1/Case 2 bullet
  lists so Pandoc actually emits them as a list (not run-on prose),
  plus a PDF-only \medskip between the two cases since callouts
  collapse paragraph spacing.

- milestones/index.qmd, conclusion.qmd: remove stray --- horizontal
  rules in body content (per project rule: HRs only inside code or
  style examples).

- assets/images/diagrams/03_layers-diag-1.svg: redraw per STYLE.md.
  Old version had four L-shaped paths starting inside the source box.
  New version: orange parent at top, three children fanning out below
  with straight diagonal/vertical arrows, no overlapping geometry.

- pdf/_quarto.yml:
  * fvextra Highlighting/verbatim envs with breaklines so long code
    lines wrap cleanly inside the page column instead of overflowing
    the right margin.
  * \titleformat{\part} so Part divider pages carry the brand: a
    flameorange "PART I" eyebrow above a torchnavy bold-sans title,
    bracketed by hairline rules.
This commit is contained in:
Vijay Janapa Reddi
2026-04-22 16:26:05 -04:00
parent 59f74076bf
commit ea00a2efcf
6 changed files with 111 additions and 34 deletions

View File

@@ -1,29 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 680 360" font-family="Helvetica Neue, Helvetica, Arial, sans-serif">
<rect width="680" height="360" fill="#ffffff"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 680 260" font-family="Helvetica Neue, Helvetica, Arial, sans-serif">
<rect width="680" height="260" fill="#ffffff"/>
<defs>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<path d="M0,0 L8,3 L0,6 Z" fill="#9ca3af"/>
</marker>
</defs>
<g transform="translate(0,-50)">
<rect x="40" y="60" width="600" height="340" fill="#f8f9fa" stroke="#e5e7eb" stroke-width="1" rx="2"/>
<text x="50" y="80" font-size="11" font-weight="700" fill="#1f2937">Your Layer System</text>
<rect x="250" y="100" width="180" height="60" fill="#fff1e8" stroke="#ff8246" stroke-width="1" rx="2"/>
<text x="340.0" y="127.0" text-anchor="middle" font-size="10" font-weight="700" fill="#1f2937">Layer Base Class</text>
<text x="340.0" y="142.0" text-anchor="middle" font-size="9" font-weight="400" fill="#6b7280">forward(), parameters()</text>
<rect x="100" y="220" width="160" height="60" fill="#f4f5f7" stroke="#9ca3af" stroke-width="1" rx="2"/>
<text x="180.0" y="247.0" text-anchor="middle" font-size="10" font-weight="700" fill="#1f2937">Linear Layer</text>
<text x="180.0" y="262.0" text-anchor="middle" font-size="9" font-weight="400" fill="#6b7280">y = xW + b</text>
<rect x="420" y="220" width="160" height="60" fill="#f4f5f7" stroke="#9ca3af" stroke-width="1" rx="2"/>
<text x="500.0" y="247.0" text-anchor="middle" font-size="10" font-weight="700" fill="#1f2937">Dropout Layer</text>
<text x="500.0" y="262.0" text-anchor="middle" font-size="9" font-weight="400" fill="#6b7280">regularization</text>
<rect x="250" y="320" width="180" height="60" fill="#f4f5f7" stroke="#9ca3af" stroke-width="1" rx="2"/>
<text x="340.0" y="347.0" text-anchor="middle" font-size="10" font-weight="700" fill="#1f2937">Sequential Container</text>
<text x="340.0" y="362.0" text-anchor="middle" font-size="9" font-weight="400" fill="#6b7280">layer composition</text>
<path d="M250 130 H180 V220" stroke="#9ca3af" stroke-width="1" fill="none" marker-end="url(#arrow)"/>
<path d="M430 130 H500 V220" stroke="#9ca3af" stroke-width="1" fill="none" marker-end="url(#arrow)"/>
<path d="M250 350 H180 V280" stroke="#9ca3af" stroke-width="1" fill="none" marker-end="url(#arrow)"/>
<path d="M430 350 H500 V280" stroke="#9ca3af" stroke-width="1" fill="none" marker-end="url(#arrow)"/>
</g>
<rect x="40" y="20" width="600" height="220" fill="#f8f9fa" stroke="#e5e7eb" stroke-width="1" rx="2"/>
<text x="50" y="40" font-size="11" font-weight="700" fill="#1f2937">Your Layer System</text>
<rect x="250" y="60" width="180" height="60" fill="#fff1e8" stroke="#ff8246" stroke-width="1" rx="2"/>
<text x="340" y="87" text-anchor="middle" font-size="10" font-weight="700" fill="#1f2937">Layer Base Class</text>
<text x="340" y="102" text-anchor="middle" font-size="9" font-weight="400" fill="#6b7280">forward(), parameters()</text>
<rect x="80" y="170" width="160" height="60" fill="#f4f5f7" stroke="#9ca3af" stroke-width="1" rx="2"/>
<text x="160" y="197" text-anchor="middle" font-size="10" font-weight="700" fill="#1f2937">Linear Layer</text>
<text x="160" y="212" text-anchor="middle" font-size="9" font-weight="400" fill="#6b7280">y = xW + b</text>
<rect x="260" y="170" width="160" height="60" fill="#f4f5f7" stroke="#9ca3af" stroke-width="1" rx="2"/>
<text x="340" y="197" text-anchor="middle" font-size="10" font-weight="700" fill="#1f2937">Sequential Container</text>
<text x="340" y="212" text-anchor="middle" font-size="9" font-weight="400" fill="#6b7280">layer composition</text>
<rect x="440" y="170" width="160" height="60" fill="#f4f5f7" stroke="#9ca3af" stroke-width="1" rx="2"/>
<text x="520" y="197" text-anchor="middle" font-size="10" font-weight="700" fill="#1f2937">Dropout Layer</text>
<text x="520" y="212" text-anchor="middle" font-size="9" font-weight="400" fill="#6b7280">regularization</text>
<path d="M280 120 L160 170" stroke="#9ca3af" stroke-width="1" fill="none" marker-end="url(#arrow)"/>
<path d="M340 120 V170" stroke="#9ca3af" stroke-width="1" fill="none" marker-end="url(#arrow)"/>
<path d="M400 120 L520 170" stroke="#9ca3af" stroke-width="1" fill="none" marker-end="url(#arrow)"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -121,6 +121,4 @@ You chose to be both. You did not just fly the rocket. You built it. And now you
**Don't import torch. You built it.**
---
*Share your journey with the TinyTorch community, or explore the [MLSysBook](https://mlsysbook.ai) for the full textbook.*

View File

@@ -61,6 +61,4 @@ Milestone proves: WHAT you can build with it
The combination of modules + milestones ensures you don't just complete exercises — you build something historically significant that works.
---
**Build the future by understanding the past.**

View File

@@ -794,11 +794,17 @@ You're building a medical diagnosis system with 5 disease categories. Should you
:::{.callout-note collapse="true" title="Answer"}
**Case 1: Mutually exclusive diseases** (patient has exactly one)
- **Use**: CrossEntropyLoss
- **Model output**: Logits of shape (batch_size, 5)
- **Why**: Categories are mutually exclusive - softmax ensures probabilities sum to 1.0
- **Why**: Categories are mutually exclusive softmax ensures probabilities sum to 1.0
::: {.content-visible when-format="pdf"}
\medskip
:::
**Case 2: Multi-label classification** (patient can have multiple diseases)
- **Use**: BinaryCrossEntropyLoss
- **Model output**: Probabilities of shape (batch_size, 5) after sigmoid
- **Why**: Each disease is an independent binary decision. Softmax would incorrectly force them to sum to 1.

View File

@@ -239,6 +239,33 @@ format:
\newunicodechar{╚}{\texttt{+}}
\newunicodechar{╝}{\texttt{+}}
% ── Code-block line wrapping ────────────────────────────────
% Pandoc emits highlighted code into the `Highlighting` Verbatim
% environment (from `fancyvrb`). By default that environment does
% NOT break long lines — they overflow the page right margin and
% fall off the printable area. fvextra is a drop-in superset of
% fancyvrb that adds `breaklines`, plus visual cues so a wrapped
% line is unambiguously a continuation, not a new statement.
\usepackage{fvextra}
\DefineVerbatimEnvironment{Highlighting}{Verbatim}{%
breaklines,%
breakanywhere,%
breaksymbolleft={\color{flameorange!60}\hookrightarrow\space},%
breaksymbolright={},%
breakanywheresymbolpre={},%
breakanywheresymbolpost={},%
commandchars=\\\{\}%
}
% Plain ``` fences (no language tag) render through Pandoc's
% `verbatim` environment. Same treatment so ASCII art / shell
% snippets without syntax highlighting also wrap cleanly.
\RecustomVerbatimEnvironment{verbatim}{Verbatim}{%
breaklines,%
breakanywhere,%
breaksymbolleft={\color{flameorange!60}\hookrightarrow\space},%
breaksymbolright={}%
}
% =============================================================
% Professional styling — fancy header/footer, chapter format,
% section hierarchy, microtype polish, widow/orphan discipline,
@@ -369,6 +396,23 @@ format:
% Running head carries just the chapter title (no number).
\renewcommand{\chaptermark}[1]{\markboth{#1}{}}
% ── Part page styling ──────────────────────────────────────
% Default `book` class renders Part pages as plain serif black
% "Part I" / "Foundation Tier" stacked centered. Repaint with
% the brand palette so Part dividers carry the same identity as
% chapter openers: flameorange "PART I" eyebrow, torchnavy
% bold sans title, hairline rule above and below to give the
% page weight without any color blocking.
\titleformat{\part}[display]
{\centering\normalfont\sffamily}
{\vspace*{0.15\textheight}%
{\color{flameorange!50}\titlerule[0.6pt]}\vspace{1em}%
{\color{flameorange}\large\bfseries\MakeUppercase{\partname~\thepart}}}
{0.8em}
{\color{torchnavy}\Huge\bfseries}
[\vspace{1em}{\color{flameorange!50}\titlerule[0.6pt]}]
\titlespacing*{\part}{0pt}{0pt}{0pt}
% ── Section hierarchy ──────────────────────────────────────
% Sans-serif navy titles, flameorange numerals. Weight and
% color fade as level depth increases so the reader's eye

View File

@@ -6,7 +6,7 @@ title: "Welcome"
<img src="assets/images/tito.png" alt="TinyTorch" style="width: 100%;">
</div>
Everyone wants to be an astronaut 🧑‍🚀. Very few want to be the rocket scientist 🚀.
Everyone wants to be an astronaut. Very few want to be the rocket scientist.
In machine learning, we see the same pattern. Everyone wants to train models, run inference, deploy AI. Very few want to understand how the frameworks actually work. Even fewer want to build one.
@@ -59,38 +59,51 @@ This is how people move from *using* machine learning to *engineering* machine l
## Who This Is For
::: {.content-visible when-format="html"}
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin: 1.5rem 0;">
<div style="background: #fafafa; padding: 1.25rem; border-radius: 0.5rem; border-left: 4px solid #9c27b0;">
<strong>🎓 Students & Researchers</strong>
<strong>Students & Researchers</strong>
<p style="margin: 0.5rem 0 0 0; font-size: 0.95rem;">Want to understand ML systems deeply, not just use them superficially. If you've wondered "how does that actually work?", this is for you.</p>
</div>
<div style="background: #fafafa; padding: 1.25rem; border-radius: 0.5rem; border-left: 4px solid #4caf50;">
<strong>ML Engineers</strong>
<strong>ML Engineers</strong>
<p style="margin: 0.5rem 0 0 0; font-size: 0.95rem;">Need to debug, optimize, and deploy models in production. Understanding the systems underneath makes you more effective.</p>
</div>
<div style="background: #fafafa; padding: 1.25rem; border-radius: 0.5rem; border-left: 4px solid #2196f3;">
<strong>💻 Systems Programmers</strong>
<strong>Systems Programmers</strong>
<p style="margin: 0.5rem 0 0 0; font-size: 0.95rem;">You understand memory hierarchies, computational complexity, performance optimization. You want to apply it to ML.</p>
</div>
<div style="background: #fafafa; padding: 1.25rem; border-radius: 0.5rem; border-left: 4px solid #ffc107;">
<strong>🛠 Self-taught Engineers</strong>
<strong>Self-taught Engineers</strong>
<p style="margin: 0.5rem 0 0 0; font-size: 0.95rem;">Can use frameworks but want to know how they work. Preparing for ML infrastructure roles and need systems-level understanding.</p>
</div>
</div>
What you need is not another API tutorial. You need to build.[^pin]
:::
::: {.content-visible when-format="pdf"}
[^pin]: My own background was in compilers, specifically just-in-time (JIT) compilation. But I did not become a systems engineer by reading papers alone. I became one by building [Pin](https://software.intel.com/content/www/us/en/develop/articles/pin-a-dynamic-binary-instrumentation-tool.html), a dynamic binary instrumentation engine that uses JIT technology. The lesson stayed with me: reading teaches concepts, but building deepens understanding.
**Students & Researchers** — want to understand ML systems deeply, not just use them superficially. If you've wondered "how does that actually work?", this is for you.
**ML Engineers** — need to debug, optimize, and deploy models in production. Understanding the systems underneath makes you more effective.
**Systems Programmers** — you understand memory hierarchies, computational complexity, performance optimization. You want to apply it to ML.
**Self-taught Engineers** — can use frameworks but want to know how they work. Preparing for ML infrastructure roles and need systems-level understanding.
:::
What you need is not another API tutorial. You need to build.
## What You Will Build
@@ -112,6 +125,8 @@ This is not a simulation. This is the actual architecture of modern ML framework
Each module follows a **Build-Use-Reflect** cycle: implement from scratch, apply to real problems, then connect what you built to production systems and understand the tradeoffs. Work through Foundation first, then choose your path based on your interests.
::: {.content-visible when-format="html"}
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin: 1.5rem 0;">
<div style="border: 1px solid #e0e0e0; padding: 1rem; border-radius: 0.5rem;">
@@ -140,6 +155,20 @@ Each module follows a **Build-Use-Reflect** cycle: implement from scratch, apply
</div>
:::
::: {.content-visible when-format="pdf"}
**Type every line yourself** — do not copy-paste. The learning happens in the struggle of implementation.
**Profile your code** — use the built-in profiling tools. Measure first, optimize second.
**Run the tests** — every module includes comprehensive tests. When they pass, you have built something real.
**Compare with PyTorch** — once your implementation works, compare with PyTorch's equivalent to see how production frameworks scale the same ideas.
:::
Take your time. The goal is not to finish fast. The goal is to understand deeply.
<div style="background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%); padding: 1.5rem 2rem; border-radius: 0.5rem; margin: 2rem 0; text-align: center;">