Tutorial 2: Training Your Own LLMs

SFT → LoRA & QLoRA → learning from feedback with PPO, GRPO and DPO. Three runnable notebooks train real models on a free T4 GPU, so you can watch each post-training method work — and see where it struggles.

📅 Oct. 23rd, 2026 📚 Companion to Lectures 5 & 6 ⏱ about 2.5–3 hours 💻 Kaggle T4 GPU (tested) 📝 slides + 3 notebooks
View the slides Notebook A: SFT + RM + PPO Notebook B: GRPO Notebook C: DPO ⬇ Download all (.zip)

1Overview

Lecture 5 explained how LLMs are pre-trained; Lecture 6 explained why post-training uses reinforcement learning. This tutorial runs the whole post-training toolbox at small scale. The slides walk through SFT, parameter-efficient fine-tuning (LoRA, QLoRA) and the three feedback-based methods. The notebooks then train real models: each one isolates one way of turning a training signal into better behaviour.

Pre-trainedbase modelSFTdemonstrationsReward model → PPOlearned reward + criticAGRPOverifiable reward, groupsBDPOoffline preference pairsCAAligned modelNotebooks B and C start from small Instruct models, which have already been SFT-ed.
Where each notebook sits in the post-training pipeline. All three use LoRA adapters; Notebook A also uses a 4-bit (QLoRA-style) base model.
NotebookMethodModelDataTraining signal
ASFT → reward model → PPOQwen3-4B-Base, 4-bit NF4 + LoRASST-2 movie reviewsnext-token NLL; human sentiment labels → learned reward
BGRPOQwen2-0.5B-Instruct + LoRA128 generated arithmetic questionsverifiable reward: correct answer + format
CDPOSmolLM2-135M-InstructUltraFeedback preference pairschosen ≻ rejected, relative to a frozen reference

Learning objectives

  • Explain the SFT loss and why only response tokens are graded; estimate GPU memory for full fine-tuning, LoRA and QLoRA.
  • Explain why LoRA's update \(\Delta W = BA\) starts at zero, and how QLoRA stores the frozen base in 4-bit NF4.
  • Train a reward model from human labels and use it, together with a KL penalty, as the reward for PPO.
  • Follow one PPO iteration: rollouts, rewards, GAE advantages from a value head, clipped policy updates.
  • Compute GRPO's group-relative advantage by hand and recognise when a group gives no learning signal.
  • Write the DPO loss, interpret its training metrics, and say when DPO is preferable to online RL.
  • Read training diagnostics critically: tell a real improvement from noise on a small evaluation set.

Time plan

PartWhat you doTime (approx.)
SlidesSFT, LoRA/QLoRA, PPO, GRPO, DPO60 min
Notebook C (DPO)Shortest run: 32 steps, about 40 s of training on a T415 min
Notebook B (GRPO)Screening + 64 steps, about 3 min of training25 min
Notebook A (SFT + RM + PPO)Longest run: three training stages on a 4B model; start it first and read while it trains60+ min
Suggested orderStart Notebook A on Kaggle first (it is the slowest), then work through B and C in a second session while A trains.

2Slides: Training Your Own LLMs

52 slides in four parts — the big picture, SFT, efficient fine-tuning (LoRA & QLoRA), and learning from feedback (PPO, GRPO, DPO) — with a running example: turning a 7B base model into a helpful, safe medical assistant.

Key ideas from the slides

SFT grades only the answer

$$\mathcal{L}_{\text{SFT}} = -\sum_{t\,\in\,\text{response}} \log p_\theta(y_t \mid x, y_{\lt t})$$

Prompt tokens get label -100 and are ignored — like grading the student's answer, not the question they copied.

Most of the GPU bill is training state

Fine-tuning a 7B model needs about 16 bytes per parameter: 2 (weights) + 2 (gradients) + 8 (Adam) + 4 (fp32 copy).

≈112 GBfull fine-tuning
≈15 GBLoRA
≈4 GBQLoRA

LoRA: a low-rank update

$$W = W_0 + BA,\quad B\in\mathbb{R}^{d\times r},\ A\in\mathbb{R}^{r\times k},\ r \ll \min(d,k)$$

