← Part of Lysen · lysen.org
Lysen ML
← All algorithms Supervised · regression

Linear regression

The problem it solves: a linear regression model is a straight line which tries to fit all of the data points as tight as possible. You have a number you want to predict, for example a price, a demand or a temperature, and one or more numbers you already know. Any method that predicts a number rather than a category belongs to a family called regression, and this is where that family starts.

The idea in one sentence: draw a line, see how close it is to all of the data points, then repeat, trying to make the distance to the data points lower. That is the entire algorithm. Everything else in this chapter is about what "how close" means, which direction to move next, and the four ways a straight line will quietly lie to you.

Used for house and rent pricingdemand forecastingtrend linesrisk scoringthe baseline every model must beat
Learning typeSupervised
Primary taskRegression
MechanismLinear · gradient descent

Running example for the whole chapter: houses for sale. Every point is one house, where x = size in m² and y = the asking price in euros. One column keeps every idea visible on a flat chart, and this is the simple version, so no ridge, no lasso. Those are in module 4, once you have seen the problem they solve.

01

Intuition: draw the perfect line

What it does. Suppose we have data about the prices of houses, so we have the amount of square meters against the price of the house. Every house is one dot on a chart. The model is the line you draw through those dots, and once you have that line you can read a price off it for any size you like, including sizes nobody in your data has. That is both the useful part and, later, the dangerous part.

How it does it. Draw a line, see how close it is to all of the data points, then repeat, trying to make the distance to the data points lower. A line only has two numbers in it: the slope w, which is how many euros one extra square meter adds, and the initial value β, which is where the line starts. Fitting means finding the pair of numbers that leaves the smallest total distance to the dots.

Why the line is worth having. Two reasons, and they are different. The first is prediction: a new house comes on the market at 96 m² and you want a number. The second is explanation: the slope is a sentence you can say out loud in a meeting, something like "in this city, a square meter is worth about €2,670", and most models cannot give you that sentence at all.

1a The problem, before any algorithm

This is what you actually get: 52 houses, a size and a price for each, and nothing else. Your eye has already drawn the line, roughly, before you finished reading this sentence. That is exactly the point. The relationship is obvious to you, and the whole chapter is about writing down what your eye just did, so a computer can do the same thing on twelve columns you cannot picture.

Bigger houses cost more. Nobody needed maths for that. What you cannot do by eye is say how much more, per square meter, or how wrong that answer is.

1b Be the algorithm: fit the line by hand

your line the miss on each house best possible line
price = 240,000 + 1,500 × size
…mean absolute error …RMSE …mean squared error (€²) …worse than best by

Tune the two sliders to fit the line as close to the data points as possible, and watch the three errors underneath. They all say the same thing in different units, and they all get smaller as the line gets better. The button does it in one shot with the maths from §2c, but try to beat it by hand first, it is harder than it looks, and that difficulty is the reason the rest of the chapter exists.

02

The algorithm: every step of the loop

What you just did with two sliders is written out below as a recipe. Programmers call this kind of numbered recipe pseudocode, which just means code written for humans instead of for a computer.

1initialize the slope w and the initial value β // any two numbers will do (§2a)
2repeat:
3 see how well the line fits // one number for the whole line (§2b)
4 update the initial value and the weights // step downhill (§2c)
5until a certain difference threshold is met // it stopped improving (§2d)

Three of those five lines need real numbers before a computer can run them: how you start, what "how well it fits" means, and how you update. Each gets its own panel below, and each panel repeats the line it is about so you never have to scroll back up here.

2a Line 1: how to initialize

1 initialize the slope w and the initial value β ← the line this panel is about

Initialization is quite simple: you can start with any initial weight values and any initial value β. As you saw in module 1, the loop gets closer to the perfect line every time it runs. Of course, a starting line that is further away takes longer to get to the perfect line than a closer one, so if you can estimate something sensible, start there.

In practice that means: zeros are a perfectly good start, a rough guess is a slightly better one, and the only genuinely bad start is one so extreme that the first steps overshoot. Pick a starting line below and watch it walk. Same data, same learning rate, same target, only the first line differs.

