Klassisk maskinlæring: kraftfullt og undervurdert

Har du en tabell med tall og et spørsmål om en kategori eller en verdi, er en språkmodell som regel feil verktøy. Det du trenger er eldre, billigere og ofte bedre.

Magnus Gribbestad 8. oktober 2026 7 min
Figur · grensen finner plassen sin (konstruert)
Klassifisering: en grense som justeres Punkter som viser deler med vibrasjon og temperatur. Først uten fasit, så merket som holdt eller sviktet. Modellen trekker en grense, justerer den i flere runder så antall feil synker, og bruker den til å avgjøre om en ny del vil svikte. temperatur ↑ vibrasjon → 8 av 28 feil 4 av 28 feil 2 av 28 feil holdt sviktet gjettet feil ny del Svar: svikter
  1. Du har målinger fra mange deler, men ingen fasit. Hvert punkt er én del: hvor mye den vibrerer, og hvor varm den er.
  2. Nå har du fasit. Sirklene er deler som holdt. Firkantene er deler som sviktet.
  3. Modellen trekker en første grense, nesten på måfå. Gule ringer viser punktene den plasserer feil. Her er grensen en rett linje for å holde figuren enkel. Beslutningstrær og gradient boosting tegner trappetrinn, ikke rette streker.
  4. Den flytter og vrir grensen for å få færre feil. Hver runde justerer den litt. Tallet nederst teller feil på punktene modellen tilpasses, altså treningsdata.
  5. Til slutt finner grensen sin plass. Noen få punkter ligger fortsatt feil, og det er greit. Virkeligheten er sjelden helt ryddig.
  6. Så kommer en ny del. Modellen ser hvilken side av grensen den ligger på, og svarer: svikter.
Kort sagt

Klassisk maskinlæring er modeller som finner mønstre i eksempler og bruker dem til å forutsi en kategori eller et tall. De trenger lite data og lite regnekraft, og de gjør én jobb godt. Hvor den hører hjemme står på maskinlæring-siden.

Har du en tabell med tall og et spørsmål om en kategori eller en verdi, er en språkmodell som regel feil verktøy. Det du trenger er eldre, billigere og ofte bedre.

AI er mer enn språkmodeller

Når folk sier AI nå, mener de nesten alltid språkmodeller. Men mye av AI-en som faktisk kjører i drift, i banker, energiselskaper og industribedrifter, er noe annet. Det er modeller som gjetter om en transaksjon er svindel, hvor mye strøm en bygning bruker i morgen, eller om en maskin trenger service snart. Det kalles klassisk maskinlæring, og den gjorde jobben lenge før ChatGPT.

To oppgaver dekker det meste

OppgaveSvarer medEksempler
KlassifiseringEn kategoriEr denne delen i ferd med å svikte? Er e-posten spam? Lav, middels eller høy risiko?
RegresjonEt tallStrømbehov neste time. Prisen på en bolig. Timer til neste service.

Du gir modellen mange eksempler med riktig svar. Den gjetter, får vite hvor langt unna den var, og justerer seg litt. Etter mange runder treffer den. Trær bygges på en annen måte, ved å velge én deling om gangen, men tanken er den samme: ende opp med færre feil på eksemplene. Det er samme grunnidé som i en språkmodell, men med en mye mindre modell, på mye mindre data og med én bestemt jobb.

Hvorfor enkle modeller ofte vinner

På tabeller har trebaserte modeller, som gradient boosting, lenge slått store nevrale nett. I 2022 sammenlignet Grinsztajn, Oyallon og Varoquaux modellene på 45 datasett og fant at trebaserte modeller fortsatt lå øverst på middels store datasett, selv uten å regne med at de er mye raskere å trene. Siden har feltet beveget seg, som tallet lengst til høyre viser.

