Vam tancar el mòdul anterior amb una pregunta pendent: "puc fer el meu model encara millor?". La primera resposta d'aquest mòdul és la regularització, la tècnica que doma l'overfitting amb precisió quirúrgica en lloc de a cops de martell. A la lliçó 06-05 vam veure que un model sobreajustat memoritza el soroll de les dades d'entrenament; en els models lineals, aquest sobreajustament té una signatura molt recognoscible: coeficients enormes i de signes oposats que es compensen entre si. La regularització ataca directament aquesta signatura afegint a la funció de cost un càstig per complexitat. En aquesta lliçó entendràs Ridge (L2), Lasso (L1) i Elastic Net, el paper de l'hiperparàmetre alpha, i aplicaràs les tres tècniques a la predicció de la despesa mensual dels clients de MercaFresh.
Contingut
- L'overfitting en models lineals: coeficients desbocats
- La idea central: penalitzar la complexitat
- Ridge (L2): encongir sense anul·lar
- Lasso (L1): selecció automàtica de features
- Elastic Net: el millor de tots dos mons
- L'hiperparàmetre alpha i les trajectòries de coeficients
- Escalar abans de regularitzar
- Regularització a MercaFresh: predicció de la despesa mensual
- La mateixa idea en classificació: el paràmetre C
- Taula comparativa i criteris d'elecció
L'overfitting en models lineals: coeficients desbocats
A 04-01 vam entrenar regressions lineals minimitzant l'error quadràtic mitjà, i ja vam avisar que la regularització estendria aquella idea. Per què cal? Perquè la regressió lineal ordinària (OLS) té un punt feble: les features correlacionades.
Recorda la lliçó 02-03: a MercaFresh, num_comandes_mes i num_productes_mes estan fortament correlacionades (qui fa més comandes compra més productes). Quan dues columnes contenen gairebé la mateixa informació, el model lineal té infinites maneres gairebé equivalents de repartir el pes entre elles:
despesa = 20·num_comandes + 5·num_productesprediu gairebé el mateix quedespesa = 500·num_comandes - 155·num_productes
Totes dues s'ajusten igual de bé al conjunt d'entrenament, però la segona és una bomba de rellotgeria: els seus coeficients gegants amplifiquen qualsevol petita variació de la dada d'entrada, i en dades noves l'error es dispara. És exactament el símptoma d'alta variància que vam diagnosticar a 06-05: el model és hipersensible a la mostra concreta amb què es va entrenar.
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
rng = np.random.default_rng(42)
n = 60
# Dues features gairebe redundants (correlacio ~0.98)
num_comandes = rng.poisson(4, n).astype(float)
num_productes = num_comandes * 5 + rng.normal(0, 1, n)
# La despesa real depen sobretot del nombre de comandes
despesa = 22 * num_comandes + rng.normal(0, 8, n)
X = np.column_stack([num_comandes, num_productes])
ols = LinearRegression().fit(X, despesa)
print(ols.coef_) # p. ex. [17.3, 0.95] - o valors molt mes extrems segons la mostraAmb només 60 clients i features gairebé duplicades, si repeteixes l'experiment canviant la llavor veuràs que els coeficients ballen de manera salvatge entre execucions. Un model els paràmetres del qual depenen tant de l'atzar de la mostra no és de fiar.
La idea central: penalitzar la complexitat
La solució és sorprenentment simple. En lloc de minimitzar només l'error, minimitzem:
$$\text{Cost} = \underbrace{\text{Error d'ajust (MSE)}}{\text{predic bé?}} + \alpha \cdot \underbrace{\text{Penalització(coeficients)}}{\text{soc simple?}}$$
- El primer terme empeny el model a ajustar-se a les dades (el de sempre).
- El segon terme castiga els coeficients grans: com més grans siguin els pesos, més gran serà el cost.
- alpha (α) és l'hiperparàmetre que regula l'equilibri: el "preu" que paga el model per cada unitat de complexitat.
El model ja no es pot permetre coeficients de 500 i -155 "perquè sí": només mantindrà un pes gran si la millora en l'error ho compensa. Això redueix la variància a canvi d'un petit augment del biaix — el compromís que vam formalitzar a 06-05, ara amb un control continu.
Les tres tècniques d'aquesta lliçó es diferencien únicament en com mesuren la mida dels coeficients:
| Tècnica | Penalització | Fórmula del terme |
|---|---|---|
| Ridge | L2 (quadrats) | $\alpha \sum_j w_j^2$ |
| Lasso | L1 (valors absoluts) | $\alpha \sum_j |w_j|$ |
| Elastic Net | Barreja L1 + L2 | $\alpha \left( r \sum_j |w_j| + \frac{1-r}{2} \sum_j w_j^2 \right)$ |
Nota: la penalització no inclou mai el terme independent (intercepte); castigar el nivell base de la predicció no tindria sentit.
Ridge (L2): encongir sense anul·lar
Ridge penalitza la suma de quadrats dels coeficients. Com que elevar al quadrat castiga desproporcionadament els valors grans, Ridge odia els coeficients extrems i prefereix repartir el pes de manera equilibrada entre features correlacionades.
Propietats clau:
- Encongeix tots els coeficients cap a zero, però no els fa mai exactament zero: reduir un pes petit aporta cada vegada menys estalvi quadràtic, així que mai no compensa anul·lar-lo del tot.
- És l'opció més estable quan hi ha multicolinealitat: en l'exemple anterior, Ridge repartiria el pes entre
num_comandesinum_productesde manera robusta. - Té solució analítica tancada, per la qual cosa és ràpid i numèricament estable.
from sklearn.linear_model import Ridge
ridge = Ridge(alpha=1.0).fit(X, despesa)
print(ridge.coef_) # coeficients moderats i estables entre execucionsLasso (L1): selecció automàtica de features
Lasso penalitza la suma de valors absoluts. La diferència geomètrica sembla menor, però té una conseqüència enorme: amb L1, reduir un coeficient de 0.1 a 0 estalvia exactament el mateix que reduir-lo de 5.1 a 5. Per això a Lasso sí que li compensa posar coeficients exactament a zero quan una feature aporta poc.
El resultat és que Lasso fa selecció automàtica de features: el model final usa només un subconjunt de columnes, i la resta queden literalment eliminades (coeficient = 0). Això connecta directament amb l'enginyeria de característiques de 03-06: allà vam crear features a mà (RFM, ràtios, agregats) sense saber quines serien útils; Lasso ens dona un mecanisme basat en dades per descartar les que no aporten.
from sklearn.linear_model import Lasso
lasso = Lasso(alpha=1.0).fit(X, despesa)
print(lasso.coef_) # p. ex. [21.8, 0.0] - num_productes eliminada!Matís important: quan dues features estan molt correlacionades, Lasso tendeix a quedar-se'n una i anul·lar l'altra, i quina tria pot dependre de l'atzar de la mostra. Ridge, en canvi, reparteix el pes entre totes dues. Cap estratègia no és "la bona" en abstracte: depèn de si vols un model compacte (Lasso) o estable (Ridge).
Elastic Net: el millor de tots dos mons
Elastic Net combina totes dues penalitzacions amb un segon hiperparàmetre, l1_ratio (r en la fórmula anterior):
l1_ratio=1→ Lasso pur.l1_ratio=0→ Ridge pur.- Valors intermedis → continua anul·lant features irrellevants (herència L1) però tracta les features correlacionades en grup en lloc de triar-ne una arbitràriament (herència L2).
from sklearn.linear_model import ElasticNet
enet = ElasticNet(alpha=1.0, l1_ratio=0.5).fit(X, despesa)
print(enet.coef_)És l'opció recomanable quan tens moltes features, sospites que en sobren algunes i a més hi ha grups correlacionats — una situació molt habitual després d'una sessió generosa d'enginyeria de característiques.
L'hiperparàmetre alpha i les trajectòries de coeficients
alpha controla la intensitat del càstig:
- alpha = 0: sense penalització → regressió lineal ordinària (amb tots els seus problemes).
- alpha petit: penalització suau, coeficients gairebé lliures.
- alpha gran: penalització dura, coeficients cada vegada més petits; a l'extrem, tots tendeixen a zero i el model prediu gairebé la mitjana (underfitting pur, com el
DummyRegressorde 06-02).
La millor manera de visualitzar-ho és el gràfic de trajectòries: com evoluciona cada coeficient en augmentar alpha.
import matplotlib.pyplot as plt
alphas = np.logspace(-2, 3, 100) # de 0.01 a 1000, en escala logaritmica
coefs_ridge, coefs_lasso = [], []
for a in alphas:
coefs_ridge.append(Ridge(alpha=a).fit(X, despesa).coef_)
coefs_lasso.append(Lasso(alpha=a, max_iter=10000).fit(X, despesa).coef_)
fig, axes = plt.subplots(1, 2, figsize=(12, 4), sharey=True)
for ax, coefs, titol in [(axes[0], coefs_ridge, "Ridge"),
(axes[1], coefs_lasso, "Lasso")]:
ax.plot(alphas, coefs)
ax.set_xscale("log")
ax.set_xlabel("alpha (escala log)")
ax.set_title(f"Trajectories de coeficients - {titol}")
ax.axhline(0, color="gray", lw=0.5)
axes[0].set_ylabel("Valor del coeficient")
plt.show()El que veuràs al gràfic:
- A Ridge, les corbes descendeixen suaument cap a zero però no el toquen: s'hi acosten asimptòticament.
- A Lasso, les corbes xoquen contra zero i s'hi queden: a partir d'un cert alpha, cada feature "mor" i el model es va simplificant per etapes.
I com es tria el millor alpha? Es prova una graella de valors amb validació creuada (06-03). En aquesta lliçó ho farem amb un bucle manual; la cerca sistemàtica i automatitzada (GridSearchCV i companyia) és el tema de la lliçó 07-05.
Escalar abans de regularitzar
Punt crític que reprèn la lliçó 03-05: la regularització castiga la mida numèrica dels coeficients, i aquesta mida depèn de l'escala de cada feature.
Si despesa_total es mesura en euros (valors de milers) i frequencia en comandes/mes (valors d'unitats), la primera necessitarà un coeficient diminut i la segona un de gran per al mateix efecte real. La penalització castigaria injustament frequencia només per la seva escala. Conclusió:
Estandarditza sempre les features (StandardScaler) abans de Ridge, Lasso o Elastic Net. I, com vam aprendre al mòdul 3, dins d'un
Pipelineperquè l'escalat s'ajusti només amb l'entrenament i no hi hagi fuites (06-01).
Regularització a MercaFresh: predicció de la despesa mensual
Apliquem-ho tot al problema de regressió de MercaFresh: predir la despesa mensual d'un client a partir de features de comportament, diverses de les quals correlacionades entre si (com vam descobrir a la matriu de correlació de 02-03).
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression, Ridge, Lasso, ElasticNet
# --- Dataset sintetic de MercaFresh (features de comportament) ---
rng = np.random.default_rng(7)
n = 300
frequencia = rng.gamma(3, 1.5, n) # comandes/mes
productes = frequencia * 6 + rng.normal(0, 2, n) # correlacionada amb frequencia
antiguitat = rng.uniform(1, 60, n) # mesos com a client
tiquet_mitja = rng.normal(35, 8, n) # EUR per comanda
visites_web = frequencia * 4 + rng.normal(0, 3, n) # correlacionada amb frequencia
soroll_1 = rng.normal(0, 1, n) # features irrellevants
soroll_2 = rng.normal(0, 1, n)
# Despesa real: depen de la frequencia i el tiquet; la resta es redundant o soroll
despesa_mensual = frequencia * tiquet_mitja + rng.normal(0, 15, n)
X = pd.DataFrame({
"frequencia": frequencia, "productes": productes,
"antiguitat": antiguitat, "tiquet_mitja": tiquet_mitja,
"visites_web": visites_web, "soroll_1": soroll_1, "soroll_2": soroll_2,
})
y = despesa_mensual
X_entrenament, X_prova, y_entrenament, y_prova = train_test_split(
X, y, test_size=0.2, random_state=42)
# --- Torneig: OLS vs Ridge vs Lasso vs Elastic Net, sempre amb escalat ---
models = {
"OLS": LinearRegression(),
"Ridge": Ridge(alpha=10),
"Lasso": Lasso(alpha=1.0, max_iter=10000),
"Elastic Net": ElasticNet(alpha=1.0, l1_ratio=0.5, max_iter=10000),
}
for nom, model in models.items():
pipe = Pipeline([("scaler", StandardScaler()), ("reg", model)])
# RMSE per validacio creuada de 5 folds, com a 06-03
rmse = -cross_val_score(pipe, X_entrenament, y_entrenament, cv=5,
scoring="neg_root_mean_squared_error").mean()
pipe.fit(X_entrenament, y_entrenament)
coefs = pipe.named_steps["reg"].coef_.round(1)
print(f"{nom:12s} RMSE-CV: {rmse:6.2f} EUR coefs: {coefs}")Un resultat típic d'aquest experiment:
- OLS reparteix pes entre
frequencia,productesivisites_web(redundants) i fins i tot assigna alguna cosa a les features de soroll. - Ridge redueix tots els pesos i estabilitza el repartiment entre les correlacionades; sol millorar lleugerament el RMSE de validació.
- Lasso anul·la
soroll_1,soroll_2i sovint alguna de les redundants: el model resultant és més curt i més llegible per a l'equip de negoci de MercaFresh ("la despesa l'expliquen la freqüència i el tiquet mitjà"). - Elastic Net queda entre tots dos: elimina el soroll però conserva part del grup correlacionat.
Fixa't que la comparació es fa amb validació creuada sobre l'entrenament, reservant la prova per al veredicte final — la disciplina del mòdul 6 no s'abandona per usar tècniques més avançades.
La mateixa idea en classificació: el paràmetre C
La regularització no és exclusiva de la regressió. De fet, ja l'has estat usant sense saber-ho:
- A 04-02 vam veure que
LogisticRegressionde sklearn té un paràmetreC. Doncs bé:LogisticRegressionve regularitzada amb L2 per defecte, iCés exactament l'invers d'alpha:C = 1/α. - A 04-04, el paràmetre
Cde les SVM complia el mateix paper: controlar l'equilibri entre ajustar bé l'entrenament i mantenir un model simple (marge ampli).
| Paràmetre | Valor petit | Valor gran |
|---|---|---|
alpha (Ridge/Lasso/EN) |
Poca regularització → risc d'overfitting | Molta regularització → risc d'underfitting |
C (LogisticRegression/SVM) |
Molta regularització → underfitting | Poca regularització → overfitting |
Compte amb la inversió: apujar alpha i apujar C tenen efectes oposats. A més, LogisticRegression(penalty="l1", solver="liblinear") et dona un classificador amb selecció de features a l'estil Lasso — útil en el churn de MercaFresh si vols un model que usi poques variables RFM.
from sklearn.linear_model import LogisticRegression
# Churn amb regularitzacio L1: coeficients a zero = features descartades
clf = Pipeline([
("scaler", StandardScaler()),
("logreg", LogisticRegression(penalty="l1", C=0.1, solver="liblinear")),
])Taula comparativa i criteris d'elecció
| Criteri | Ridge (L2) | Lasso (L1) | Elastic Net |
|---|---|---|---|
| Coeficients a zero exacte | No | Sí | Sí |
| Selecció de features | No | Automàtica | Automàtica (per grups) |
| Features molt correlacionades | Reparteix el pes (estable) | En tria una gairebé a l'atzar | Tendeix a conservar el grup |
| Nre. d'hiperparàmetres | 1 (alpha) |
1 (alpha) |
2 (alpha, l1_ratio) |
| Quan usar-la | Moltes features útils i correlacionades; prioritat: estabilitat | Sospites que poques features importen; prioritat: interpretabilitat | Moltes features, algunes d'irrellevants i altres en grups correlacionats |
Regla pràctica: comença amb Ridge com a opció segura; passa a Lasso si necessites un model compacte i explicable; usa Elastic Net quan Lasso es comporti de manera inestable per la correlació entre features.
Errors Comuns i Consells
- Regularitzar sense escalar. L'error número u. Sense
StandardScaler, alpha castiga les features per la seva unitat de mesura, no per la seva rellevància. Usa sempre unPipeline. - Confondre alpha i C. En regressió (Ridge/Lasso), més alpha = més regularització. En classificació (
C), és a l'inrevés. Comprova sempre en quina direcció mous el control. - Interpretar el zero de Lasso com "aquesta variable no influeix en la realitat". Lasso diu que la feature no aporta atès que ja hi són les altres; amb features correlacionades, l'eliminada pot ser tan causal com la supervivent. La inferència causal és una altra disciplina.
- Triar alpha mirant l'error d'entrenament. L'entrenament sempre preferirà alpha = 0. L'alpha es tria amb validació (creuada), mai amb l'error d'entrenament.
- Oblidar
max_itera Lasso/ElasticNet. Usen optimització iterativa (descens per coordenades) i amb alphas petits poden no convergir; si veus warnings, apujamax_iter. - Consell: explora alpha sempre en escala logarítmica (
np.logspace), perquè el seu efecte és multiplicatiu: la diferència rellevant és entre 0.01, 0.1, 1 i 10, no entre 1 i 2.
Exercicis
- Trajectòries sobre MercaFresh. Amb el dataset de despesa mensual d'aquesta lliçó (les 7 features), dibuixa les trajectòries de coeficients de Lasso per a
alphas = np.logspace(-2, 2, 100)(estandarditzant abans). En quin ordre "moren" les features? Coincideix amb el que saps de com es va generar la despesa? - Ridge contra la multicolinealitat. Genera 20 mostres diferents del dataset petit de la secció 1 (canviant la llavor) i ajusta en cadascuna OLS i Ridge amb
alpha=10(amb escalat). Calcula la desviació estàndard del primer coeficient entre les 20 execucions per a cada model. Quin és més estable? - L1 en el churn. Sobre el dataset de churn amb features RFM del mòdul 3, entrena
LogisticRegression(penalty="l1", solver="liblinear")ambCa[0.01, 0.1, 1, 10]dins d'un pipeline amb escalat. Per a cada C, compta quants coeficients queden a zero i calcula l'F1 amb validació creuada estratificada (06-03). Quina C triaries i per què?
Solucions
- Estandarditza amb
StandardScaleri ajusta unLassoper cada alpha, guardantcoef_. En pintar les 7 corbes veuràs quesoroll_1isoroll_2moren gairebé immediatament (alphas petits), després cauen les redundants (visites_web,productes— Lasso conserva normalmentfrequenciadel grup correlacionat) i les últimes supervivents sónfrequenciaitiquet_mitja, exactament les dues variables amb què es va generar la despesa. L'ordre de mort de les trajectòries és en si mateix un rànquing de rellevància. - Estructura: bucle
for llavor in range(20), regenerar dades ambnp.random.default_rng(llavor), ajustar tots dos models sobre features estandarditzades i guardarcoef_[0]. Amb OLS la desviació estàndard del coeficient resulta diverses vegades més gran que amb Ridge (amb dades tan correlacionades pot ser un ordre de magnitud). Conclusió: Ridge no només millora la predicció; fa que el model sigui reproduïble, que és el que significa reduir variància. - Amb
C=0.01(regularització molt forta) gairebé tots els coeficients queden a zero i l'F1 cau cap al del baselineDummyClassifier(06-02): underfitting. AmbC=10no s'anul·la gairebé res i el resultat s'assembla a la logística sense regularitzar. El punt interessant sol ser aC=0.1–1: F1 comparable al màxim amb 2-4 features RFM eliminades. Triaries la C amb millor F1-CV i, en empat pràctic, la més regularitzada (model més simple). La cerca sistemàtica d'aquest tipus de decisions l'automatitzarem a 07-05.
Conclusió
La regularització converteix el compromís biaix-variància de 06-05 en un control continu: la funció de cost passa a premiar simultàniament l'ajust i la simplicitat, i alpha decideix l'equilibri. Ridge (L2) encongeix coeficients i estabilitza models amb features correlacionades; Lasso (L1) a més posa coeficients a zero exacte, regalant-nos selecció automàtica de features; Elastic Net barreja totes dues. Has vist que la idea no és nova per a tu: el paràmetre C de la regressió logística i de les SVM era regularització disfressada. I has confirmat dues disciplines innegociables: escalar dins d'un Pipeline i triar alpha amb validació creuada, mai amb l'entrenament. Regularitzar millora un model contenint-lo; la lliçó següent explora el camí oposat i complementari: millorar combinant molts models perquè els seus errors es cancel·lin entre si. Benvingut a l'Ensemble Learning.
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