With \(d=k=4096,\ r=16\): 131K instead of 16.8M trainable weights per matrix (128× fewer). \(B=0\) at start, so training begins exactly at the pre-trained model.

QLoRA: 4-bit base, 16-bit adapters

Store the frozen base in NF4 (4-bit levels placed at normal-distribution quantiles, dense near zero), dequantize on the fly, and train only BF16 adapters. A 65B model goes from >780 GB to <48 GB — one GPU.

3Before you start

Option A · Kaggle (recommended, tested)

  1. Click a Kaggle button above; Kaggle imports the notebook from this site's GitHub repository. Sign in and choose Copy & Edit if asked.
  2. In the right panel: Accelerator → GPU T4 (or T4×2; only one GPU is used) and Internet → On. Phone verification is required for both.
  3. Start a fresh session and run the first cell before anything else: it installs pinned library versions into a private environment.
  4. Run the remaining cells in order. Outputs (adapters, logs, ZIP backups) appear in Kaggle's Output panel.

Option B · Colab or your own GPU

The notebooks were tested on Kaggle (Python 3.13, PyTorch 2.11, CUDA 12.8). They write to /kaggle/working; on other machines, change that path at the top of each notebook. Any CUDA GPU with ≥ 15 GB memory works.

pip install "transformers==4.51.3" \
    "trl==0.18.2" "peft==0.15.2" \
    "datasets==3.5.0" "accelerate==1.6.0" \
    bitsandbytes math-verify

These are the pins used by Notebooks B and C. Notebook A installs newer versions in its own first cell.

Hugging Face downloadsAll models and datasets download automatically. If you see “unauthenticated requests to the HF Hub” or rate limits, add a free HF_TOKEN as a Kaggle secret.

4Notebook A · SFT, reward model and PPO (RLHF)

Notebook A at a glance

transformerspeftbitsandbytesdatasets23 cellsKaggle T4

The classic InstructGPT recipe in miniature. A base model learns to write movie reviews (SFT), a reward model learns to score sentiment from human labels, and PPO steers the SFT model toward reviews the reward model scores as positive.

4.1 One frozen 4-bit base, three LoRA adapters

Instead of loading three copies of a 4B model, the notebook loads one base in 4-bit NF4 and attaches three independent LoRA adapters (rank 8 on q,k,v,o projections). Switching the active adapter switches the “model”:

Qwen3-4B-Base — frozen, stored once in 4-bit NF4adapter "sft"LoRA r = 8SFT model = reference πrefadapter "reward"LoRA + reward_headreward model sφadapter "ppo"LoRA + value_headpolicy πθ + critic Vmodel.set_adapter(name) switches which small set of weights is active
The SFT adapter also serves as the frozen reference policy for PPO's KL penalty; the base with adapters disabled is the “Base” model in the final comparison.
Notebook A, cell 8 (condensed): QLoRA-style setup
qconfig = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_quant_type="nf4",
                             bnb_4bit_use_double_quant=True, bnb_4bit_compute_dtype=DTYPE)
base = AutoModelForCausalLM.from_pretrained(MODEL_ID, quantization_config=qconfig, device_map={"": 0})
base = prepare_model_for_kbit_training(base, use_gradient_checkpointing=False)

lora = LoraConfig(r=8, lora_alpha=16, lora_dropout=0.0,
                  target_modules=["q_proj", "k_proj", "v_proj", "o_proj"], task_type="CAUSAL_LM")
model = get_peft_model(base, lora, adapter_name="sft")    # adapter 1
model.add_adapter("reward", copy.deepcopy(lora))           # adapter 2
model.add_adapter("ppo", copy.deepcopy(lora))              # adapter 3
reward_head = nn.Linear(H, 1)   # score from the last token's hidden state
value_head  = nn.Linear(H, 1)   # V(s_t) for every generated token

The SST-2 data are split once and frozen, so every stage sees different reviews:

2,048SFT reviews
4,096reward-model reviews
1,024PPO prompts
128 / 128validation / RM test
40generation test prefixes

