Omkostningsfunktioner og mindste kvadraters metode
Beregn middelkvadratfejl, visualisér omkostningsfladen, og forstå, hvorfor minimering af fejlen giver de bedst passende parametre.
Omkostningsfunktioner og mindste kvadraters metode er en gratis Machine Learning Academy-lektion på CoddyKit. Dette er lektion 2 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Machine Learning Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Machine Learning Academy-kurset indeholder 4 lektioner i alt.
Hvad gør en linje bedst?
Givet et punktdiagram med datapunkter kan uendeligt mange linjer gå gennem eller tæt på dataene. Spørgsmålet er: Hvilken linje er den bedste? Vi har brug for en formel matematisk definition af "bedst", som vi kan optimere algoritmisk.
Svaret er en omkostningsfunktion (også kaldet en tabsfunktion eller målfunktion) — et enkelt tal, der måler, hvor forkerte modellens forudsigelser er på tværs af alle træningseksempler. Den bedste linje er den, der minimerer omkostningsfunktionen. Det omdanner modeltræning til et matematisk optimeringsproblem.
Mean Squared Error: standardomkostningsfunktionen
Den mest almindelige omkostningsfunktion til regression er Mean Squared Error (MSE). For hvert træningseksempel beregner du residualen (faktisk minus forudsagt), opløfter den i anden og beregner derefter gennemsnittet på tværs af alle eksempler:
MSE = (1/n) × Σ(yᵢ - ŷᵢ)²
Opløftning i anden har to vigtige virkninger: Det gør alle fejl positive (så positive og negative fejl ikke ophæver hinanden), og det straffer store fejl mere end små fejl (en residual på 10 bidrager med 100, ikke 10, til omkostningen). Det betyder, at MSE får modellen til at undgå store fejl.
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}')Hvorfor opløfte fejlene i anden?
Du spørger måske, hvorfor man ikke bare beregner gennemsnittet af residualernes absolutte værdier (MAE) i stedet for at opløfte dem i anden. Begge er gyldige omkostningsfunktioner, men MSE har matematiske fordele:
- MSE er differentierbar overalt, hvilket er afgørende for gradientbaseret optimering.
- De kvadrerede fejl gør MSE-overfladen til en glat skål med ét globalt minimum, i modsætning til nogle omkostningsfunktioner med flere lokale minima.
- MSE har en lukket algebraisk løsning, hvilket betyder, at vi kan beregne de optimale parametre direkte uden iterativ søgning.
Mean Absolute Error (MAE) er mere robust over for afvigende værdier og foretrækkes ofte i praksis, men MSE er udgangspunktet for at forstå mindste-kvadraters-regression.
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 MAEOmkostningsoverfladen: visualisering af optimeringen
Forestil dig et 2D-rum, hvor den ene akse er hældningen m, og den anden er skæringen b. For hver kombination af (m, b) kan vi beregne MSE på træningsdataene. Resultatet er en omkostningsoverflade — en skålformet 3D-overflade, hvor bunden af skålen er den optimale (m, b), der minimerer MSE.
For lineær regression med MSE er denne overflade en perfekt konveks paraboloide — den har præcis ét minimum, hvilket garanterer, at optimeringen altid finder de globalt bedste parametre. Det er en vigtig teoretisk fordel sammenlignet med mere komplekse modeller med ikke-konvekse tabsoverflader.
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))Løsningen med mindste kvadrater
Ordinary Least Squares (OLS) er den lukkede matematiske løsning, der finder den hældning og skæring, som minimerer MSE, i én enkelt beregning — uden iteration. For simpel lineær regression (én egenskab) er formlerne:
m = Σ(xᵢ - x̄)(yᵢ - ȳ) / Σ(xᵢ - x̄)²
b = ȳ - m × x̄
Disse formler bruger kun gennemsnit, summer og produkter af træningsdataene. Scikit-learns LinearRegression bruger matrixformen i den generaliserede løsning, som håndterer et vilkårligt antal egenskaber.
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}')Den normale ligning for flere egenskaber
Når du har flere egenskaber, generaliseres OLS til den normale ligning ved hjælp af matrixalgebra:
w = (XᵀX)⁻¹ Xᵀy
Her er X egenskabsmatricen (med en kolonne af ettaller til bias), y er målvektoren, og w er vektoren med optimale vægte. Det er præcis det, scikit-learn beregner internt, når du kalder LinearRegression().fit().
Den normale ligning er hurtig til små datasæt (op til ca. 10.000 egenskaber), men langsom til meget store datasæt, fordi beregningen af den inverse matrix er en O(n³)-operation. Til enorme datasæt foretrækkes gradientnedstigning.
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}')Gradientnedstigning: en alternativ optimeringsmetode
Til meget store datasæt eller modeller med millioner af parametre (f.eks. neurale netværk) er den normale ligning for langsom. Gradientnedstigning er et iterativt alternativ: Start ved et tilfældigt punkt på omkostningsoverfladen, beregn gradienten (omkostningsoverfladens hældning), og tag et lille skridt i nedadgående retning. Gentag, indtil du når bunden.
Læringsraten styrer skridtets størrelse. Hvis den er for stor, overskyder du minimum; hvis den er for lille, sker konvergensen smertefuldt langsomt. Gradientnedstigning er grundlaget for træning af deep learning-modeller og den algoritme, du implicit bruger, hver gang du træner et neuralt netværk.
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-kvadreret: tilpasningsgrad
R² (R-kvadreret), også kaldet determinationskoefficienten, måler, hvor stor en del af variansen i y modellen forklarer. Den går fra 0 til 1 (men kan være negativ for en meget dårlig model):
- R² = 1.0 — perfekte forudsigelser; linjen forklarer al variation.
- R² = 0.0 — modellen er ikke bedre end altid at forudsige gennemsnittet af y.
- R² = 0.8 — modellen forklarer 80 % af variansen i y.
R² er den primære måleenhed til evaluering af regressionsmodeller, fordi den i modsætning til MSE er uafhængig af skala og altid fortolkes som en andel.
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}')Evaluering af omkostningen med scikit-learn
Scikit-learn stiller alle standardmåleenheder til regression til rådighed i sklearn.metrics. Du importerer dem som funktioner, der tager to arrays — faktiske værdier og forudsagte værdier — og returnerer en skalarværdi.
Beregn altid måleenheder på testsættet, ikke træningssættet. Trænings-MSE fortæller dig, hvor godt modellen passer til de data, den blev trænet på, og den er altid lavere end test-MSE. Test-MSE er det ærlige estimat af generaliseringsevnen.
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}')Når MSE ikke er det rigtige tab
MSE er standarden til regression, men er ikke altid det bedste valg:
- Hvis dit mål har afvigende værdier, forstærker MSE deres effekt markant. Brug Huber loss eller MAE for at opnå robusthed.
- Hvis relative fejl betyder mere for dig end absolutte fejl (f.eks. når du forudsiger salg for produkter til både 100 $ og 1.000.000 $), skal du bruge MSLE (Mean Squared Log Error).
- Til tidsserieprognoser er domænespecifikke måleenheder som MAPE (Mean Absolute Percentage Error) ofte lettere at fortolke.
Tabsfunktionen er en designbeslutning, der afspejler, hvilke typer fejl der betyder mest for dit specifikke problem.
Hurtigt tjek
Test din forståelse af begreberne inden for Machine Learning with Python fra denne lektion.
Opsummering af lektionen
I denne lektion lærte du, at MSE måler den samlede forudsigelsesfejl ved at beregne gennemsnittet af kvadrerede residualer på tværs af alle træningseksempler, at OLS-løsningen finder den præcist optimale hældning og skæring i én beregning ved hjælp af den normale ligning, og at R-kvadreret måler, hvilken andel af variansen modellen forklarer, og er uafhængig af skala. Dernæst bruger vi scikit-learns LinearRegression til at træne en virkelig model, undersøge dens koefficienter og evaluere den på et separat testsæt.
Lær Python med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 30
- Lektioner
- 120
Ofte stillede spørgsmål
Er lektionen “Omkostningsfunktioner og mindste kvadraters metode” gratis?
Ja — hele teksten til “Omkostningsfunktioner og mindste kvadraters metode” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Machine Learning Academy-kurset, skal du opgradere til CoddyKit PRO. Machine Learning Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Omkostningsfunktioner og mindste kvadraters metode”?
Beregn middelkvadratfejl, visualisér omkostningsfladen, og forstå, hvorfor minimering af fejlen giver de bedst passende parametre. Du øver dig i Machine Learning Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Machine Learning Academy?
Der kræves ingen tidligere erfaring. Machine Learning Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 2 af 4.
Hvor lang tid tager lektionen “Omkostningsfunktioner og mindste kvadraters metode”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Machine Learning Academy-lektion?
Ja. Alle Machine Learning Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Linjes ligning: Hældning, skæring og forudsigelser
- Omkostningsfunktioner og mindste kvadraters metode
- Træning af lineær regression med scikit-learn
- Multipel lineær regression og feature-vigtighed