How Models Generate

Quantization: The Same Model in Fewer Bits

0 of 19 complete

0%

Contents

Back|How Models GenerateQuantization: The Same Model in Fewer Bits
1/19
44 min left
Prerequisites
Chat Templates: The Text a Conversation Becomesrequired
Related Topics
Smaller Numbers: Storing Embeddings in One Byte or One BitTokens and EmbeddingsThe Silent Cut: How Much of Your Text an Embedding Model Really ReadsTokens and EmbeddingsStructured Output Costs Right Answers: One JSON Box, MeasuredAgents in Production
1 of 19

Why Would Anyone Shrink a Model?

Every lesson so far has used qwen2.5:3b, a model with about 3.09 billion weights. A weight is one of the numbers the model learned during training; lesson 4's keys and values, for example, come from multiplying by such numbers. All 3.09 billion of them have to sit in memory for the model to run.

How much memory that takes depends on how precisely each number is stored. Store every weight as a 16-bit number and the model needs about 6 GB. Store them more roughly and it needs less. The model qwen2.5:3b that Ollama downloads by default is already stored roughly, at about 5 bits per weight, which is why it is under 2 GB.

Under the heading how much can you shrink a model before it changes, an illustration of a person holding a checklist and looking at a computer screen that shows a large square and a small square. Beneath: one model, three files, 6.18 GB, 3.29 GB and 1.93 GB.

Storing numbers with fewer bits is called quantization. Think of a photo saved at lower quality: the file gets much smaller, and most of the time you cannot see the difference, but look closely at the fine details and some are gone.

This lesson measures exactly that for a language model. It downloads the same model in three forms, and compares their size, their next-word odds, their answers and their speed on my laptop. It turns out that a smaller file does not only save memory; it also makes the model write faster, for a reason that connects back to lesson 3.

Words You Need First

A hand-drawn list of five terms. Weight: one learned number inside the model. Bit: a 0 or 1, and 16 bits can store a number finely. Quantization: storing each weight with fewer bits. F16, Q8_0, Q4_K_M: 16 bits, about 8.5, about 5 per weight. Memory bandwidth: how fast numbers move from memory to the chip. Beneath: Q8_0 is the same format lesson 5 found in the KV cache.

Weight. One of the numbers a model learned during training. qwen2.5:3b has about 3.09 billion of them.

Bit. The smallest unit a computer stores, a 0 or a 1. With 16 bits you can tell apart 65,536 different values; with 8 bits, 256; with 4 bits, only 16.

Quantization. Storing each weight with fewer bits, which means rounding it to the nearest of fewer possible values.

F16, Q8_0, Q4_K_M. The names Ollama and the llama.cpp project use for three formats: 16-bit numbers; 8-bit numbers with a shared scale; and a mix that is mostly 4-bit. You will see these names in model tags.

Memory . How many bytes a second can travel from memory to the chip that does the arithmetic. It matters more than you might expect, as the speed slide shows.

Three Files, One Model

The lab used three versions of the same model, all from Ollama's library: qwen2.5:3b (Q4_K_M), qwen2.5:3b-instruct-q8_0 (Q8_0) and qwen2.5:3b-instruct-fp16 (F16). They are the same trained model; only the storage of the weights differs.

Three isometric blocks headed Qwen2.5 3B Instruct, 3.09 billion weights, three files, titled same model, three sizes. The tallest, F16, 6.18 GB. The middle, Q8_0, 3.29 GB. The shortest, Q4_K_M, 1.93 GB. Beneath: height is the file size, same weights, fewer bits for each.

The files were 6.18 GB, 3.29 GB and 1.93 GB. Loaded with a 4,096-token window, Ollama reported 6.34, 3.44 and 2.09 GB, the file plus a little room for the window and working space.