45
datasett i sammenligningen. Grinsztajn m.fl., NeurIPS 2022
10 000
eksempler regnes her som middels stort. I 2022 lå trebaserte modeller øverst
2,8 s
brukte TabPFN på å slå sterke metoder som var finjustert i 4 timer. Hollmann m.fl., Nature 2025, datasett opp til 10 000 rader

Det siste tallet viser at historien ikke stopper her. En modell trent på millioner av syntetiske tabeller, TabPFN, slo tidligere metoder på små datasett uten tidkrevende finjustering. Det betyr ikke at du skal bytte i morgen. Det betyr at feltet ikke står stille, og at «enkelt» ikke er det samme som «ferdig utviklet».

Les lisensen før du prøver TabPFN i en bedrift. Koden er Apache 2.0, men modellvektene har egen lisens. README på GitHub (lest 8. oktober 2026) sier at vektene til TabPFN-2.5, 2.6, 3 og 3.5 er ikke-kommersielle, og viser til en egen bedriftslisens for kommersiell bruk. Vektene til TabPFN-2 har Prior Labs-lisensen, som er Apache 2.0 med krav om navngiving. For TabPFN-2.5 og nyere åpnes en nettleser første gang, der du logger inn hos Prior Labs og godtar lisensen. README anbefaler GPU, og sier at CPU er tregt. Installeres med pip install tabpfn. De 2,8 sekundene er tallet fra Nature-artikkelen, og jeg har ikke sjekket hvilken maskinvare som lå bak.

Men også uten nye modeller er det god grunn til å starte enkelt:

Det gjelder tabeller. På bilder, lyd og fri tekst er det motsatt.

Når du bytter verktøy

Du harStart med
Tall og kategorier i en tabellKlassisk maskinlæring: beslutningstrær, gradient boosting (XGBoost, LightGBM), logistisk regresjon
Veldig få raderEn enkel modell eller en regel. Tabellmodeller som TabPFN kan testes, men les lisensen først (se over)
Bilder, lyd eller rå signalerDyplæring, for eksempel nevrale nett for bilder
Fri tekst, åpne spørsmål, dialogSpråkmodell
Krav om å kunne forklare hvorforEn modell du kan lese: logistisk regresjon eller et lite beslutningstre
Både tekst og tallSpråkmodell til å gjøre teksten om til kategorier, klassisk modell til å forutsi

Rekkefølgen er poenget. Start der det enkleste kan virke, og gå videre først når du har sett at det ikke holder.

Hva som skal til, for at det virker

Modellen blir aldri bedre enn dataene. Det er der arbeidet starter, ikke i valget av algoritme.

Regn ut den dumme regelen først

Før du trener noe: regn ut hva en dum regel gir. Holder 98 av 100 deler, og modellen din alltid svarer «holder», har den 98 prosent rett og finner ikke en eneste feil. Slår ikke modellen den dumme regelen på det du faktisk bryr deg om, har du ikke en modell. Sjekk derfor hvor mange av de som sviktet den fant, ikke bare hvor ofte den hadde rett. Og test alltid på data den ikke har sett under treningen.

Elefanten

Et bilde, ikke en fasit

En modell trent på katter og hunder får se en elefant. Den svarer «hund, 71 prosent sikker», for det er det eneste den kan svare. Ingenting i modellen sier fra at dette er noe helt annet enn det den ble trent på. Tallet er konstruert.

Det kalles distribusjonsskift, og det skjer når modellen møter data som er annerledes enn treningsdataene. En maskin får ny driftsform, en sensor blir byttet, eller verden endrer seg. Derfor må modeller i drift følges opp og trenes på nytt. Og husk at modellen finner det som henger sammen med utfallet, ikke det som forårsaker det. Handler du som om det er det samme, kan du gjøre noe dumt med stor selvtillit.

La AI hjelpe deg å velge

Prompt · Trenger jeg maskinlæring?
Jeg har data om [hva dataene handler om]. Hver rad er [én enhet, for eksempel én del eller én kunde], og jeg vil forutsi [hva]. Jeg har omtrent [antall] rader og [antall] kolonner.

