A 02-05 vam construir un detector de frau amb el teorema de Bayes: partíem d'un prior (quina fracció de comandes són fraudulentes), observàvem una evidència i actualitzàvem cap al posterior. Aquella màquina d'actualitzar creences era, sense saber-ho, un classificador a mig construir: li faltava poder combinar diverses evidències alhora sense que els comptes explotessin. Naive Bayes completa la construcció amb una suposició descaradament falsa — que totes les features són independents entre si — que, contra tot pronòstic, produeix un dels classificadors més ràpids, frugals i útils de la pràctica. En aquesta lliçó faràs el viatge complet: del teorema al classificador, un exemple numèric a mà amb comandes de MercaFresh, les tres variants i quan fer servir cadascuna, i la implementació amb scikit-learn.

Contingut

  1. Del teorema de Bayes al classificador
  2. El supòsit "naive" i per què funciona tot i ser fals
  3. Exemple numèric a mà: és fraudulenta aquesta comanda?
  4. Suavitzat de Laplace
  5. Les tres variants: Gaussian, Multinomial, Bernoulli
  6. Implementació amb scikit-learn
  7. Fortaleses i febleses

Del teorema de Bayes al classificador

Recordatori exprés de 02-05, en vocabulari de classificació:

$$P(\text{classe} \mid \text{dades}) = \frac{P(\text{dades} \mid \text{classe}) \cdot P(\text{classe})}{P(\text{dades})}$$

Peça Nom Al detector de frau
$P(\text{classe})$ Prior Fracció històrica de comandes fraudulentes (p. ex. 1%)
$P(\text{dades} \mid \text{classe})$ Versemblança Amb quina freqüència els fraus presenten aquesta evidència
$P(\text{classe} \mid \text{dades})$ Posterior El que volem: probabilitat de frau donat el que hem observat
$P(\text{dades})$ Evidència Normalitzador: igual per a totes les classes

El classificador bayesià és directe: calcula el posterior de cada classe i tria la de posterior màxim. Com que $P(\text{dades})$ és idèntic per a totes les classes, ni tan sols cal calcular-lo — n'hi ha prou de comparar $P(\text{dades} \mid \text{classe}) \cdot P(\text{classe})$.

Fixa't en la diferència de filosofia amb la regressió logística (04-02): aquella aprenia $P(\text{classe} \mid \mathbf{x})$ directament, ajustant pesos; Naive Bayes la construeix per peces — aprèn com es distribueixen les dades dins de cada classe i deixa que el teorema en faci la síntesi. Per això es diu que la logística és un model discriminatiu i Naive Bayes un de generatiu.

El supòsit "naive" i per què funciona tot i ser fals

L'obstacle: amb diverses features, la versemblança és una probabilitat conjunta — $P(x_1, x_2, \dots, x_n \mid \text{classe})$. Estimar-la honestament exigeix haver vist moltes vegades cada combinació de valors, i les combinacions creixen exponencialment: amb 15 features és impossible (és una altra cara de la maledicció de la dimensionalitat de 04-05).

La sortida "ingènua": suposar que, dins de cada classe, les features són independents entre si. Aleshores la conjunta es factoritza en un producte de termes individuals, cadascun trivial d'estimar:

$$P(x_1, \dots, x_n \mid c) \approx P(x_1 \mid c) \cdot P(x_2 \mid c) \cdots P(x_n \mid c)$$

El supòsit és fals gairebé sempre — a MercaFresh, l'import d'una comanda i el seu nombre d'articles estan clarament correlacionats (02-03). Per què funciona, doncs? Dues raons:

  • Classificar només exigeix ordenar bé. No necessitem que el posterior sigui exacte, només que la classe correcta quedi per sobre de les altres. Les violacions d'independència distorsionen les probabilitats (solen tornar-les massa extremes: l'evidència correlacionada es "compta dues vegades"), però sovint distorsionen totes les classes en direccions semblants, i el rànquing sobreviu.
  • Menys paràmetres, menys variància. Estimar n distribucions univariants per classe requereix poques dades i produeix estimacions estables; un model que respectés totes les dependències necessitaria moltíssimes més dades per no al·lucinar. Amb dades escasses, el model esbiaixat-però-estable guanya al fidel-però-tremolós — un avançament del compromís biaix-variància de 06-05.

Conseqüència pràctica: fes servir les etiquetes de Naive Bayes amb confiança, i les seves probabilitats amb pinces (tendeixen al 0.99 o al 0.01 injustificats).

Exemple numèric a mà: és fraudulenta aquesta comanda?