4.2 Component 1 — SFT: learn the domain

SFT continues next-token training on real movie reviews (128 optimizer steps × 8 accumulated reviews, lr 1e-4). It teaches the style of reviews, not positivity: half of the reviews are negative.

4.53 → 3.52held-out review NLL, Base → SFT (lower is better)
Review prefixBase model continues…After SFT
it 's just disappointinglycheap .
How would the previous sentence be correctly capitalized? …
portable fiction .
the film is beautifully mounted ,enthralingly photographed , expertly edited and confidently assembled . yet , overall , the movie falls short because of the shoestring budget …enthralingly photographed and expertly edited .

The base model drifts into web-text habits (a capitalization quiz); after SFT the continuations look like SST-2 reviews.

4.3 Component 2 — Reward model: learn what “good” means

The reward model is the same backbone with its own adapter and a linear reward_head on the last token. It is trained with binary cross-entropy on human sentiment labels:

$$\mathcal{L}_{\text{RM}} = -\big[\,\ell \log \sigma(s_\phi(x)) + (1-\ell)\log\big(1-\sigma(s_\phi(x))\big)\big],\qquad \ell\in\{0,1\}$$
reward model accuracy
Validation accuracy during training (every 32 steps) and on the held-out test split: 94.5% (58 + 63 of 128 correct).
Simplification vs. InstructGPTInstructGPT trains its reward model on pairwise rankings of generated answers (Bradley–Terry loss). Here the human signal is a pre-collected sentiment label per review — easier to obtain, and enough to define a reward.

4.4 Component 3 — PPO: optimise the reward, stay close to SFT

1 Sample prefix6-token review prefix2 Generate48 tokens with πθ3 ScoreRM score − β·KL to SFT4 AdvantagesGAE with value head V5 Updateclipped loss, 2 epochsrepeat: 96 iterations × 8 rollouts
One PPO iteration in Notebook A (96 iterations × 8 rollouts = 768 sampled continuations, 2 update epochs each).

The reward model's score is mapped to \([-1, 1]\) and added at the last token; every token also pays a KL penalty for drifting from the SFT policy:

$$r_t = -\beta\big(\log\pi_\theta(y_t\mid s_t)-\log\pi_{\text{SFT}}(y_t\mid s_t)\big) + \mathbb{1}[t=T]\,\big(2\sigma(s_\phi(x,y))-1\big),\qquad \beta = 0.05$$

A value head estimates \(V(s_t)\); advantages come from GAE (\(\gamma=1,\ \lambda=0.95\)), and the policy is updated with the clipped objective (\(\epsilon=0.2\)):

$$\hat A_t=\sum_{l\ge 0}(\gamma\lambda)^l\delta_{t+l},\quad \delta_t=r_t+\gamma V(s_{t+1})-V(s_t),\qquad \mathcal{L}^{\text{CLIP}} = -\mathbb{E}_t\big[\min(\rho_t\hat A_t,\ \operatorname{clip}(\rho_t,1-\epsilon,1+\epsilon)\hat A_t)\big]$$
Notebook A (condensed; masks omitted): rewards, GAE and the PPO loss
# --- rollout: per-token KL penalty, reward-model score added at the last token
score   = 2 * reward_logits(sequence).sigmoid() - 1          # in [-1, 1]
rewards = -kl_beta * (old_logprobs - ref_logprobs) * mask
rewards[-1] += score

# --- GAE, computed backwards over the generated tokens
for t in reversed(range(T)):
    delta = rewards[:, t] + gamma * values[:, t + 1] - values[:, t]
    carry = delta + gamma * lam * carry
    advantage[:, t] = carry
returns = advantage + values
advantage = (advantage - advantage.mean()) / advantage.std()  # normalised

# --- clipped policy loss + clipped value loss
ratio = torch.exp(logprobs - old_logprobs)
pg = torch.maximum(-ratio * adv, -ratio.clamp(1 - clip, 1 + clip) * adv).mean()
vclip = old_values + (vpreds - old_values).clamp(-value_clip, value_clip)
vf = 0.5 * torch.maximum((vpreds - returns) ** 2, (vclip - returns) ** 2).mean()
loss = pg + value_coef * vf

