Els dos models anteriors comparteixen una limitació de fons: la seva frontera de decisió és un hiperplà — un tall recte a l'espai de features. Però el churn de MercaFresh no sempre es deixa tallar en línia recta: un client abandona si fa molt que no compra i a més la seva tendència es desploma, o si és de pla bàsic i la seva despesa cau, i aquestes regles amb "i" i "o" dibuixen fronteres esglaonades. Els arbres de decisió ataquen el problema com ho faria un analista humà: encadenant preguntes. En aquesta lliçó veuràs com un algorisme decideix què preguntar i en quin ordre (impuresa de Gini i entropia, amb els comptes fets a mà), entrenaràs i dibuixaràs un arbre sobre el churn de MercaFresh, i entendràs per què aquest model tan interpretable és també un memoritzador compulsiu si no se li posa fre.
Contingut
- La intuïció: classificar preguntant
- Com es tria cada divisió: impuresa de Gini
- Entropia i guany d'informació
- Arbres de regressió (breu)
- Implementació amb scikit-learn: churn de MercaFresh
- Interpretabilitat: regles llegibles i feature importance
- Hiperparàmetres clau i la tendència al sobreajustament
- Avantatges i limitacions
La intuïció: classificar preguntant
Un arbre de decisió és una cascada de preguntes binàries sobre les features. Cada client entra per l'arrel, respon preguntes i descendeix fins a una fulla, que emet la predicció:
flowchart TD
A{"recencia_dies <= 45?"} -- "Si" --> B{"tendencia >= 0.8?"}
A -- "No" --> C{"comandes_per_mes <= 1.5?"}
B -- "Si" --> D["Fulla: ES QUEDA<br/>(230 clients, 96% fidels)"]
B -- "No" --> E["Fulla: RISC<br/>(45 clients, 60% churn)"]
C -- "Si" --> F["Fulla: CHURN<br/>(180 clients, 91% churn)"]
C -- "No" --> G{"pla = basic?"}
G -- "Si" --> H["Fulla: CHURN<br/>(90 clients, 74% churn)"]
G -- "No" --> I["Fulla: RISC<br/>(55 clients, 52% churn)"]
Observa tres coses:
- Cada camí arrel→fulla és una regla de negoci llegible: "si el client fa més de 45 dies que no compra i fa ≤1.5 comandes/mes, prediu churn (el 91% dels històrics d'aquesta fulla van abandonar)".
- Les fulles guarden proporcions, no només etiquetes: l'arbre també dona probabilitats (la fracció de churn a la fulla).
- La frontera resultant és esglaonada: cada pregunta talla l'espai amb un pla perpendicular a un eix; la combinació forma regions rectangulars. És un model genuïnament no lineal sense necessitat de transformar features.
La pregunta del milió: donat el dataset, quina pregunta cal posar a l'arrel? recencia <= 45 o despesa <= 20? I per què 45 i no 60? L'algorisme necessita un criteri numèric per comparar preguntes candidates.
Com es tria cada divisió: impuresa de Gini
La idea: una bona pregunta separa els clients en grups tan purs com sigui possible — grups on gairebé tots són churn o gairebé tots són fidels. La impuresa de Gini mesura com de barrejat està un grup:
$$Gini = 1 - \sum_{k} p_k^2$$
on $p_k$ és la proporció de cada classe al grup. Per a dues classes:
| Composició del grup | Càlcul | Gini | Lectura |
|---|---|---|---|
| 100% churn | $1 - 1^2 - 0^2$ | 0.0 | Pur: perfecte |
| 90% / 10% | $1 - 0.81 - 0.01$ | 0.18 | Gairebé pur |
| 50% / 50% | $1 - 0.25 - 0.25$ | 0.50 | Màxima barreja: inútil |
Càlcul a mà complet. Node amb 10 clients de MercaFresh: 4 churn, 6 fidels. Gini inicial: $1 - 0.4^2 - 0.6^2 = 1 - 0.16 - 0.36 = 0.48$. Candidata: recencia_dies <= 60.
| Clients | Churn | Fidels | Gini del grup | |
|---|---|---|---|---|
| recència ≤ 60 (esquerra) | 6 | 1 | 5 | $1 - (1/6)^2 - (5/6)^2 = 0.278$ |
| recència > 60 (dreta) | 4 | 3 | 1 | $1 - (3/4)^2 - (1/4)^2 = 0.375$ |
Gini després de dividir = mitjana ponderada per mida: $\frac{6}{10} \cdot 0.278 + \frac{4}{10} \cdot 0.375 = 0.167 + 0.150 = 0.317$.
La divisió redueix la impuresa de 0.48 a 0.317: un guany de 0.163. L'algorisme repeteix aquest càlcul per a cada feature i cada punt de tall possible, tria la divisió de màxim guany, i recorre sobre cada grup fill fins que els nodes siguin purs o s'arribi a un límit. Aquest procediment voraç (triar sempre el millor localment, sense mirar enrere) s'anomena CART i és el que implementa scikit-learn.
Entropia i guany d'informació
El criteri alternatiu clàssic ve de la teoria de la informació. L'entropia mesura la incertesa d'un grup:
$$H = -\sum_{k} p_k \log_2 p_k$$
Amb el mateix node d'abans (4 churn, 6 fidels): $H = -0.4 \log_2 0.4 - 0.6 \log_2 0.6 = 0.529 + 0.442 = 0.971$ bits — gairebé la incertesa màxima (1 bit, la d'un 50/50). Un grup pur té entropia 0: no hi ha res a endevinar. El guany d'informació d'una divisió és la reducció d'entropia, calculada amb la mateixa mitjana ponderada que vam fer amb Gini.
Gini o entropia? A la pràctica donen arbres gairebé idèntics:
| Criteri | Rang (2 classes) | Cost de càlcul | Ús |
|---|---|---|---|
| Gini | 0 – 0.5 | Menor (sense logaritmes) | Per defecte a sklearn |
| Entropia | 0 – 1 bit | Una mica més gran | criterion="entropy" |
Queda't amb la idea comuna: dividir és comprar puresa, i l'arbre sempre compra allà on el guany és màxim.
Arbres de regressió (breu)
El mateix mecanisme prediu números: per a la despesa mensual de 04-01, cada fulla prediu la mitjana de l'objectiu entre els seus clients, i la "impuresa" a reduir és la variància (el MSE dins del node). La pregunta comandes_per_mes <= 3.2 és bona si separa els clients en dos grups de despeses internament semblants. DecisionTreeRegressor ho implementa amb la mateixa interfície. La predicció resultant és una funció esglaonada — constant dins de cada regió rectangular — cosa que fa aquests arbres mals extrapoladors però bons capturadors de salts i llindars.
Implementació amb scikit-learn: churn de MercaFresh
Reutilitzem el dataset de churn de la lliçó anterior (el df de 04-02). Un detall alliberador que reprèn la taula de 03-05: els arbres comparen cada feature amb si mateixa (recencia <= 45 no canvia si la recència està en dies o escalada), així que no necessiten escalat ni desasimetrització. N'hi ha prou d'imputar nuls i codificar categòriques:
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import OneHotEncoder, OrdinalEncoder
from sklearn.tree import DecisionTreeClassifier, plot_tree, export_text
import matplotlib.pyplot as plt
num_cols = ["edat", "satisfaccio", "recencia_dies", "comandes_per_mes",
"despesa_mitjana_comanda", "ratio_inactivitat", "tendencia"]
# Preprocessador minim per a arbres: sense escalar, sense Yeo-Johnson (03-05)
prep_arbre = ColumnTransformer([
("num", SimpleImputer(strategy="median", add_indicator=True), num_cols),
("cat", OneHotEncoder(sparse_output=False, handle_unknown="ignore"), ["ciutat"]),
("ord", OrdinalEncoder(categories=[["basic", "estandard", "premium"]]), ["pla"]),
])
X_entrenament, X_prova, y_entrenament, y_prova = train_test_split(
X, y, test_size=0.2, stratify=y, random_state=42)
arbre = Pipeline([
("prep", prep_arbre),
("model", DecisionTreeClassifier(max_depth=3, min_samples_leaf=20,
random_state=42)),
])
arbre.fit(X_entrenament, y_entrenament)
print(f"Accuracy en prova: {arbre.score(X_prova, y_prova):.2%}")
# Dibuixar l'arbre entrenat
noms = arbre.named_steps["prep"].get_feature_names_out()
plt.figure(figsize=(16, 8))
plot_tree(arbre.named_steps["model"], feature_names=noms,
class_names=["fidel", "churn"], filled=True, rounded=True)
plt.show()Lectura del codi:
max_depth=3: com a molt 3 preguntes encadenades — un arbre que cap en una diapositiva. De seguida veurem per què limitar la profunditat no és opcional.min_samples_leaf=20: cap fulla no pot quedar-se amb menys de 20 clients; evita regles basades en anècdotes.plot_treepinta cada node amb la seva pregunta, el seu Gini, quantes mostres conté i el seu repartiment de classes — la teoria dels apartats 2 i 3, dibuixada. Colors més intensos = nodes més purs.random_state=42: els empats entre divisions igual de bones es trenquen a l'atzar; fixar la llavor fa l'arbre reproduïble.
Interpretabilitat: regles llegibles i feature importance
Dues sortides de l'arbre valen or en una reunió de negoci. La primera, les regles en text pla:
Qualsevol responsable de retenció ho entén sense saber què és un Gini. La segona, la importància de cada feature: quanta reducció total d'impuresa van aportar les divisions que la fan servir:
import pandas as pd
importancies = pd.Series(arbre.named_steps["model"].feature_importances_,
index=noms).sort_values(ascending=False)
print(importancies.head(5).round(3))Si recencia_dies i tendencia dominen el rànquing, el model confirma la tesi de negoci de 03-06: el churn s'anuncia amb silenci i refredament. Cautela: les importàncies sumen 1 i es reparteixen entre features correlacionades de manera una mica arbitrària (mateix avís que amb els coeficients de 04-01/04-02), i aquest mètode tendeix a afavorir features amb molts valors diferents.
Hiperparàmetres clau i la tendència al sobreajustament
Aquí hi ha el costat fosc. Sense límits, l'algorisme divideix fins que cada fulla és pura — encara que per aconseguir-ho necessiti una fulla per client. Aquest arbre se sap l'entrenament de memòria: encerta el 100% en entrenament i s'ensorra en prova, perquè les seves darreres divisions no capturen patrons sinó soroll individual. És el fenomen del sobreajustament (overfitting), que diagnosticarem amb rigor a 06-05; els arbres en són l'exemple de manual.
sense_fre = Pipeline([("prep", prep_arbre),
("model", DecisionTreeClassifier(random_state=42))])
sense_fre.fit(X_entrenament, y_entrenament)
print(f"Entrenament: {sense_fre.score(X_entrenament, y_entrenament):.2%}"
f" | Prova: {sense_fre.score(X_prova, y_prova):.2%}")
# Tipic: Entrenament: 100.00% | Prova: forca pitjor que l'arbre podatEls frens (hiperparàmetres de poda prèvia):
| Hiperparàmetre | Què limita | Efecte d'estrènyer-lo |
|---|---|---|
max_depth |
Preguntes encadenades màximes | Arbre més simple i general, risc de quedar-se curt |
min_samples_leaf |
Mida mínima de fulla | Prohibeix regles anecdòtiques |
min_samples_split |
Mida mínima per dividir un node | Similar, actua abans |
ccp_alpha |
Poda posterior per cost-complexitat | Poda branques que aporten poc |
Triar aquests valors sistemàticament és matèria de l'optimització d'hiperparàmetres (07-05). I un avançament que explica mitja indústria del ML: la millor cura del sobreajustament d'un arbre no és podar-lo amb més fúria, sinó fer la mitjana de molts arbres diferents — els ensembles tipus Random Forest (07-02) i el gradient boosting (07-03) neixen exactament d'aquí. En aquest curs, l'arbre individual és la peça; allà en veuràs l'edifici.
Avantatges i limitacions
| Avantatges | Limitacions |
|---|---|
| Interpretable: regles llegibles i dibuixables | Sobreajusta amb facilitat si no es poda |
| No necessita escalat ni transformacions de forma (03-05) | Inestable: petits canvis a les dades poden canviar tot l'arbre |
| Captura no-linealitat i interaccions sense enginyeria prèvia | Fronteres només perpendiculars als eixos (les diagonals li costen esglaons) |
| Maneja features numèriques i ordinals amb naturalitat | Extrapola malament en regressió (predicció esglaonada, plana fora del rang) |
| Ràpid en predicció | Un arbre sol rarament és el model més precís disponible |
Errors Comuns i Consells
- Entrenar sense límits i presumir del 100% en entrenament. Aquest número no mesura aprenentatge sinó memòria. Compara sempre entrenament contra prova; una bretxa gran és l'alarma de sobreajustament (06-05).
- Escalar les features "per si de cas" amb un Pipeline compartit. No trenca res, però destrossa la interpretabilitat: la regla
recencia <= 0.83(en unitats robustes) no l'entén ningú. Per a arbres, deixa les features en les seves unitats naturals. - Prendre l'arbre dibuixat com a veritat estable. Reentrenar amb un 5% més de dades pot reorganitzar branques senceres. Les importàncies solen ser més estables que l'estructura; per a les conclusions de negoci, basa't en elles.
- Llegir
feature_importances_com a causalitat. És reducció d'impuresa, no efecte causal — la mateixa cautela de 02-03 que arrosseguem des dels coeficients. - Consell: comença sempre amb un arbre petit (
max_depth=3) i dibuixa'l. Encara que el model final sigui un altre, aquest dibuix és la millor eina d'exploració i comunicació del projecte: et diu quines features tallen i per on.
Exercicis
Exercici 1. A mà: un node té 8 clients (4 churn, 4 fidels). La divisió A separa en (3 churn, 1 fidel) i (1 churn, 3 fidels); la divisió B separa en (4 churn, 2 fidels) i (0 churn, 2 fidels). Calcula el Gini ponderat després de cada divisió i decideix quina triaria l'algorisme.
Exercici 2. Entrena l'arbre del churn amb max_depth d'1 a 12 i dibuixa l'accuracy en entrenament i en prova davant de la profunditat. Descriu les tres zones de la corba i localitza la profunditat raonable.
Exercici 3. Extreu amb export_text la regla completa del camí que porta a la fulla amb més proporció de churn de l'arbre de max_depth=3, i tradueix-la a una frase que pogués aparèixer en un informe per a l'equip de retenció de MercaFresh.
Solucions
Exercici 1
Gini inicial: $1 - 0.5^2 - 0.5^2 = 0.5$.
- Divisió A: cada fill té Gini $1 - (3/4)^2 - (1/4)^2 = 0.375$. Ponderat: $\frac{4}{8}(0.375) + \frac{4}{8}(0.375) = 0.375$.
- Divisió B: fill esquerre $1 - (4/6)^2 - (2/6)^2 = 0.444$; fill dret $1 - 0 - 1 = 0$ (pur). Ponderat: $\frac{6}{8}(0.444) + \frac{2}{8}(0) = 0.333$.
Guanya B (0.333 < 0.375): encara que deixa un fill força barrejat, fabrica un node completament pur, i al criteri li compensa. Lliçó: l'algorisme valora la puresa ponderada total, no el repartiment equilibrat.
Exercici 2
import matplotlib.pyplot as plt
profunditats = range(1, 13)
acc_entrenament, acc_prova = [], []
for d in profunditats:
m = Pipeline([("prep", prep_arbre),
("model", DecisionTreeClassifier(max_depth=d, random_state=42))])
m.fit(X_entrenament, y_entrenament)
acc_entrenament.append(m.score(X_entrenament, y_entrenament))
acc_prova.append(m.score(X_prova, y_prova))
plt.plot(profunditats, acc_entrenament, marker="o", label="entrenament")
plt.plot(profunditats, acc_prova, marker="s", label="prova")
plt.xlabel("max_depth"); plt.ylabel("accuracy"); plt.legend(); plt.show()Tres zones: (1) profunditats 1-2, totes dues corbes baixes — l'arbre és massa simple per al patró (underfitting); (2) zona intermèdia (típicament 3-5), la prova assoleix el seu màxim; (3) a partir d'aquí l'entrenament continua pujant cap al 100% mentre la prova s'estanca o cau — l'arbre memoritza soroll (overfitting). La profunditat raonable és la del màxim en prova. Aquesta corba en U invertida és el retrat del compromís biaix-variància que formalitzarem a 06-05.
Exercici 3
Localitza la fulla amb class: churn i més puresa i encadena'n les condicions. Amb les dades simulades, un resultat típic: recencia_dies > 52.5 i tendencia <= 0.74 i comandes_per_mes <= 2.1. Traducció d'informe: "El segment de més risc són els clients amb més de 52 dies sense comprar l'activitat recent dels quals és menys de tres quartes parts de l'habitual i que fan dues comandes al mes o menys: històricament, la gran majoria d'aquests clients acaba abandonant. Recomanem prioritzar-los en la campanya de retenció." La regla és accionable precisament perquè les features (03-06) es van dissenyar amb lectura de negoci.
Conclusió
Has afegit el primer model no lineal a la teva caixa d'eines: l'arbre classifica encadenant preguntes, tria cadascuna comprant la màxima puresa (Gini o entropia — ja saps fer el compte a mà), es llegeix com a regles de negoci i ordena les features per importància. També n'has vist el taló d'Aquil·les: sense max_depth i min_samples_leaf, memoritza en lloc d'aprendre — un avançament del sobreajustament (06-05) i la motivació dels ensembles (07-02). I una comoditat nova: és el primer model del curs que no necessita escalat.
L'arbre dibuixa fronteres esglaonades, perpendiculars als eixos. La lliçó següent ataca la geometria des de l'angle oposat: en lloc de trossejar l'espai amb preguntes, buscar directament el millor tall possible — l'hiperplà que separa les classes amb la màxima distància de seguretat — i, quan cap tall recte no basti, projectar les dades a un espai on sí que n'hi hagi. Són les màquines de vectors de suport.
Curs de Machine Learning
Mòdul 1: Introducció al Machine Learning
- Què és el Machine Learning?
- Història i evolució del Machine Learning
- Tipus de Machine Learning
- Aplicacions del Machine Learning
- El flux de treball d'un projecte de Machine Learning
Mòdul 2: Fonaments d'Estadística i Probabilitat
- Conceptes bàsics d'estadística
- Distribucions de probabilitat
- Correlació i covariància
- Inferència estadística
- Teorema de Bayes
Mòdul 3: Preprocessament de Dades
- Neteja de dades
- Gestió de dades mancants
- Transformació de dades
- Codificació de variables categòriques
- Normalització i estandardització
- Enginyeria de característiques
Mòdul 4: Algorismes de Machine Learning Supervisat
- Regressió lineal
- Regressió logística
- Arbres de decisió
- Màquines de suport vectorial (SVM)
- K veïns més propers (K-NN)
- Naive Bayes
- Xarxes neuronals
Mòdul 5: Algorismes de Machine Learning No Supervisat
- Clustering: K-means
- Clustering jeràrquic
- Anàlisi de components principals (PCA)
- Anàlisi d'agrupament DBSCAN
- Visualització de dades amb t-SNE i UMAP
Mòdul 6: Avaluació i Validació de Models
- Divisió de dades: entrenament, validació i prova
- Mètriques d'avaluació
- Validació creuada
- Corba ROC i AUC
- Overfitting i underfitting
Mòdul 7: Tècniques Avançades i Optimització
- Regularització: Ridge, Lasso i Elastic Net
- Ensemble Learning
- Gradient Boosting
- Xarxes neuronals profundes (Deep Learning)
- Optimització d'hiperparàmetres
Mòdul 8: Implementació i Desplegament de Models
- Frameworks i biblioteques populars
- Implementació de models en producció
- Manteniment i monitoratge de models
- Consideracions ètiques i de privadesa
Mòdul 9: Projectes Pràctics
- Projecte 1: Predicció de preus d'habitatges
- Projecte 2: Classificació d'imatges
- Projecte 3: Anàlisi de sentiments a les xarxes socials
- Projecte 4: Detecció de fraus
- Projecte 5: Segmentació de clients