Històric de 1 000 comandes de MercaFresh: 20 de fraudulentes (prior del 2%) i 980 de legítimes. Tres features binàries per comanda, amb les seves freqüències en cada classe:

Feature P(sí | frau) P(sí | legítima)
import_alt (> percentil 95) 0.70 0.10
adreca_nova 0.80 0.15
matinada (2:00–6:00) 0.50 0.05

Arriba una comanda amb import_alt = sí, adreca_nova = sí, matinada = no. Puntuació de cada classe (prior × producte de versemblances, fent servir $P(\text{no}) = 1 - P(\text{sí})$):

  • Frau: $0.02 \times 0.70 \times 0.80 \times (1 - 0.50) = 0.02 \times 0.28 = 0.0056$
  • Legítima: $0.98 \times 0.10 \times 0.15 \times (1 - 0.05) = 0.98 \times 0.01425 = 0.01397$

Guanya legítima (0.01397 > 0.0056). Normalitzant per obtenir el posterior: $P(\text{frau}) = \frac{0.0056}{0.0056 + 0.01397} \approx 0.29$.

Dues lectures valuoses:

  • El prior pesa moltíssim: malgrat dos senyals d'alarma de tres, el 2% de partida manté el frau per sota del 50%. És la mateixa lliçó dels falsos positius de 02-05: amb esdeveniments rars, l'evidència ha de ser aclaparadora. Tot i així, un posterior del 29% davant del 2% basal — la comanda és 14 vegades més sospitosa que la mitjana — justifica de sobres una revisió manual.
  • Cada feature multiplica: l'absència de matinada va afavorir "legítima" (0.95 contra 0.50). A Naive Bayes cap evidència no és neutral: totes empenyen.

Això és tot l'algorisme. Entrenar = comptar freqüències (o mitjanes i variàncies). Predir = multiplicar i comparar. D'aquí la seva velocitat imbatible.

Suavitzat de Laplace

Una fallada mortal del comptatge pur: si a l'històric cap frau no va passar de matinada, aleshores $P(\text{matinada} \mid \text{frau}) = 0$, i aquest zero aniquila el producte sencer — cap comanda de matinada no podria ser classificada mai com a frau, per escandalosos que fossin els seus altres senyals. Un sol forat a les dades vetaria una classe completa.

El suavitzat de Laplace ho evita sumant un petit comptatge fictici $\alpha$ (típicament 1) a cada casella: en lloc de $\frac{\text{casos}}{\text{total}}$, s'estima $\frac{\text{casos} + \alpha}{\text{total} + \alpha \cdot k}$ (amb k valors possibles). Així cap probabilitat estimada no és exactament 0 ni 1 — "no haver-ho vist encara" es tracta com a "molt rar", no com a "impossible". A sklearn és el paràmetre alpha de les variants de comptatge.

Les tres variants: Gaussian, Multinomial, Bernoulli

L'únic que canvia entre variants és com es modela $P(x_i \mid c)$ segons el tipus de feature:

Variant Features que espera Com modela cada feature Cas d'ús típic
GaussianNB Contínues Una normal per classe: mitjana i variància (02-02) Dades tabulars com el churn de MercaFresh
MultinomialNB Comptatges (enters ≥ 0) Freqüències relatives suavitzades Text: vegades que apareix cada paraula
BernoulliNB Binàries (0/1) Probabilitat de "sí" per classe Presència/absència: flags com els de l'exemple a mà

GaussianNB estima, per a cada feature i cada classe, la mitjana i la desviació d'una campana de Gauss — la distribució normal de 02-02 treballant de versemblança — i avalua la densitat del valor observat en cada campana. MultinomialNB és el rei històric de la classificació de text (spam, sentiments): cada document es representa com a comptatge de paraules, i la versemblança de cada paraula en cada classe s'estima amb Laplace; el retrobaràs al projecte d'anàlisi de sentiments (09-03). Si les teves features són mixtes, la via pragmàtica és discretitzar/binaritzar cap a una variant, o dividir i combinar — encara que en tabular mixt solen rendir millor els arbres (04-03).

Implementació amb scikit-learn

GaussianNB sobre el churn de MercaFresh, amb el patró de Pipeline habitual. Matís de preprocessament: Naive Bayes no fa servir distàncies, així que l'escalat li és indiferent (com a l'arbre, 03-05); en canvi la transformació Yeo-Johnson de 03-03 li va especialment bé, perquè acosta cada feature a la normalitat que GaussianNB pressuposa:

from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.naive_bayes import GaussianNB