A page in two columns headed 3,085,938,688 weights, times the bits for each, titled file size, by hand. The arithmetic: 3.09B times 16 divided by 8 equals 6.17 GB; 3.09B times 8.5 divided by 8 equals 3.28 GB; 3.09B times 4 divided by 8 equals 1.54 GB. The file on disk: F16 6.18 GB; Q8_0 3.29 GB; Q4_K_M 1.93 GB. Beneath, left: dividing by 8 turns bits into bytes. Right: Q4_K_M is bigger than 4 bits, from block scales and a quarter of the weights at 6 bits.

You can work the sizes out by hand. There are 3,085,938,688 weights. At 16 bits each, that is 3.09 billion × 16 ÷ 8 bytes, about 6.17 GB, almost exactly the F16 file. At 8.5 bits, about 3.28 GB, almost exactly the Q8_0 file. At a pure 4 bits it would be 1.54 GB, but the Q4_K_M file is 1.93 GB, for two reasons of about equal size. Each block of 4-bit weights also stores its own scale and minimum, which brings those weights to about 4.5 bits each. And about a quarter of the weights, including the table that turns tokens into numbers, are stored in a 6-bit format. Dividing the file size by the number of weights gives 5.0 bits per weight on average.

What the Names Mean

Three editorial boxes inside a frame labelled bits per weight, from file size and weight count, titled what F16, Q8_0 and Q4_K_M mean. F16, 16.0 bits: each weight a 16-bit number, as close as this lesson gets to the original. Q8_0, 8.5 bits: 8 bits per weight plus one shared scale per block of 32. Q4_K_M, 5.0 bits: about 4.5 bits for three quarters of the weights, about 6.6 for the rest. Beneath: the file also holds the tokenizer and settings, so these are slight overestimates.

F16 stores each weight as a 16-bit floating-point number, a format that keeps about three significant digits and a wide range of sizes. This lesson treats it as the reference, the version closest to the model as it was trained.

Q8_0 groups the weights into blocks of 32. Each block keeps one shared scale, a 16-bit number, and each weight in the block is stored as an 8-bit whole number from −127 to 127 that is multiplied by the scale. That is 32 bytes for the weights plus 2 for the scale, 34 bytes per 32 weights, which is 8.5 bits per weight. If that sounds familiar, it is the same q8_0 format that lesson 5 found this laptop's Ollama using for the .

Q4_K_M is a mix from the llama.cpp project, which is the engine Ollama runs. About three quarters of the weights are stored as 4-bit numbers in blocks that carry their own scales, about 4.5 bits each once those are counted. About a quarter, chosen tensor by tensor (a tensor is one table of weights), are stored in a 6-bit format; in this file that includes the token table and the value weights of every layer. The "K" names the family of methods and the "M" means the medium-sized mix. ollama show --verbose lists each tensor's format, and the lab measured the result as 5.0 bits per weight on average.

What Rounding Does to a Weight

A hand-drawn sketch of three rows of steps. 16 bits: sixteen small boxes. 8 bits: eight wider boxes. 4 bits: four wide boxes. Beneath the rows: fewer steps, each weight is rounded more. Beneath: a sketch, not to scale, 16 bits give 65,536 steps, 8 bits 256, 4 bits 16.

Think of a ruler. A ruler marked in millimetres lets you record a length precisely. A ruler marked only in centimetres forces you to round every length to the nearest centimetre. Quantization swaps a fine ruler for a coarse one.

With 8 bits and a scale shared by 32 weights, the steps are fine: in the playground at the end of this lesson, the largest change to eight sample weights is 0.0032. With 4 bits, there are only 16 steps (the box uses 15, from −7 to 7), and the largest change is 0.0557, about seventeen times as much. In proportion, small weights suffer most: at 4 bits, three of the eight sample weights round to exactly zero.

One rounded weight hardly matters. The question is what billions of slightly rounded weights do together. That is what the next measurements test.

Compare Them Yourself

This script asks each of the three files for the next word after "The capital of France is", with its probability, and then times how fast each writes 64 tokens.

