Kostenfuncties en kleinste kwadraten
U berekent de gemiddelde kwadratische fout, visualiseert het kostenoppervlak en begrijpt waarom het minimaliseren van de fout tot de best passende parameters leidt.
Kostenfuncties en kleinste kwadraten is een gratis Machine Learning Academy-les op CoddyKit. Dit is les 2 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Machine Learning Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Machine Learning Academy bevat in totaal 4 lessen.
Wat maakt een lijn 'de beste'?
Gegeven een spreidingsdiagram met gegevenspunten kunnen oneindig veel lijnen door of in de buurt van de gegevens lopen. De vraag is: welke lijn is de beste? We hebben een formele wiskundige definitie van 'beste' nodig die we algoritmisch kunnen optimaliseren.
Het antwoord is een kostenfunctie (ook wel verliesfunctie of doelfunctie genoemd) — één getal dat meet hoe fout de voorspellingen van het model zijn over alle trainingsvoorbeelden. De beste lijn is de lijn die de kostenfunctie minimaliseert. Hiermee wordt het trainen van een model een wiskundig optimalisatieprobleem.
Mean Squared Error: de standaardkostenfunctie
De meest gebruikte kostenfunctie voor regressie is Mean Squared Error (MSE). Voor elk trainingsvoorbeeld bereken je het residu (werkelijk min voorspeld), kwadrateer je dit en neem je vervolgens het gemiddelde over alle voorbeelden:
MSE = (1/n) × Σ(yᵢ - ŷᵢ)²
Kwadrateren heeft twee belangrijke effecten: alle fouten worden positief (zodat positieve en negatieve fouten elkaar niet opheffen) en grote fouten worden zwaarder bestraft dan kleine fouten (een residu van 10 draagt 100 bij aan de kosten, niet 10). Hierdoor probeert MSE grote vergissingen te vermijden.
import numpy as np
y_actual = np.array([250000, 300000, 350000, 200000, 400000])
y_pred = np.array([240000, 320000, 330000, 210000, 380000])
# Compute MSE manually
residuals = y_actual - y_pred
squared_residuals = residuals ** 2
mse = squared_residuals.mean()
print('Residuals:', residuals)
print('Squared residuals:', squared_residuals)
print(f'MSE: {mse:,.0f}')
print(f'RMSE (interpretable): ${np.sqrt(mse):,.0f}')Waarom worden fouten gekwadrateerd?
Je vraagt je misschien af: waarom nemen we niet gewoon het gemiddelde van de absolute waarden van residuen (MAE) in plaats van ze te kwadrateren? Beide zijn geldige kostenfuncties, maar MSE heeft wiskundige voordelen:
- MSE is overal differentieerbaar, wat essentieel is voor optimalisatie op basis van gradiënten.
- De gekwadrateerde fouten maken van het MSE-oppervlak een gladde kom met één globaal minimum, in tegenstelling tot sommige kostenfuncties met meerdere lokale minima.
- MSE heeft een algebraïsche oplossing in gesloten vorm, wat betekent dat we de optimale parameters rechtstreeks kunnen berekenen zonder iteratief zoeken.
Mean Absolute Error (MAE) is robuuster tegen uitschieters en heeft in de praktijk vaak de voorkeur, maar MSE is het uitgangspunt voor het begrijpen van kleinste-kwadratenregressie.
import numpy as np
from sklearn.metrics import mean_squared_error, mean_absolute_error
y_actual = np.array([1.0, 2.0, 3.0, 4.0, 100.0]) # note the outlier
y_pred = np.array([1.1, 2.0, 3.1, 4.0, 4.0]) # miss the outlier
mse = mean_squared_error(y_actual, y_pred)
mae = mean_absolute_error(y_actual, y_pred)
print(f'MSE: {mse:.2f} -> heavily penalises the outlier (100 vs 4)')
print(f'MAE: {mae:.2f} -> less sensitive to the outlier')
# MSE amplifies the big miss much more than MAEHet kostenoppervlak: de optimalisatie visualiseren
Stel je een tweedimensionale ruimte voor waarin de ene as de helling m is en de andere het intercept b. Voor elke combinatie van (m, b) kunnen we de MSE op de trainingsgegevens berekenen. Het resultaat is een kostenoppervlak — een komvormig driedimensionaal oppervlak waarvan de bodem de optimale (m, b) is die MSE minimaliseert.
Voor lineaire regressie met MSE is dit oppervlak een perfecte convexe paraboloïde — het heeft precies één minimum, waardoor optimalisatie altijd de wereldwijd beste parameters vindt. Dit is een belangrijk theoretisch voordeel ten opzichte van complexere modellen met niet-convexe verliesoppervlakken.
import numpy as np
import matplotlib.pyplot as plt
# Simple 1-feature dataset
np.random.seed(42)
x = np.array([1, 2, 3, 4, 5], dtype=float)
y = np.array([2.1, 4.0, 5.9, 8.1, 10.0])
# Compute MSE for a grid of (slope, intercept) values
slopes = np.linspace(0, 4, 50)
intercepts = np.linspace(-3, 3, 50)
MSE = np.zeros((50, 50))
for i, m in enumerate(slopes):
for j, b in enumerate(intercepts):
y_pred = m * x + b
MSE[j, i] = ((y - y_pred) ** 2).mean()
# Minimum MSE occurs at the true parameters (~m=2, b=0)
print('Minimum MSE:', MSE.min().round(3))
print('At grid position:', np.unravel_index(MSE.argmin(), MSE.shape))De oplossing met gewone kleinste kwadraten
Ordinary Least Squares (OLS) is de wiskundige oplossing in gesloten vorm die de helling en het intercept vindt waarvoor MSE in één berekening wordt geminimaliseerd — iteratie is niet nodig. Voor enkelvoudige lineaire regressie (één kenmerk) zijn de formules:
m = Σ(xᵢ - x̄)(yᵢ - ȳ) / Σ(xᵢ - x̄)²
b = ȳ - m × x̄
Deze formules gebruiken alleen gemiddelden, sommen en producten van de trainingsgegevens. De LinearRegression van Scikit-learn gebruikt de algemene matrixvorm van deze oplossing, die elk aantal kenmerken aankan.
import numpy as np
x = np.array([1, 2, 3, 4, 5], dtype=float)
y = np.array([2.1, 4.0, 5.9, 8.1, 10.0])
# OLS closed-form solution
x_mean, y_mean = x.mean(), y.mean()
numerator = ((x - x_mean) * (y - y_mean)).sum()
denominator = ((x - x_mean) ** 2).sum()
m = numerator / denominator
b = y_mean - m * x_mean
print(f'Optimal slope (m): {m:.4f}') # ~2.0
print(f'Optimal intercept (b): {b:.4f}') # ~0.0
print(f'MSE at optimal params: {((y - (m*x+b))**2).mean():.4f}')De normaalvergelijking voor meerdere kenmerken
Wanneer je meerdere kenmerken hebt, wordt OLS met matrixalgebra gegeneraliseerd naar de normaalvergelijking:
w = (XᵀX)⁻¹ Xᵀy
Hier is X de kenmerkmatrix (met een kolom enen voor de bias), y de doelvector en w de vector met optimale gewichten. Dit is precies wat scikit-learn intern berekent wanneer je LinearRegression().fit() aanroept.
De normaalvergelijking is snel voor kleine gegevensverzamelingen (tot ongeveer 10.000 kenmerken), maar langzaam voor zeer grote gegevensverzamelingen, omdat het berekenen van de matrixinverse een O(n³)-bewerking is. Voor enorme gegevensverzamelingen heeft gradient descent de voorkeur.
import numpy as np
# Multiple features: X has columns [1, sqft, bedrooms]
X_raw = np.array([[1000, 3], [1500, 4], [800, 2], [2000, 5]], dtype=float)
X = np.column_stack([np.ones(4), X_raw]) # add bias column
y = np.array([200000, 300000, 160000, 380000], dtype=float)
# Normal Equation: w = (X^T X)^{-1} X^T y
w = np.linalg.inv(X.T @ X) @ X.T @ y
print(f'Bias (intercept): {w[0]:,.0f}')
print(f'Sqft coefficient: {w[1]:.2f}')
print(f'Bedrooms coef: {w[2]:,.0f}')
# Verify: prediction for a 1200 sqft, 3 bed house
pred = w[0] + w[1]*1200 + w[2]*3
print(f'Prediction: ${pred:,.0f}')Gradient descent: een alternatieve optimalisatiemethode
Voor zeer grote gegevensverzamelingen of modellen met miljoenen parameters (zoals neurale netwerken) is de normaalvergelijking te traag. Gradient descent is een iteratief alternatief: begin op een willekeurig punt op het kostenoppervlak, bereken de gradiënt (de helling van het kostenoppervlak) en zet een kleine stap in de neerwaartse richting. Herhaal dit tot je de bodem bereikt.
De leersnelheid bepaalt de stapgrootte. Is deze te groot, dan schiet je voorbij het minimum; is deze te klein, dan verloopt de convergentie tergend langzaam. Gradient descent vormt de basis van het trainen van deep-learningmodellen en is het algoritme dat je impliciet gebruikt wanneer je een neuraal netwerk traint.
import numpy as np
# Gradient descent for linear regression
x = np.array([1, 2, 3, 4, 5], dtype=float)
y = np.array([2.1, 4.0, 5.9, 8.1, 10.0])
m, b = 0.0, 0.0 # start at zero
lr = 0.02 # learning rate
for epoch in range(500):
y_pred = m * x + b
residuals = y_pred - y
# Gradients of MSE w.r.t. m and b
grad_m = (2/len(x)) * (residuals * x).sum()
grad_b = (2/len(x)) * residuals.sum()
m -= lr * grad_m
b -= lr * grad_b
print(f'Learned slope: {m:.4f}') # ~2.0
print(f'Learned intercept: {b:.4f}') # ~0.0R-kwadraat: kwaliteit van de passing
R² (R-kwadraat), ook wel de determinatiecoëfficiënt genoemd, meet welk deel van de variantie in y door het model wordt verklaard. De waarde ligt tussen 0 en 1 (maar kan negatief zijn voor een zeer slecht model):
- R² = 1.0 — perfecte voorspellingen; de lijn verklaart alle variatie.
- R² = 0.0 — het model doet het niet beter dan altijd het gemiddelde van y voorspellen.
- R² = 0.8 — het model verklaart 80% van de variantie in y.
R² is de belangrijkste metriek voor het evalueren van regressiemodellen, omdat deze in tegenstelling tot MSE onafhankelijk is van de schaal en altijd als een proportie wordt geïnterpreteerd.
import numpy as np
from sklearn.metrics import r2_score
y_actual = np.array([200, 250, 300, 350, 400], dtype=float)
y_pred_good = np.array([195, 255, 305, 345, 402], dtype=float) # tight fit
y_pred_bad = np.array([300, 300, 300, 300, 300], dtype=float) # always predict mean
print(f'Good model R2: {r2_score(y_actual, y_pred_good):.3f}') # close to 1.0
print(f'Baseline R2: {r2_score(y_actual, y_pred_bad):.3f}') # close to 0.0
# Manual calculation
ss_res = ((y_actual - y_pred_good)**2).sum()
ss_tot = ((y_actual - y_actual.mean())**2).sum()
print(f'Manual R2: {1 - ss_res/ss_tot:.3f}')Kosten evalueren met scikit-learn
Scikit-learn biedt alle standaardmetrieken voor regressie in sklearn.metrics. Je importeert ze als functies die twee arrays — werkelijke waarden en voorspelde waarden — als invoer nemen en een scalaire score retourneren.
Bereken metrieken altijd op de testset, niet op de trainingsset. De trainings-MSE vertelt je hoe goed het model past bij de gegevens waarop het is getraind, en die is altijd lager dan de test-MSE. De test-MSE is een eerlijke schatting van de prestaties op nieuwe gegevens.
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
import numpy as np
np.random.seed(42)
X = np.random.randn(200, 1)
y = 3 * X.ravel() + 2 + np.random.randn(200) * 0.5
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
model = LinearRegression().fit(X_train, y_train)
y_pred = model.predict(X_test)
print(f'Test MSE: {mean_squared_error(y_test, y_pred):.4f}')
print(f'Test RMSE: {mean_squared_error(y_test, y_pred, squared=False):.4f}')
print(f'Test MAE: {mean_absolute_error(y_test, y_pred):.4f}')
print(f'Test R2: {r2_score(y_test, y_pred):.4f}')Wanneer MSE niet de juiste verliesfunctie is
MSE is de standaard voor regressie, maar niet altijd de beste keuze:
- Als je doelvariabele uitschieters bevat, versterkt MSE hun effect sterk. Gebruik Huber loss of MAE voor robuustheid.
- Als je meer belang hecht aan relatieve fouten dan aan absolute fouten (bijvoorbeeld bij het voorspellen van de verkoop van producten van $100 en $1.000.000), gebruik dan MSLE (Mean Squared Log Error).
- Voor voorspellingen van tijdreeksen zijn domeinspecifieke metrieken zoals MAPE (Mean Absolute Percentage Error) vaak beter te interpreteren.
De verliesfunctie is een ontwerpbeslissing die vastlegt welke soorten fouten het belangrijkst zijn voor jouw specifieke probleem.
Korte controle
Test je begrip van de concepten uit deze les over machinelearning met Python.
Samenvatting van de les
In deze les heb je geleerd: MSE meet de totale voorspellingsfout door de gekwadrateerde residuen over alle trainingsvoorbeelden te middelen, de OLS-oplossing vindt de exacte optimale helling en het intercept in één berekening met de normaalvergelijking en R-kwadraat meet welk deel van de variantie het model verklaart en is onafhankelijk van de schaal. Hierna gebruiken we de LinearRegression van scikit-learn om een echt model te trainen, de coëfficiënten ervan te bekijken en het te evalueren op een afzonderlijke testset.
Leer Python met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 30
- Lessen
- 120
Veelgestelde vragen
Is de les “Kostenfuncties en kleinste kwadraten” gratis?
Ja — de volledige tekst van “Kostenfuncties en kleinste kwadraten” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus Machine Learning Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus Machine Learning Academy bevat in totaal 4 lessen.
Wat leer ik in “Kostenfuncties en kleinste kwadraten”?
U berekent de gemiddelde kwadratische fout, visualiseert het kostenoppervlak en begrijpt waarom het minimaliseren van de fout tot de best passende parameters leidt. Je oefent met Machine Learning Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met Machine Learning Academy te beginnen?
Ervaring vooraf is niet nodig. Machine Learning Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 2 van 4.
Hoe lang duurt de les “Kostenfuncties en kleinste kwadraten”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over Machine Learning Academy?
Ja. Elke les over Machine Learning Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- De vergelijking van een rechte: richtingscoëfficiënt, snijpunt en voorspellingen
- Kostenfuncties en kleinste kwadraten
- Lineaire regressie trainen met scikit-learn
- Meervoudige lineaire regressie en het belang van features