…
…step …RMSE now …steps to settle

Notice what does not change: the line it ends on. All three land in the same place, because for a straight line there is only one valley to fall into, and that stops being true the moment a model gets more interesting than this one. What changes is only how long you wait.

2b Line 3: seeing how well the line fits

3 see how well the line fits // turn a whole line into one number

For one house the error is easy. Take the real price, subtract the price the line predicts, and you have how far off you were. Do that for all 52 houses and you have 52 numbers. What you want is one number, so that you can hold two lines next to each other and say which one is better.

The most common one is the root mean squared error (RMSE). Square every error, take the mean of those squares, then take the square root of the result. The squaring makes everything positive and punishes a big miss much harder than a small one. The square root at the end matters more than it looks: without it you are holding a number measured in euros squared, and nobody has any feeling for what a euro squared is. With it, you are back in euros.

RMSE = √( (1/n) Σ (yᵢ − ŷᵢ)² ) // ŷ = β + w·x, the price the line predicts
MAE  = (1/n) Σ |yᵢ − ŷᵢ| // the same misses, without the squaring

The other one is the mean absolute error (MAE). Take the size of every error, ignore the sign, and average them. It answers a question you can say out loud: on an average house, how many euros is this line wrong by? Both are worked out over all houses, and for both, smaller is better.

They sound like the same thing said twice, and on this data they are not. Below is what each one does with a miss, and which houses end up owning the score.

…× worse to MAE …× worse to squared error

Both curves are drawn against the same misses, and scaled so the biggest one on the chart counts as 100. MAE is a straight line: twice the miss, twice the punishment. Squared error is a parabola: twice the miss, four times the punishment. Drag the slider and compare the two multipliers, which are measured against a €20k miss.

share of the MAE share of the squared error
…
…MAE of the best line …RMSE of the same line …RMSE ÷ MAE

Same line, same 52 houses, two different numbers, and RMSE is always the bigger of the two. The gap between them is a measurement in its own right: it is small when your misses are all about the same size, and it grows the moment a few houses are much further out than the rest. If RMSE is far above MAE, go and look at your extremes before you do anything else.

CuriousWhy not just use the differences?

A question which might have come up in your mind is: why not just use the differences, or the average of the differences? That is because sometimes the line is above the data points, which makes the difference negative, and when the point is above the line it is positive. So they cancel each other out.

Which means a line that is badly wrong, but wrong evenly above and below, scores exactly as well as the perfect line. Try it: both lines below have an average difference of about zero, and only one of them is any good.

…mean of the raw differences …mean absolute error
line is under the house (+) line is over the house (−)

The first number cannot tell the two lines apart. The second one can, and it is not close. That is why, if you just want the difference, you take the absolute error, or the mean absolute error (MAE).

CuriousWhy then squared?

So the absolute error already fixes the cancelling problem, and it is easier to explain. Why does everybody square instead? Because of outliers.

An outlier is a data point that sits far away from the pattern the rest of the points make. In this data it would be a house that is cheap for its size because it is falling apart, or one that costs double because it comes with half a canal. Squaring means a miss of €200,000 counts one hundred times as much as a miss of €20,000, not ten times as much. So the squared error is desperate to reduce that one house, and it will tilt the whole line to do it. The absolute error mostly shrugs at it.

Drag the ringed house around and watch the two lines come apart. This panel uses half the market, 26 houses, because the fewer rows you have the louder one strange row shouts, so small data and outliers are a dangerous pair. Neither line is cheating; they are answering different questions.

fitted on squared error fitted on absolute error
Drag the ringed house. It starts where it belongs, so both lines start close together.
…gap between the two lines at 190 m² …squared-error line moved by

So which do you use? If the strange house is a typing error, you want the line that ignores it, and you should also go and fix the data. If it is real and you will be asked to price houses like it, a line that pretends it does not exist is worse than useless. That decision is not in the formula, and it comes back in module 6.

2c Line 4: update, or how to get closer to the perfect line

4 update the initial value and the weights // the only line that actually changes anything