A real screenshot of VS Code with quant_compare.py open, all 33 lines. The docstring says run it after pulling the three models. It lists the three model names and the prompt The capital of France is, reads each model's file size from /api/tags, then for each model asks for one next token with its probability, asks for a 64-token short story about a lighthouse, and prints the model name, its size in GB, the next word with its probability, and its writing speed in tokens a second. Beneath: copy it from the box on the slide.

Before you run this lab. It uses qwen2.5:3b, qwen2.5:3b-instruct-q8_0 and qwen2.5:3b-instruct-fp16, running in Ollama on your own computer. If you have not set that up yet, the lab setup guide shows how to install Ollama, download the models and check that everything works, on macOS, Windows or Linux. You can use a different model instead: the guide shows the one line to change, and your numbers will differ from the ones in this lesson.

"""The same model stored three ways: how big, how fast to write, and does the next word change?

Run it with Ollama running and the three models pulled:
    ollama pull qwen2.5:3b
    ollama pull qwen2.5:3b-instruct-q8_0
    ollama pull qwen2.5:3b-instruct-fp16
    python quant_compare.py
"""
import json
import math
import urllib.request

MODELS = ["qwen2.5:3b", "qwen2.5:3b-instruct-q8_0", "qwen2.5:3b-instruct-fp16"]
PROMPT = "The capital of France is"


def post(path, body):
    req = urllib.request.Request("http://localhost:11434/api/" + path, data=json.dumps(body).encode(),
                                 headers={"Content-Type": "application/json"})
    return json.loads(urllib.request.urlopen(req).read())


sizes = {m["name"]: m["size"] for m in json.loads(urllib.request.urlopen("http://localhost:11434/api/tags").read())["models"]}
for model in MODELS:
    first = post("generate", {"model": model, "prompt": PROMPT, "raw": True, "stream": False, "logprobs": True,
                              "top_logprobs": 1, "options": {"num_predict": 1, "temperature": 0}})
    top = first["logprobs"][0]["top_logprobs"][0]
    run = post("generate", {"model": model, "prompt": "Write a short story about a lighthouse.", "stream": False,
                            "options": {"num_predict": 64, "temperature": 0}})
    speed = run["eval_count"] / (run["eval_duration"] / 1e9)
    print(f"{model:<27} {sizes[model] / 1e9:4.2f} GB  next word {top['token']!r} at {math.exp(top['logprob']):.2f}"
          f"  writes {speed:4.1f} tokens/s")

Do the Next-Word Odds Change?

The lab asked all three files for their ten most likely next words on lesson 1's 24 prompts: 12 with one clear answer, such as "The capital of France is", and 12 open ones, such as "My favourite food is". F16 is the reference.

A scatter chart headed probability of F16's top word, 24 prompts, titled Q8_0 sits on the line, Q4_K_M wanders. Along the bottom, the probability in F16 from 0 to 1; up the side, the probability of the same word in the smaller file. A diagonal line marks no change. The Q8_0 dots sit on or very near the line; the Q4_K_M dots scatter further from it. Beneath: top word unchanged, Q8_0 24 of 24, Q4_K_M 19 of 24.

Q8_0 kept F16's top word on all 24 prompts, and the probability of that word moved by a median of 0.4 percentage points, at most 2.8. For practical purposes, it is the same model.

Q4_K_M kept the top word on 19 of the 24. The probability of F16's top word moved by a median of 2.9 points and at most 14.4. That is a visible change, but look at where it happened.

Two panels headed The best way to learn is, next word, titled where a near tie flips. Left, F16: to 0.30, its top choice, with by second at 0.26. Right, Q4_K_M: by 0.31, a different top choice. Beneath: all 5 of Q4_K_M's changed top words were on open prompts like this one, where two words were almost equally likely.

All 5 changed top words were on open prompts, and all 12 prompts with one clear answer kept theirs. After "The best way to learn is", F16 put " to" first at 0.30 and " by" second at 0.26; Q4_K_M swapped them, with " by" first at 0.31. The other four changes were similar: two or more words nearly tied, and a small nudge swapped their order. Where one word was well ahead of the rest, rounding did not change the winner.