Er dette klassifisering, regresjon eller noe annet? Trenger jeg maskinlæring, eller holder en enkel regel? Foreslå en enkel baseline og en modell å starte med, og fortell hva som kan gå galt med akkurat disse dataene.
Be om baseline først. Den forteller deg hva modellen må slå for å være verdt bryet.

Klassisk maskinlæring er ikke utdatert. Det er riktig verktøy for en bestemt jobb, og den jobben er det mange som har. Et eksempel på hvordan det ser ut når mønsteret er «lær det normale», står i Å finne det unormale.

For deg som bygger

«Regn ut den dumme regelen først» som kjørbar kode. Først en liten fil som lager konstruerte data: 2 000 deler, omtrent 3 prosent som sviktet, med vibrasjon og temperatur. Alt er funnet på. Deretter tre regler, bare med standardbiblioteket, som du kan kjøre med én gang. Lagre som deler.py og regel.py i samme mappe.

Python · deler.py
import random

# Konstruerte data: 2 000 deler, omtrent 3 prosent sviktet.
# Kolonnene er vibrasjon (mm/s) og temperatur (°C). Alle tall er funnet på.
def lag_data(n=2000, andel_svikt=0.03, frø=1):
    rng = random.Random(frø)
    rader = []
    for _ in range(n):
        svikt = rng.random() < andel_svikt
        if svikt:
            rader.append(((rng.gauss(3.4, 0.7), rng.gauss(80, 6)), 1))
        else:
            rader.append(((rng.gauss(2.0, 0.5), rng.gauss(68, 5)), 0))
    return rader

# Del i trening og test. Testdelen brukes aldri til å velge regler.
def del_opp(rader, testandel=0.3, frø=1):
    rng = random.Random(frø)
    rader = rader[:]
    rng.shuffle(rader)
    snitt = int(len(rader) * (1 - testandel))
    return rader[:snitt], rader[snitt:]
Python · regel.py
import statistics

from deler import lag_data, del_opp

trening, test = del_opp(lag_data())
holdt = [x for x, y in trening if y == 0]
snitt = [statistics.mean(k) for k in zip(*holdt)]
sd = [statistics.stdev(k) for k in zip(*holdt)]

def dum_regel(x):
    return 0  # alle deler holder

def terskel_regel(x):
    return int(x[0] > 2.8)  # fast grense på vibrasjon

def z_score_regel(x, grense=2.5):
    z = [(v - m) / s for v, m, s in zip(x, snitt, sd)]
    return int(max(z) > grense)  # én variabel langt over det normale holder

def vurder(regel):
    ekte = [y for _, y in test]
    gjett = [regel(x) for x, _ in test]
    rett = sum(g == e for g, e in zip(gjett, ekte)) / len(test)
    funnet = sum(g and e for g, e in zip(gjett, ekte)) / sum(ekte)
    falske = sum(g and not e for g, e in zip(gjett, ekte))
    return rett, funnet, falske

print(f"Test: {len(test)} deler, {sum(y for _, y in test)} sviktet")
for navn, regel in [("dum regel", dum_regel), ("terskel", terskel_regel),
                    ("z-score", z_score_regel)]:
    rett, funnet, falske = vurder(regel)
    print(f"{navn:10} {rett:5.1%} rett | {funnet:5.1%} av svikten funnet | {falske} falske alarmer")
Utskrift
Test: 600 deler, 19 sviktet
dum regel  96.8% rett |  0.0% av svikten funnet | 0 falske alarmer
terskel    94.0% rett | 84.2% av svikten funnet | 33 falske alarmer
z-score    97.8% rett | 84.2% av svikten funnet | 10 falske alarmer