You now have one number saying how wrong the line is. The last piece is what to do about it, and here is the picture that makes it obvious.

Think of it as a landscape. Every pair of numbers (w, β) is a spot on a map, and the error of that pair is the height of the ground there. Bad lines are high up on a hill. Good lines are down in a valley. The perfect line is the lowest point in the valley. Fitting is walking downhill in that landscape, except you are blindfolded, so all you can do is feel which way the ground slopes under your feet and take a step that way. Then feel again, and step again.

That is gradient descent. The slope under your feet is the gradient, and how big a step you take is the learning rate η. Two things go wrong, and both are visible below. Steps that are too small mean you are still walking at sunset. Steps that are too big and you jump clean over the valley floor and land higher up the other side, and the next jump is worse, and the line flies off the chart.

The stronger the colour, the lower the ground, so the teal streak is the valley floor, and the cross marks its lowest point. Notice the valley is a long diagonal ditch rather than a round bowl: slope and initial value trade off against each other, so many combinations are nearly as good as each other, and the walk down the middle is slow.

0steps taken …RMSE here
Press Walk downhill. Each dot is one pass over all 52 houses.

Push η past about 1.0 and run it again. The path stops walking and starts bouncing between the walls of the ditch, and the error goes up instead of down. That single slider is the most common reason a hand-written model "does not work", and it is why every library ships with a cautious default.

CuriousWhere do the update rules actually come from?

If you have seen derivatives, this is one line of work. The error J is a function of w and β, so the partial derivative of J with respect to w is the slope of the ground in the w direction, and the same for β. Differentiate the squared error and you get:

J(w, β) = (1/n) Σ (yᵢ − (β + w·xᵢ))²
∂J/∂w = −(2/n) Σ xᵢ (yᵢ − ŷᵢ) // slope of the ground, w direction
∂J/∂β = −(2/n) Σ (yᵢ − ŷᵢ) // slope of the ground, β direction

w ← w − η · ∂J/∂w // step downhill, not up: hence the minus
β ← β − η · ∂J/∂β

Read the two derivatives out loud and they stop being symbols. Both are built from the same misses (yᵢ − ŷᵢ). The one for β is just their average, because moving the initial value shifts every prediction by the same amount. The one for w weights each miss by that house's size, because tilting the line moves a 200 m² house four times as far as a 50 m² house. And the minus sign in the update is the whole trick: the derivative points uphill, and you want to go down.

The squared error is chosen partly for the reason in the previous box, and partly because this is what its derivative looks like: clean, one line, no special cases. The absolute error has a corner at zero where it has no derivative at all, which is why fitting it needs a different and slower method.

2d The full process, start to finish

2 repeat (fit, update) … 5 until a certain difference threshold is met
price = … + … × size
…RMSE now …improvement this step

Drag the slider and watch three things move together: the line on the left, the two numbers in the formula, and the error curve. The improvement per step gets smaller and smaller, and once it drops under the threshold the loop stops. That is line 5 of the pseudocode, and it is the whole reason the algorithm ever finishes.

Press "New random start" a few times. The starting line is different every time, the path is different every time, and the numbers it lands on are the same to within a rounding error. That is worth trusting on this model, and worth being suspicious of on any bigger one.

03

Evaluation: how you know it worked

You have a line and you have an error in euros. That still does not answer the question somebody will actually ask you, which is: is that good? An RMSE of €48,000 sounds terrible for a garage and excellent for a castle. A score on its own means nothing; it only means something next to another score.

3a Better than what? The laziest possible model

So compare it to the laziest model there is: ignore the size completely and guess the average price for every single house. That model is free, it is always available, and if your line cannot beat it then your line has learned nothing. R² is exactly that comparison, written as a fraction: how much of the error the average-guesser makes has your line removed?

R² = 1 − ( Σ(yᵢ − ŷᵢ)² / Σ(yᵢ − ȳ)² ) // your errors ÷ the average-guesser's errors
…MAE …RMSE …R²
…

R² of 0 means "no better than guessing the average". 1 means every point sits exactly on the line. Negative means you have managed to do worse than the average, which happens more often than people admit, usually on the rows the model has never seen.