Why Sure Answers Survive and Near Ties Flip

Why did rounding leave every clear answer alone and flip only near ties? Lesson 1 showed that the model's odds come from a score for every token in its vocabulary; the scores are turned into probabilities, and the highest score wins. Rounding billions of weights adds a little noise to every score.

When one token's score is far ahead of the rest, as with " Paris" after "The capital of France is", a little noise cannot change the order. The probability may move, and here it did, from 0.51 in the F16 file to 0.62 in the Q4_K_M file, but the winner stays the winner. When two tokens are nearly level, as with " to" at 0.30 and " by" at 0.26 in F16, the same small amount of noise is enough to swap them.

Notice also that the noise does not only make the model less sure. The Q4_K_M file was more sure of " Paris" than the F16 file. Rounding moves scores in both directions; it does not simply make a model "dumber". What it does, on average, is make the smaller file's odds a little different from the original's, and those differences show wherever the original was nearly undecided.

That gives a rule of thumb you can use: quantization is least likely to matter for questions with one clear answer, and most likely to show on open-ended writing, where many continuations are nearly equally likely anyway. The measurement of longer texts on the next slide shows the same thing from another angle.

Do the Answers Change?

Odds are one thing; answers are what users see. The lab asked each file 40 two-digit multiplications, such as "What is 47 x 83? Answer with the number only.", through the chat template at temperature 0.

A hand-drawn bar chart headed 40 two-digit multiplications, chat, temperature 0, titled right answers, of 40. F16, 33. Q8_0, 33. Q4_K_M, 30. Beneath: Q4_K_M lost 5 that F16 got and gained 2 it missed, a difference this small could be chance, sign test p = 0.45.

F16 got 33 right and Q8_0 got 33 right, the very same 33. Q4_K_M got 30. That looks like a loss, but look at the details: Q4_K_M got 5 wrong that F16 got right, and 2 right that F16 got wrong. A sign test, which asks how likely a split of 5 against 2 is if neither version is really better, gives p = 0.45, where p is the chance of a split at least this lopsided happening by luck alone. A split like that happens often by chance. With only 40 questions, this lab cannot tell whether Q4_K_M is worse at sums.

A table headed 12 open prompts, 64 tokens each, greedy, against F16, titled how long until the text differs. Q8_0: a median 136 characters the same, 1 of 12 texts identical. Q4_K_M: a median 8 characters the same, 0 of 12 texts identical. Why it grows: one different word changes everything written after it. Beneath: different is not worse, these were open prompts with many good continuations.

Longer texts show the rounding more. The lab wrote 64 tokens greedily from each of the 12 open prompts and compared each text with F16's. Q8_0's texts stayed the same as F16's for a median of 136 characters before the first difference, and 1 of the 12 was identical all the way. Q4_K_M's texts differed after a median of only 8 characters. That is lesson 2's point again: once one word differs, every later word is written after a different history, so small changes grow. On open prompts, a different text is not a worse text; it is just a different one of many good continuations.

The Surprise: Smaller Is Faster

The lab timed each file writing 128 tokens after a prompt of about 1,000 tokens, in 3 rounds with the three files in a shuffled order each round, 6 calls per file.

A bar chart headed median of 6 calls each, about 1,000-token prompt, 128 tokens written, titled writing got faster, reading did not. Three bars of writing speed: Q4_K_M 28.4, Q8_0 18.3, F16 11.1 tokens a second. Beneath: writing, Q4_K_M 28.4, Q8_0 18.3, F16 11.1, and reading barely moved, 240, 218 and 233 tokens a second.

Writing speed rose as the file shrank: 11.1 tokens a second for F16, 18.3 for Q8_0 and 28.4 for Q4_K_M. The smallest file wrote about 2.6 times as fast as the largest. Reading speed hardly moved: 233, 218 and 240 tokens a second, within the laptop's usual noise.