4.5 Results and how to read them

training dashboard
Notebook output. Top: SFT loss, reward-model loss, noisy per-batch PPO reward. Bottom: external sentiment classifier, held-out NLL, reward-model confusion matrix.
validation reward
Reward on fixed validation prefixes rises from −0.29 (SFT) to 0.25 at the final step.
Metric (40 test prefixes)SFTSFT + PPO
Positive full reviews (external DistilBERT judge)57.5%67.5%
Positive continuations only50.0%52.5%
Held-out review NLL3.52≈ 3.52
Is the improvement real?The mean positive-probability gain from PPO is +0.092, but its paired bootstrap 95% interval is [−0.048, +0.226] — it includes zero. With 40 test prefixes, this run suggests a steering effect but does not establish one. Notice too that most of the gain is in full reviews, i.e. partly carried by the prompt prefix.
PPO diagnostics
PPO diagnostics. The clip fraction is almost always 0 (updates are small), while value-head gradients are large and noisy — typical of a short PPO run.

5Notebook B · GRPO with verifiable rewards

Notebook B at a glance

trl GRPOTrainerpeftmath-verify19 cells≈3 min training

The DeepSeek-R1 recipe in miniature: no reward model and no critic. A Python function checks the final answer, and each answer is compared with the other answers sampled for the same question.

5.1 Task and verifiable rewards

The policy is Qwen2-0.5B-Instruct with a rank-16 LoRA (2.16M trainable parameters, 0.44% of the model). Training questions are 128 generated arithmetic problems (addition, subtraction with negative results, multiplication, two-step expressions, word problems); 12 fixed questions are held out. The system prompt asks for a short calculation and a final answer in tags:

<think>12 + 7 = 19; 19 * 3 = 57.</think><answer>57</answer>

Format reward \(r_{\text{fmt}}\in[0,1]\)

0.25 each for opening <think>, non-empty thinking, opening <answer>, non-empty answer. Partial credit makes the signal less sparse.

Correctness reward \(r_{\text{acc}}\in\{0,1\}\)

1 if the extracted final answer equals the reference (checked with math-verify), else 0. Only the final answer is verified, not each step.
$$r = 0.1\,r_{\text{fmt}} + r_{\text{acc}}$$

5.2 Group-relative advantage

For each question GRPO samples a group of \(G=4\) answers and normalises their rewards within the group — the group mean replaces PPO's learned value model:

$$A_i = \frac{r_i - \operatorname{mean}(r_1,\dots,r_G)}{\operatorname{std}(r_1,\dots,r_G)+\varepsilon}$$
What is 24 − 58?one prompt, G = 4answerreward radvantage A-34 ✓1.10+0.5-34 ✓1.10+0.534 ✗0.10-1.5-34 ✓1.10+0.5mean 0.85, std 0.50A = (r − 0.85) / 0.50
A real training group from the notebook. Three answers are correct; the one that dropped the minus sign is pushed down hard (−1.5).

If all four answers get the same reward, every advantage is zero and the question teaches nothing. The notebook therefore screens training questions first and keeps 8 of the first 12 probes whose answers were mixed (some right, some wrong). Even so, groups often become uniform during training:

GRPO zero-signal groups
Gradient norm on each step that samples a new group. Grey steps (11 of 32) had identical rewards in every group, so their gradient is essentially zero.
Notebook B, cell 15 (condensed): no reward model, just two Python functions
training_args = GRPOConfig(
    num_generations=4,            # group size G
    num_iterations=2,             # reuse each sampled group twice (needs the clip)
    max_steps=64, learning_rate=2e-5,
    temperature=0.9, top_p=0.95,  # sampling must be diverse to get mixed groups
    beta=0.02, epsilon=0.2,       # KL coefficient and clip range
    loss_type="grpo", scale_rewards=True,
    reward_weights=[0.1, 1.0],    # format, correctness
)
trainer = GRPOTrainer(model=model, args=training_args,
                      reward_funcs=[format_reward, accuracy_reward],
                      train_dataset=train_dataset, peft_config=lora_config)