The second chart is the one professionals look at first. It plots each miss against the house's size, so a good fit looks like a shapeless cloud around zero. Any pattern in it, whether a curve, a fan or a drift, is the model telling you which assumption it has broken. Both patterns you can produce there are module 4.

3b The score that counts is on houses it has never seen

train · the line is fitted on these test · held back
…RMSE on train …RMSE on test …difference

Marking your own homework is the oldest mistake in machine learning. So you hide a slice of the data, usually 20 to 30 percent, fit on the rest, and score on the slice the model has never seen. Shuffle the split a few times and watch the test score wobble by a few thousand euros: with 52 houses, which ones happen to land in the test set matters, and that wobble is itself information about how much you should trust any single number.

For a straight line the two scores stay close, because a line has almost no freedom to memorise anything. Remember how calm this panel is, because in §4b you will make that gap explode on purpose.

04

Failure modes: how a straight line lies, and how to counter each

A line will always give you an answer. It has no way of telling you that the answer is nonsense, and it never refuses. These are the four ways it goes wrong, in the order you are likely to meet them, each with the thing you do about it.

4a The data is not linear, so make a new column

Here is a different question about the same market: how does the price depend on the distance to the city centre? The first kilometre out of the centre costs a fortune, and the difference between 9 and 10 km away is almost nothing. That is a curve, and no straight line can be a curve.

The fix is not a different algorithm. It is a different column. This is called feature creation: you build a new column out of the ones you already have, distance squared in this case, and hand it to the same linear model. The model is still linear in its weights, which is all it ever needed to be; it just now has a bent column to be linear about.

…RMSE …R²
…

Look at the residual chart, not the score. With one column the misses make a clean smile: over-predicting in the middle, under-predicting at both ends. That shape is the model saying "there is structure here I cannot reach". With the squared column added it collapses into a shapeless cloud, which is what "nothing left to explain" looks like.

The catch: you had to know to add that column. Nothing in the algorithm suggests it, and this is one of the places where knowing the subject beats knowing the maths.

4b Too much freedom, so hold it back with λ

If a squared column helps, why not a cubed one, and a ninth power while we are at it? Because a flexible enough curve stops following the pattern and starts following the noise: it bends to pass through individual houses that only sit where they sit by chance. That is variance: the model changes wildly when the data changes slightly, and it looks brilliant on the houses you fitted and embarrassing on the ones you did not.

The counter is regularization: add a penalty for large weights to the thing you are minimising, controlled by a number called λ (lambda). Now the model has to buy every bend with error it saves elsewhere. λ at zero is no penalty at all. λ too high and you have flattened the model into a horizontal line that ignores the data. Somewhere in between is the point where the test score is best, and that point is found by trying, not by thinking.

minimise  Σ (yᵢ − ŷᵢ)²  +  λ · Σ wⱼ² // ridge: the penalty is the squared weights
…RMSE on train …RMSE on test
…
the 12 houses it was fitted on held-out houses

Start at λ = 0 and compare the two scores. The train error is beautiful and the test error is five times worse, and on the chart the filled houses sit almost on the curve while the hollow ones do not. Slide λ up and watch the trade: the train error gets steadily worse, and once the penalty starts to bite the test error falls fast, bottoming out around the middle of the slider with the two scores close together. They never cross: a model is always at least as good on the houses it was fitted to. Push it to the end and both rise together.

This penalty is ridge. Lasso is the same idea with |w| instead of w², which has the useful side effect of pushing useless weights to exactly zero, so it also picks your columns for you. Both are one argument in every library, and both are what this chapter left out of the simple version.

4c One strange house pulls the whole line

You already broke this one yourself in §2b. A single extreme point drags a squared-error line towards it, because squaring makes that one house shout louder than twenty ordinary ones. Everything about the fit is contaminated: the slope you quote in the meeting, the price you predict for every other house, and the R² you are proud of.