Why would writing depend on the file size? Lesson 3 showed that writing is done one token at a time. For every single token, the chip must use every weight in the model once, and the weights live in memory, so for every token they must be fetched from memory to the chip.

A sequence diagram headed writing one token, a simplified picture, titled every weight, once per token. Three columns: memory, the chip and output. Step one, all the weights, layer by layer, go from memory to the chip. Step two, a little arithmetic on them, on the chip. Step three, one token, to the output. Step four, all the weights again, next token, from memory to the chip. Beneath: half the bytes to move means roughly twice the tokens a second.

If moving the weights is the slow part, then writing speed times file size should come out roughly the same for all three files: the number of bytes the laptop can move per second.

A table headed file size times writing speed, lab medians, titled writing moves the weights. Q4_K_M: 1.93 GB times 28.4 tokens a second is 55 GB/s. Q8_0: 3.29 GB times 18.3 is 60 GB/s. F16: 6.18 GB times 11.1 is 69 GB/s. Beneath: if each written token reads every weight once, the laptop moved 55 to 69 GB of weights a second, probably the limit.

It does, roughly: 1.93 × 28.4 ≈ 55 GB a second, 3.29 × 18.3 ≈ 60, and 6.18 × 11.1 ≈ 69. The figures are not identical, because unpacking 4-bit numbers takes a little arithmetic too, but they are close enough to suggest where the time goes: writing is probably mostly waiting for memory. The gap between them may partly be the extra arithmetic of unpacking 4-bit numbers. This is a calculation from the lab's numbers, not a direct measurement of .

Reading a prompt is different. Lesson 3 explained that reading handles many tokens at once, so each weight fetched from memory is used for many tokens before the next is needed, and fetching is no longer the slow part. That is a likely reason reading speed barely changed; the lab measured the speeds, not the cause.

What Fits on Your Machine

Speed is a welcome surprise, but the main reason people quantize is memory. A model only runs if all its weights fit in memory, alongside the from lesson 5 and everything else the computer is doing.

Worked by hand with this lesson's bits per weight: a model with 7 billion weights needs about 7 × 16 ÷ 8 = 14 GB at F16, but about 7 × 5 ÷ 8 ≈ 4.4 GB at Q4_K_M's 5 bits. On a laptop with 16 GB, the first barely fits, if at all, once the operating system and a browser are running; the second leaves plenty of room. A model with 70 billion weights needs about 140 GB at F16, about 74 GB at Q8_0's 8.5 bits, and about 44 GB at 5 bits. None of those fits this 24 GB laptop, and only the smallest fits a machine with 64 GB.

So quantization often decides which model you can run at all, not just how fast it runs. A bigger model at 5 bits can be a better choice than a smaller model at 16 bits, if both fit. This lab did not compare models of different sizes, so it cannot say where that line falls for your task.

Remember the other costs from earlier lessons too. The window you set reserves KV cache memory on top of the weights, and on this laptop that cache was itself stored in q8_0, which is quantization applied to the keys and values instead of the weights.

The Lab Report

A real terminal recording of python quant.py report. Section 1, size, 3.09 billion weights, loaded at num_ctx 4096 with a q8_0 KV cache: Q4_K_M 1.93 GB file, 5.0 bits per weight, 2.09 GB loaded; Q8_0 3.29 GB, 8.5 bits, 3.44 GB; F16 6.18 GB, 16.0 bits, 6.34 GB. Section 2, next-token odds on 24 prompts against F16: Q4_K_M top token the same on 19 of 24, probability moved by a median 2.9 points, at most 14.4; Q8_0 24 of 24, median 0.4, at most 2.8; F16 24 of 24, 0.0. Then Q4_K_M's 5 changed top tokens, 5 on open prompts and 0 on fact prompts, listed with their probabilities. Section 3, answers: Q4_K_M 30 of 40 multiplications, 0 of 12 texts identical to F16, a median 8 characters before the first difference; Q8_0 33 of 40, 1 of 12, 136; F16 33 of 40, 12 of 12, 288; Q4_K_M against F16, 5 lost and 2 gained, sign test p = 0.45; Q8_0, 0 lost and 0 gained. Section 4, speed: Q4_K_M reads 240 and writes 28.4 tokens a second, Q8_0 218 and 18.3, F16 233 and 11.1; then size times writing speed, 55, 60 and 69 GB/s moved, with the note that this assumes each written token reads every weight once.