# 'preprocessador': el ColumnTransformer de 03-06 (la branca Yeo-Johnson
# ajuda aqui de debo; el RobustScaler ni ajuda ni fa nosa)
X_entrenament, X_prova, y_entrenament, y_prova = train_test_split(
    X, y, test_size=0.2, stratify=y, random_state=42)

nb = Pipeline([
    ("prep", preprocessador),
    ("model", GaussianNB()),
])
nb.fit(X_entrenament, y_entrenament)   # entrenar = estimar mitjanes/variancies per classe
print(f"Accuracy en prova: {nb.score(X_prova, y_prova):.2%}")

# El que ha apres: una campana per feature i classe
model = nb.named_steps["model"]
print("Priors apresos:", model.class_prior_.round(3))   # [P(fidel), P(churn)]
print("Mitjana de cada feature a la classe churn:", model.theta_[1].round(2))

# Posterior per prioritzar revisions, com a 02-05
p_churn = nb.predict_proba(X_prova)[:, 1]

Punts de lectura:

  • class_prior_ són els priors estimats de l'entrenament — la proporció de cada classe, el "2%" del nostre exemple a mà.
  • theta_ i var_ guarden la mitjana i la variància de cada feature en cada classe: tot el model cap en dues taules petites. Compara-ho amb K-NN (04-05), que carrega el dataset sencer: són els dos extrems de l'espectre memòria/síntesi.
  • Velocitat: entrenar és una passada de comptatges i moments — Naive Bayes entrena en mil·lisegons allà on la SVM (04-04) triga minuts. Per això és el classificador de referència per a línies base instantànies i per a sistemes amb reentrenament continu.
  • Per a text, el mateix esquelet amb MultinomialNB(alpha=1.0) després d'una vectorització de comptatges — la recepta completa, a 09-03.

Fortaleses i febleses

Fortaleses Febleses
Entrenament i predicció rapidíssims, escalen linealment Probabilitats mal calibrades (massa extremes)
Rendeix decentment amb molt poques dades (pocs paràmetres) El supòsit d'independència penalitza quan les dependències són el senyal
Maneja milers de features amb naturalitat (text) GaussianNB pateix amb features molt allunyades de la normal
Sense hiperparàmetres crítics (només alpha a les variants de comptatge) Rarament és el model més precís en tabular; és la línia base honesta
Incremental: pot aprendre per lots (partial_fit) Les features irrellevants sorolloses empenyen igual que les bones (la selecció de 03-06 ajuda)

Errors Comuns i Consells

  • Prendre predict_proba al peu de la lletra. Un 0.998 de Naive Bayes no significa un 99.8% real: l'evidència correlacionada s'ha comptat diverses vegades. Per decidir etiquetes i ordenar riscos val; per comunicar probabilitats al negoci, no sense calibrar.
  • Fer servir MultinomialNB amb features contínues o negatives. Espera comptatges; amb la sortida del RobustScaler (valors negatius) directament falla. Cada variant amb el seu tipus de feature — la taula de l'apartat 5 és el mapa.
  • Oblidar el suavitzat amb categories rares. Amb alpha=0, una categoria mai vista en una classe veta aquesta classe per sempre. Deixa l'alpha=1 per defecte llevat que hi hagi un motiu fundat.
  • Descartar-lo per "massa simple". En text i en línies base continua sent competitiu, i com a primer model d'un projecte dona en segons la referència que els altres han de batre.
  • Consell: quan GaussianNB rendeixi malament, dibuixa l'histograma per classe de les teves features (02-01). Si hi veus bimodalitats o asimetries brutals, la campana que el model assumeix no s'assembla a la realitat — i la transformació de 03-03 o el binning poden recuperar diversos punts d'accuracy.

Exercicis

Exercici 1. Amb les taules de l'exemple a mà, classifica la comanda (import_alt = no, adreca_nova = sí, matinada = sí) i calcula el seu posterior de frau normalitzat.

Exercici 2. A l'històric, cap comanda fraudulenta no va fer servir pagament_contra_reemborsament (0 de 20). Sense suavitzat, quin posterior de frau tindria una comanda amb contra reemborsament, import alt, adreça nova i matinada? Recalcula $P(\text{contra reemborsament} \mid \text{frau})$ amb Laplace ($\alpha = 1$, feature binària) i explica el canvi qualitatiu.

Exercici 3. Entrena sobre el churn GaussianNB, la regressió logística (04-02) i l'arbre de 04-03, cronometrant el fit de cadascun (time.perf_counter). Compara accuracy i temps, i raona en quin escenari de negoci triaries Naive Bayes tot i no ser el més precís.