The counter, in order. First, look at the point and find out what it is: a data-entry mistake, a different kind of property, or a real house at a real price. Second, if it is a mistake, fix or drop it and say in writing that you did. Third, if it is real but rare, fit with the absolute error or a Huber loss, which behaves like squared error near the middle and like absolute error out at the extremes. What you must not do is delete it because it improves your score; that is not modelling, that is decorating.

4d Data that looks linear, and is not

This is the quiet one, because nothing on your screen looks wrong. Inside the range you measured, the line fits beautifully and every score agrees. The lie only starts when you ask about a size nobody in your data has. The model has never seen a 350 m² house; it does not know that price per square meter flattens out at the top of the market, because nothing in the data it was given says so. It just keeps the slope going forever, confidently.

…the line says …reality …off by
…

Inside the shaded band, where the houses are, the line is excellent. Drag past it and the error grows without anything on the chart warning you. The counter is a habit, not a formula: write down the range each column was fitted on, refuse to predict outside it, and be suspicious of any model whose training data does not contain examples of the thing you are asking about.

05

Prompting AI: making an assistant build it properly

An assistant will write you a working linear regression from one lazy sentence. The code will run, and it will skip every single thing in modules 3 and 4. Compare the vague and the strong version, then build your own and watch which traps each line closes.

"Fit a linear regression on my house price data in Python."

What you typically get back

Six lines that fit on everything, print an R² of 0.88, and stop. No split, so that R² is marking its own homework. No residual plot, so a curve in the data would go unnoticed. No look at the extremes, so one wrecked house can be steering the slope. And a coefficient reported to four decimal places, which reads as precision and is nothing of the kind.

no train/test splitno residual plotno outlier checkno range recordedR² quoted aloneno baseline to beat
06

Beyond AI: choosing the tool, owning the call

Two things survive even a perfect prompt. The first is which model to reach for, which depends on things about your data that you have to notice. The second is the set of judgment calls, which have no score attached at all, and for regression the first of those is the biggest one in the whole field.

If your problem looks like thisReach forBecauseThe price you pay
A roughly straight relationship, few columns, and somebody will ask you to explain the model Linear regressionthis chapter Fast, needs little data, and the slope is a sentence a human can act on. Straight only. Sensitive to outliers and to extrapolation, and it says nothing about cause.
A clearly curved but smooth relationship Polynomial featuresor splines Same model, bent columns. Keeps the interpretation roughly intact. Easy to overfit, and the tails go wild fast. Needs the λ from §4b.
Many columns, some of them useless, and you want the model to choose Ridge / Lassochapter planned The penalty shrinks weak weights, and lasso pushes them to exactly zero, which is column selection for free. One more setting to tune, and coefficients are no longer unbiased estimates.
Steps and thresholds, or columns that only matter in combination Decision treeor gradient boosting Finds interactions and jumps by itself, and needs no scaling at all. No smooth trend, no simple sentence to quote, and it will not extrapolate at all.
You are predicting a label, not a number Logistic regressionnext chapter Same machinery, different last step: it reports a probability instead of a value. Different scores entirely: accuracy lies, so precision and recall move in.

6b The judgment calls no prompt makes for you

The big one

Correlation might exist, causation maybe not

Your model says a square meter is worth €2,670. It does not say that adding a square meter to your house creates €2,670. Big houses also sit in different streets, with different gardens and different neighbours, and the line has quietly bundled all of that into one number. The moment somebody uses your slope to decide what to do rather than what to expect, you have to say this out loud.

Judgment call

Which columns you feed it

Add postcode and the model gets better and starts pricing neighbourhoods, which in most cities means it starts pricing who lives there. A column can carry history that nobody typed into it, and the algorithm cannot tell the difference between a fair predictor and a proxy.

Data reality

What an error costs, in real life

RMSE treats €40,000 too high and €40,000 too low as the same mistake. For a seller they are not the same at all. If being wrong in one direction is worse than the other, the score you optimised is not the score you care about, and no library will notice.

Responsibility

What it is used for

The same line that estimates a price can be used to reject a mortgage or to set someone's rent. The maths does not change, but what you owe the person on the other end of the prediction does, and "the model said so" has never been an answer.