CODETIPS ACADEMY / FINE-TUNING METHODS

Part 1 — What Is Fine-Tuning? Teach an Existing Model a New Job

Understand weights, training, and useful applications with a one-weight numerical experiment.

Project: Workshop Assistant · Audience: basic Python developers · Run: CPU; optional external training only in Part 10.

Start with a familiar idea

Fine-tuning means taking a model that has already learned something and training it further for a more specific task. A model contains numbers called parameters or weights. Training changes those numbers using examples. Fine-tuning starts from learned numbers rather than starting again from random numbers.

Imagine a developer who already knows Python. Teaching that developer your team's naming conventions is easier than teaching programming from zero. The analogy has limits: a model is calculating outputs, not understanding a lesson like a person. Still, it helps separate pretraining, which builds broad capabilities, from fine-tuning, which adapts an existing starting point.

What can you use it for? A support team might classify questions into Python, Linux, and IoT queues. A coding assistant might learn a consistent JSON response format. An image model might recognize defects on your own camera feed. A writing model might follow reviewed examples of your organization's tone. These are tasks with patterns that can be demonstrated repeatedly.

Fine-tuning is not a dependable database update mechanism. If an ESP32 product price changes every day, retrieve the current price from a database. Changing weights does not guarantee exact recall, correct citations, or deletion of old facts. Prompting, retrieval, validation, and fine-tuning can be combined.

Our project and the tools you need

We will build a tiny Workshop Assistant for Python, Linux, and ESP32 questions. Parts 1–9 use original, synthetic examples and small PyTorch models on CPU. They do not call a paid API or download model weights. You will see actual gradient updates, frozen layers, LoRA matrices, training curves, and evaluation results.

These are teaching models, not a capable pretrained chatbot. We explicitly train a small source model before adapting it. Part 10 shows how the same workflow connects to a public pretrained language model. Its external-model training is optional and separately marked.

You only need basic Python: variables, lists, functions, imports, and classes. A tensor is an array that can track derivatives; a gradient tells us which direction increases a loss; a loss is a number that measures a mismatch. We will introduce each when it appears. Install the ZIP's requirements and open the notebook matching this part. The README has Windows and Linux instructions.

One weight, one training example

Suppose an existing model predicts y = w*x. Its learned weight is w = 2. Our new task has the example x = 2, desired answer y = 6. The model currently predicts 4. Use squared error: (prediction - target)^2 = (4 - 6)^2 = 4.

The derivative with respect to the weight is 2*x*(w*x - y) = 2*2*(-2) = -8. With learning rate 0.1, the update is w_new = w - 0.1*gradient = 2.8. The prediction becomes 5.6 and the loss becomes 0.16. We improved this example by changing an existing weight.

Part 1 explained visually

import torch
w = torch.tensor(2.0, requires_grad=True)
x, target = torch.tensor(2.0), torch.tensor(6.0)
loss = (w*x - target)**2
loss.backward()
print('before:', w.item(), 'loss:', loss.item(), 'gradient:', w.grad.item())
with torch.no_grad():
    w -= 0.1*w.grad
new_loss = (w*x-target)**2
print('after:', w.item(), 'prediction:', (w*x).item(), 'loss:', new_loss.item())
assert abs(w.item()-2.8) < 1e-5
assert new_loss < loss

Executed output (CPU teaching experiment):

before: 2.0 loss: 4.0 gradient: -8.0
after: 2.799999952316284 prediction: 5.599999904632568 loss: 0.16000007092952728

requires_grad=True asks PyTorch to track operations involving the weight. backward() calculates its gradient. The no_grad() block updates the value without recording that update as another differentiable calculation. In a larger model, an optimizer performs updates for thousands or billions of weights.

One successful example does not establish a useful model. If the original job needed w=2, moving toward 3 can make the old job worse. This is a first glimpse of forgetting. We need unseen examples, a baseline, and often a mix of old and new tasks.

Should you fine-tune?

Situation First experiment
The instruction is unclear Improve the prompt and examples
The answer depends on fresh documents Retrieve documents; check sources
A rule can decide the answer exactly Implement the rule
Many reviewed examples demonstrate the same behavior Evaluate a fine-tuning experiment
You have only a few inconsistent labels Improve the data before training

Fine-tuning has costs: collecting examples, checking labels, running experiments, and maintaining a model version. A small classifier may solve your problem more cheaply than adapting a language model. Decide by measured behavior, not by the popularity of a method.

Check your understanding

Change the learning rate to 0.01, rerun the cell, and explain why the update is smaller. Then try 1.0: a larger step can overshoot and make the loss worse. A learning rate is a step-size choice, not a percentage improvement.

By the end of this part, you should be able to explain the difference between changing a prompt and changing weights. Next, we will define a concrete task and separate training examples from the examples used to judge the result.

Further reading: PyTorch transfer learning tutorial.

Part 2 →