Solucions

Exercici 1

  • Frau: $0.02 \times (1-0.70) \times 0.80 \times 0.50 = 0.02 \times 0.12 = 0.0024$
  • Legítima: $0.98 \times (1-0.10) \times 0.15 \times 0.05 = 0.98 \times 0.00675 = 0.006615$

Guanya legítima; posterior de frau $= \frac{0.0024}{0.0024 + 0.006615} \approx 0.27$. Curiós: dos senyals d'alarma (adreça nova i matinada) contra un de tranquil·litzador (import normal) deixen la comanda en zona de sospita moderada — de nou el prior del 2% fent d'àncora, com a 02-05.

Exercici 2

Sense suavitzat, $P(\text{contra reemborsament} \mid \text{frau}) = 0/20 = 0$, i la puntuació de frau és $0.02 \times 0 \times \dots = 0$: posterior de frau exactament 0, per alarmants que siguin les altres tres features. El zero actua de veto absolut. Amb Laplace: $\frac{0 + 1}{20 + 1 \cdot 2} = \frac{1}{22} \approx 0.045$. La puntuació de frau reneix: $0.02 \times 0.045 \times 0.70 \times 0.80 \times 0.50 \approx 2.5 \times 10^{-4}$, comparable ja amb la de legítima (que també incorpora el seu terme de contra reemborsament). El canvi qualitatiu: "mai vist" passa d'impossible a molt improbable, i la decisió torna a dependre del conjunt de l'evidència en lloc d'un sol veto.

Exercici 3

import time
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier

candidats = {
    "GaussianNB": GaussianNB(),
    "LogisticRegression": LogisticRegression(max_iter=1000),
    "DecisionTree(d=4)": DecisionTreeClassifier(max_depth=4, random_state=42),
}
for nom, model in candidats.items():
    pipe = Pipeline([("prep", preprocessador), ("model", model)])
    t0 = time.perf_counter()
    pipe.fit(X_entrenament, y_entrenament)
    t = time.perf_counter() - t0
    print(f"{nom:20s} | fit: {t*1000:6.1f} ms | "
          f"prova: {pipe.score(X_prova, y_prova):.2%}")

Resultat típic: Naive Bayes és el més ràpid amb diferència i queda a prop (una mica per sota) dels altres en accuracy. Escenaris on guanyaria el lloc malgrat això: (1) reentrenament molt freqüent o incremental — p. ex. un filtre que s'actualitza amb cada tanda de comandes fent servir partial_fit; (2) molt poques dades etiquetades — el frau confirmat de MercaFresh pot ser un grapat de casos, i NB és de les poques coses que no sobreajusten aquí; (3) com a línia base instantània que fixa el llistó abans d'invertir en models cars. La precisió no és l'únic eix: cost, latència i frescor del model també decideixen (ho reprendrem a 08-02).

Conclusió

Has tancat el cercle obert a 02-05: el teorema de Bayes, amb el supòsit ingenu d'independència com a cola, es converteix en un classificador complet — priors per comptatge, versemblances per feature (campanes gaussianes, freqüències suavitzades amb Laplace o Bernoullis segons la variant), i el posterior màxim com a decisió. Saps fer els comptes a mà, saps per què el model funciona encara que el seu supòsit sigui mentida, i saps situar-lo: el classificador més ràpid i frugal del mòdul, ideal com a línia base i per a text, amb probabilitats que cal mirar amb escepticisme.

Amb això tens sis algorismes supervisats, cadascun amb una idea-força diferent: ajustar rectes, corbar probabilitats, encadenar preguntes, maximitzar marges, votar entre veïns, multiplicar evidències. La darrera lliçó del mòdul presenta la família que pot aprendre la idea que faci falta: petites unitats de càlcul — cadascuna sospitosament semblant a la regressió logística — connectades en capes que componen funcions arbitràriament complexes. Arriben les xarxes neuronals, i amb elles el tancament i la comparativa final del mòdul.

Curs de Machine Learning

Mòdul 1: Introducció al Machine Learning

Mòdul 2: Fonaments d'Estadística i Probabilitat

Mòdul 3: Preprocessament de Dades

Mòdul 4: Algorismes de Machine Learning Supervisat

Mòdul 5: Algorismes de Machine Learning No Supervisat

Mòdul 6: Avaluació i Validació de Models

Mòdul 7: Tècniques Avançades i Optimització

Mòdul 8: Implementació i Desplegament de Models

Mòdul 9: Projectes Pràctics

Mòdul 10: Recursos Addicionals

© Copyright 2026. Tots els drets reservats