The lab is scripts/labs/generate/quant.py. It reads the sizes from Ollama, loads each file with the same window, and runs the four measurements. The speed test uses a unique first line in every prompt, lesson 6's guard against reuse, and checks that no prompt was read impossibly fast.

Two details in the report were added after reading the first version. The first listed only "19 of 24" for Q4_K_M, which sounds like a model that gets a fifth of its words wrong; listing the five changes showed they were all near ties on open prompts. The second compared 30 against 33 right answers; the sign test shows that difference is too small to call.

Which One Should You Run?

A table headed on this laptop, for this model, titled which one to run. Q4_K_M: smallest and fastest, top word changed only in near ties. Q8_0: half the size of F16, almost identical to F16 here. F16: the reference, slowest, and needs the most memory. Beneath: test on your own task before you trust any of them.

On this laptop, for this model and these tests, the choice looks like this. Q4_K_M is a third of the size of F16 and writes about 2.6 times as fast; on these tests its differences were small and mostly on near ties. Q8_0 is about half the size of F16, writes about 1.6 times as fast, and was almost indistinguishable from F16. F16 is the reference and the slowest.

This is probably why many of Ollama's default tags are a 4-bit mix: it is a good trade for most people on most machines. But "these tests" is doing a lot of work in that sentence. This lab used short prompts and simple sums. A task that depends on fine detail, such as exact code, careful arithmetic in long chains or a language the model saw little of, may suffer more from rounding. The only fair test is your own.

A flowchart. Run Q4_K_M leads to a decision: good enough on your own test set? Yes leads to ship it, fast and small. No leads to try Q8_0, then a second decision: now good enough? Yes leads to ship Q8_0. No leads to the model, not the bits, is the limit. Beneath: your own test set is the only fair judge, and this lab used 24 prompts and 40 sums.

A sensible order is to start with the small file, check it on 20 to 50 examples from your real task, and step up to Q8_0 only if it falls short. If Q8_0 also falls short, the problem is probably the model itself, not how its weights are stored, and a bigger or different model is the answer.

Round Some Weights in Your Browser

This box has no model. It rounds eight made-up weights to 8 bits and to 4 bits, using one shared scale as Q8_0 does, and then works out the file sizes by hand.

It prints the 8-bit weights, whose largest change is 0.0032, and the 4-bit ones, whose largest change is 0.0557 and where 0.0213, −0.0062 and 0.0555 all became 0.0. Then it prints 6.18, 3.28 and 1.93 GB, close to the three files. Change the weights, or try 6 bits, and watch how the rounding grows. Real formats are cleverer than this box: Q4_K_M gives each group of 32 weights its own scale and minimum, so a group of small weights gets finer steps, and it stores about a quarter of the weights at 6 bits.

The Code, Part by Part

The three names. MODELS lists the three Ollama tags. They must be pulled first; the first one is the default qwen2.5:3b, which is the Q4_K_M file.

The file size. /api/tags lists every model Ollama has, with its size in bytes, so the script reads the size rather than guessing it.

The next word. A raw call with "logprobs": True and "top_logprobs": 1 returns the most likely next token and its log probability. math.exp turns the log probability back into an ordinary probability, as in lesson 1.

The speed. A second call writes 64 tokens. eval_count divided by eval_duration, turned from nanoseconds into seconds, gives tokens written per second, the same measure as lessons 3 and 5.

The lab. quant.py does all of this more carefully: 24 prompts instead of one, 40 sums, 12 longer texts, and speed timed in shuffled rounds with medians.

Common Mistakes