Den dumme regelen har 96,8 prosent rett og finner ingenting. Terskelen og z-scoren finner like mange av svikten (16 av 19), men z-scoren gir 10 falske alarmer mot 33 og får dermed høyest andel rett. Det er et lite testsett: 19 sviktede deler betyr at én sviktet del er 5 prosentpoeng, så ikke les mer ut av forskjellen enn at regelen med færrest falske alarmer er den du vil ha. Z-score-regelen lærer snitt og standardavvik fra delene som holdt, og slår alarm når en av målingene ligger mer enn 2,5 standardavvik over det. Den er en enkel modell i seg selv.

Så den samme øvelsen med scikit-learn: en dum regel mot et beslutningstre, med samme data. Installeres med pip install scikit-learn, og filen leser deler.py fra boksen over.

Python · sk_modell.py
# pip install scikit-learn
from sklearn.dummy import DummyClassifier
from sklearn.metrics import accuracy_score, recall_score
from sklearn.tree import DecisionTreeClassifier

from deler import lag_data, del_opp

trening, test = del_opp(lag_data())
X_tr, y_tr = [x for x, _ in trening], [y for _, y in trening]
X_te, y_te = [x for x, _ in test], [y for _, y in test]

modeller = {
    "dum regel": DummyClassifier(strategy="most_frequent"),
    "beslutningstre": DecisionTreeClassifier(max_depth=3, random_state=0),
}
for navn, modell in modeller.items():
    modell.fit(X_tr, y_tr)
    gjett = modell.predict(X_te)
    falske = sum(g and not e for g, e in zip(gjett, y_te))
    print(f"{navn:15} {accuracy_score(y_te, gjett):5.1%} rett | "
          f"{recall_score(y_te, gjett):5.1%} av svikten funnet | {falske} falske alarmer")
Utskrift · sk_modell.py
dum regel       96.8% rett |  0.0% av svikten funnet | 0 falske alarmer
beslutningstre  98.7% rett | 73.7% av svikten funnet | 3 falske alarmer

Treet har høyest andel rett og færrest falske alarmer, men finner 14 av de 19 sviktede delene, mot 16 for z-score-regelen. Det er lærdommen i tallene: «andel rett» sier lite når nesten alt holder, så se på hva som blir funnet og hva alarmene koster. Setter du class_weight="balanced" på treet, som gjør at feil på de sjeldne sviktene teller tyngre, endrer bildet seg i samme kjøring: 100 prosent av svikten funnet og 15 falske alarmer, og 97,5 prosent rett. Hvilken av dem som er best, avgjøres av hva en sviktet del og en falsk alarm koster hos deg. Alt dette er ett enkelt tre, ett konstruert datasett og 19 sviktede deler i testsettet, så ikke les mer ut av forskjellene enn at de finnes. Vil du prøve på åpne data, finnes AI4I 2020 Predictive Maintenance Dataset hos UCI: 10 000 syntetiske rader, lisens CC BY 4.0, med Machine failure som mål.

Kjørt 8. oktober 2026 med Python 3.13.16 på Windows 11: deler.py og regel.py, og utskriften over er fra den kjøringen. sk_modell.py er kjørt med scikit-learn 1.9.1 på Python 3.13.11 (et eget miljø på maskinen, ingenting ble installert for anledningen), og utskriften over er fra den kjøringen. Varianten med class_weight="balanced" er kjørt i samme miljø med samme data, men er ikke vist som egen fil. Datasettet fra UCI er ikke lastet ned eller brukt her.

Oppdatert oktober 2026. Kilder: Grinsztajn, Oyallon og Varoquaux, «Why do tree-based models still outperform deep learning on typical tabular data?», NeurIPS 2022 (Datasets and Benchmarks). Hollmann m.fl., «Accurate predictions on small data with a tabular foundation model», Nature 637, 2025. Jeg har lest sammendragene og ikke alle resultattabellene, og 2,8 sekunder gjelder klassifisering på datasett opp til 10 000 rader. Punktene om kostnad og datamengde er erfaringsregler og ikke målt her. Punktene i figuren er konstruert. Lisensopplysningene om TabPFN er fra README på GitHub, lest 8. oktober 2026, og kan endre seg per modellversjon.