trainer.train()
Why is the GRPO loss almost exactly 0?Advantages are centred within each group, so positive and negative terms cancel in the logged loss even when gradients are non-zero. Watch reward_std, frac_reward_zero_std, grad_norm and kl instead.

5.3 Results on the 12 held-out questions

5 / 12 → 9 / 12correct answers, before → after GRPO (greedy decoding)
2 → 0answers with no extractable final answer
≤ 0.021largest KL to the starting model
#Held-out questionReferenceBefore GRPOAfter GRPO
127 × 34918−888888
2387 + 568955−955955 ✓
3(17 + 26) × 8344344 ✓344 ✓
427 − 64−37−37 ✓−37 ✓
5144 / 12 + 7 × 33316533 ✓
618 boxes of 24 pencils, 157 sold: how many remain?275no answer275 ✓
746 × 17782−742742
8623 − 278345−345−345
939 − 82−43−43 ✓−43 ✓
1023 × 7 − 48113113 ✓113 ✓
11(63 − 28) × 6210210 ✓210 ✓
1214 bags of 18 marbles, 95 given away: how many remain?157no answer157 ✓
Correct5 / 129 / 12
Read this carefully Twelve questions is a tiny test set, and the in-prompt worked example (“14 is smaller, so the result is −9”) primes the model to add spurious minus signs — most wrong answers before training are sign errors. GRPO mostly fixed format and sign habits; the multiplication errors (27 × 34, 46 × 17) and one sign error (623 − 278) remain. A correct final answer also does not certify the reasoning in <think>.

6Notebook C · DPO on preference pairs

Notebook C at a glance

trl DPOTrainertransformers17 cells≈40 s training

Offline preference learning: no reward model, no value head, no generation during training. The model learns from fixed pairs of a preferred and a rejected answer to the same prompt.

The data are 128 short pairs from trl-lib/ultrafeedback_binarized (16 more for evaluation). One example:

Prompt

Given two Swahili sentences, label the second as the “cause” or “effect” of the first.

Chosen ✓

“Effect
Confidence: 90%”

Rejected ✗

“Effect. The second sentence is an effect of the first one, as it explains the reason why the person is now working in Kenya.” (invents a fact)

6.1 The DPO loss

DPO measures how much more the policy prefers the chosen answer than the frozen reference does, and pushes that margin up:

$$\Delta = \big[\log\pi_\theta(y^+\mid x)-\log\pi_\theta(y^-\mid x)\big]-\big[\log\pi_{\text{ref}}(y^+\mid x)-\log\pi_{\text{ref}}(y^-\mid x)\big],\qquad \mathcal{L}_{\text{DPO}} = -\log\sigma(\beta\Delta)$$
DPO loss
Left: the loss as a function of the margin with \(\beta=0.1\) (the notebook's worked numbers: Δ = −2, 0, +2 give 0.798, 0.693, 0.598). Right: the training loss of this run.
Notebook C, cell 13 (condensed)
training_args = DPOConfig(
    beta=0.1, loss_type="sigmoid",          # L = -log sigmoid(beta * margin)
    learning_rate=5e-6, max_steps=32,
    per_device_train_batch_size=1, gradient_accumulation_steps=4,
)
trainer = DPOTrainer(model=model, ref_model=None,   # None: TRL makes a frozen copy as reference
                     args=training_args, train_dataset=train_dataset,
                     eval_dataset=eval_dataset, processing_class=tokenizer)
trainer.train()
metrics = trainer.evaluate()   # rewards/accuracies, rewards/margins, loss

6.2 Results: a lesson in reading metrics

0.695eval loss (ln 2 = 0.693)
56%eval pairs where chosen > rejected (chance = 50%)
−0.003mean reward margin
5 / 8demo answers that changed

With 32 steps at learning rate 5e-6, the loss never leaves \(\ln 2\): the model has barely moved from the reference, and the evaluation margin is indistinguishable from zero. The answers do change (greedy decoding amplifies tiny probability changes) — for example the photosynthesis explanation became a numbered list — but these changes are not evidence of learned preferences.

The point of this notebookDPO's data requirement (fixed preference pairs) and its mechanics (a frozen reference and a classification-style loss) are fully visible here. Getting a measurable effect needs more steps, a larger learning rate or more pairs — see the exercises.

7Choosing a method

If you have…UseModels in memoryGenerates during training?Signal comes from
demonstrations (prompt, answer)SFT1nohuman-written answers
a modest GPU+ LoRA / QLoRA1 + small adapters——
preference pairs (chosen, rejected)DPO2: policy + frozen referenceno (offline)pairwise human/AI judgments
a verifiable answerGRPO2 + a reward functionyes, groups of \(G\)rules: answer checks, tests
a reward model and a budgetPPO4: policy, reference, reward model, criticyeslearned reward model

In Notebook A the four PPO “models” share one 4-bit base: they are adapters and small heads, which is why a 4B model fits on a 16 GB T4.

8Practical AI tools for research

A short companion deck by Siqi Rao covers three tools you will need for assignments and the final project.

Codex and coding agents

An agent reads files, edits code, runs tests and iterates within the permissions you grant. Put project rules in AGENTS.md, reusable workflows in Skills, and always review with git diff and your tests.

Cloud GPUs

AutoDL, Alibaba Cloud PAI, Virtai Cloud. Check GPU memory (model and batch size), budget, the CUDA/framework image and persistent storage. Calling a hosted LLM API needs no GPU.

LLM APIs

DeepSeek, Alibaba Cloud Bailian, Volcano Engine Ark, SiliconFlow, Zhipu AI, OpenRouter. Many are OpenAI-compatible: switching providers is mostly a different base URL, key and model name.
Calling an OpenAI-compatible LLM API
import os
from openai import OpenAI   # many providers speak the same protocol

client = OpenAI(api_key=os.environ["LLM_API_KEY"],          # never hard-code the key
                base_url="https://api.deepseek.com")         # change for another provider
reply = client.chat.completions.create(
    model="deepseek-chat",
    messages=[{"role": "user", "content": "Explain DPO in two sentences."}])
print(reply.choices[0].message.content)
Never commit API keysRead keys from environment variables or Kaggle/Colab secrets, as above, and check model IDs against the provider's current documentation.

9Pitfalls & troubleshooting

SymptomCause and fix
RuntimeError: Start a fresh Kaggle session and run this cell firstLibraries were imported before the pinned environment was set up. Run → Restart session, then run the setup cell first.
Enable a Kaggle GPU accelerator / CUDA out of memorySelect GPU T4 in the session options. On a smaller GPU reduce MAX_COMPLETION_LENGTH, GROUP_SIZE or the rollout batch.
Downloads fail or are very slowTurn Internet on in Kaggle; add an HF_TOKEN secret to avoid Hub rate limits.
Notebook A session timed out mid-runEach stage saves a verified ZIP. Download it from the Output panel, attach it as a private dataset and set RUN_MODE = "ppo_retry" to resume PPO without retraining SFT and the reward model.
GRPO loss is ≈ 0 and nothing seems to happenNormal for the logged loss (centred advantages). If frac_reward_zero_std is 1, all groups are uniform: use questions of mixed difficulty or a larger group.
DPO loss stays at 0.693The policy has not moved from the reference: train longer, raise the learning rate, or use more pairs; check rewards/accuracies.
PPO reward goes up but outputs get worseReward hacking: the policy exploits the reward model (e.g. generic praise). Increase \(\beta\), inspect samples, and evaluate with an independent judge.
Results change between runsSampling, small data and few steps make runs noisy. Fix seeds, compare on the same prompts, and report intervals rather than single numbers.

10Exercises

Not graded — but they map directly onto Assignment 2 and typical final-project experiments.

Warm-up · slides
Memory budget. Using 16 bytes/parameter for full fine-tuning, estimate the memory to fine-tune Qwen3-4B fully, with LoRA (bf16 base), and with QLoRA. Which fits on a 16 GB T4?
Warm-up · Notebook B
Advantages by hand. For rewards [1.1, 0.1, 0.1, 0.1] compute the group-relative advantages. Why does a rare correct answer get a large push (compare with slide 45)?
Core · Notebook C
Make DPO learn. Raise MAX_STEPS to 200 and the learning rate to 5e-5. Plot rewards/margins and rewards/accuracies. Then vary \(\beta\in\{0.01, 0.1, 0.5\}\): what changes?
Core · Notebook B
Remove the prompt bias. Delete the worked subtraction example from the prompt and re-run GRPO. Do sign errors before training disappear? Does GRPO still help?
Core · Notebook A
Turn the KL knob. Re-run PPO with \(\beta=0\) and \(\beta=0.2\). Compare validation reward, KL, repetition rate and a few raw samples. Do you see reward hacking at \(\beta=0\)?
Challenge
GRPO for something else. Write a reward function for a different verifiable task (e.g. unit conversion, a JSON format checker, or a medical multiple-choice answer key) and train with GRPOTrainer. Report before/after accuracy with a confidence interval.
Challenge
Same data, two methods. Build preference pairs from Notebook B's groups (a correct answer as chosen, a wrong one as rejected) and train DPO on them. Compare with GRPO on the held-out questions: when does online sampling matter?

11Self-check quiz

Click a question to reveal the answer.

1. Why are prompt tokens given the label -100 in SFT?The loss should only teach the model to produce the answer. Positions labelled -100 are ignored by the cross-entropy loss, so the model is not trained to reproduce the user's question.
2. Why is LoRA's \(B\) initialised to zero?So that \(\Delta W=BA=0\) at step 0: training starts exactly from the pre-trained model. \(A\) is random so that gradients for \(B\) are not zero.
3. In Notebook A, what are the four “models” PPO needs, and how do they fit on one T4?Policy (PPO adapter), reference (SFT adapter), reward model (reward adapter + head) and critic (value head). They share one frozen 4-bit base and differ only in small adapters and heads.
4. What does the KL penalty \(\beta\) prevent?It keeps the policy close to the SFT model, which preserves fluent language and limits reward hacking — exploiting weaknesses of the learned reward model.
5. A GRPO group gets rewards [1, 1, 1, 1]. What is the learning signal?Zero: every advantage is \((1-1)/(0+\varepsilon)=0\). Questions that are always solved (or never solved) teach nothing; this is why the notebook screens for mixed groups.
6. Why does GRPO not need a value model?The mean reward of the other answers to the same question serves as the baseline, replacing the learned \(V(s)\). This saves memory and avoids training a critic on sparse 0/1 rewards.
7. The DPO training loss stays at 0.693. What does that mean?\(-\log\sigma(0)=\ln 2\approx0.693\): the reference-adjusted margin is still about zero, so the policy has not learned to prefer chosen answers more than the reference does.
8. PPO raised the positive rate from 57.5% to 67.5%, but the 95% interval of the gain includes zero. What should you conclude?That the run is consistent with an improvement but does not establish one: 40 test prompts are too few. Use more evaluation prompts, several seeds, and report intervals.
9. When would you choose DPO over GRPO?When you have preference pairs but no automatic way to verify answers (e.g. helpfulness, tone, safety), and want a cheap, stable offline method. GRPO needs a reward you can compute on fresh samples.

12Further reading & credits

Credits Slides adapted from material by Martin (martinisadad.github.io). Notebook A is adapted from Ashwani Kumar's RLHF in Notebooks (Qwen3-4B, with added evaluation). Notebook B is adapted from Sergio Paniego, Post training an LLM for reasoning with GRPO in TRL (Hugging Face Cookbook, Apache 2.0). Notebook C is adapted from the Hugging Face Smol Course DPO notebook (Apache 2.0). AI tools deck by Siqi Rao.

Next steps: Lecture 6 slides (RL for LLM post-training) · Tutorial 1 · Course schedule

Tutorial 2 · CSC5051/CSC6052/MDS5110 Natural Language Processing · School of Data Science, CUHK-Shenzhen · Fall 2026. Numbers and outputs on this page come from the provided notebook runs on a Kaggle T4. ← Back to the course homepage