Assuming the default is full precision. qwen2.5:3b is already a Q4_K_M file at about 5 bits per weight. Check with ollama show.

Calling a small difference a loss. 30 against 33 right answers had a sign test p of 0.45: too close to call with 40 questions.

Testing on one prompt. One prompt showed the same answer, Paris, in all three files. The texts of 64 tokens showed how different they can become.

Forgetting the speed gain. Smaller files write faster on a laptop, most likely because writing is mostly waiting for memory.

Trusting general benchmarks for your task. The trade depends on the task; test on yours.

Comparing speeds from single runs. One run, on a different and shorter prompt, gave 36.2 tokens a second for Q4_K_M; the lab's median was 28.4. Use medians over several runs.

What This Lab Can and Cannot Tell You

A page in two columns. Under measured: one 3B model, three files; 24 prompts, 40 sums, 12 texts; writing speed on one laptop. Under not measured: bigger models, other formats; long, hard or specialist tasks; whether bandwidth is the only limit.

The lab compared three files of one small model on one laptop, with 24 prompts, 40 sums and 12 texts. Larger models are often said to tolerate rounding better and smaller ones worse, but this lab did not test that. It did not test other formats, such as 2-bit or 6-bit files, or tasks that need long exact reasoning. And the arithmetic is a calculation from measured speeds and sizes, not a measurement of the memory system itself.

Two brand cards. Ollama: qwen2.5:3b in 3 formats, Apple M4, 24 GB. Python: 24 odds, 40 sums, 12 texts, 18 timed calls per run.

Everything ran locally with Ollama and Python, so you can repeat it on your own machine, if it has room for the 6 GB file.

What to Do on Monday

A hand-drawn list of four steps. 1, check it: ollama show, which quantization is your model? 2, test it: your own 20 to 50 cases, not a benchmark. 3, compare it: run the next size up on the same cases. 4, time it: writing speed is where the smaller file pays. Beneath: smaller files write faster, check what they change.

Run ollama show on the model you use and read its quantization line, so you know what you are running. Then collect 20 to 50 real examples from your task, with the answers you expect, and run them through your current file and the next size up. If the scores are the same, keep the smaller file and enjoy the speed. If they differ, look at the examples that changed before deciding: they tell you whether the smaller file fails on something that matters to you.

A closing card headed to keep, a third of the size, 2.6 times the speed. In large type: 11.1 to 28.4 tokens/s. Beneath: writing, F16 at 6.18 GB against Q4_K_M at 1.93 GB. In the accent colour: test the small one on your own task first.

Knowledge Check

Knowledge Check

4 questions - Score 80% to pass

Q1

qwen2.5:3b has about 3.09 billion weights. About how big is the file at 16 bits per weight?

Q2

Q4_K_M changed the top next word on 5 of 24 prompts. Where did those changes happen?

Q3

Why did the smaller files write faster?

Q4

Q4_K_M got 30 of 40 sums right and F16 got 33. What does the lab conclude?

This is a real run in VS Code's terminal.

A real screenshot of VS Code's terminal after running python quant_compare.py. qwen2.5:3b: 1.93 GB, next word Paris at 0.62, writes 36.2 tokens a second. qwen2.5:3b-instruct-q8_0: 3.29 GB, next word Paris at 0.51, writes 24.0 tokens a second. qwen2.5:3b-instruct-fp16: 6.18 GB, next word Paris at 0.51, writes 12.5 tokens a second.

All three chose " Paris". The Q8_0 and F16 files gave it the same probability, 0.51; the Q4_K_M file gave it 0.62. So the smallest file was more sure of the same answer. And the writing speed rose sharply as the file got smaller: 12.5, 24.0 and 36.2 tokens a second in this run.

These speeds were higher than the lab's, which are below, partly because this script writes after a one-line prompt while the lab writes after about 1,000 tokens (lesson 5 showed a long prompt slows writing), and partly because a laptop's speed moves from run to run, as lessons 3 and 5 showed. The lab takes medians over shuffled rounds; this one run is only an example.