A 07-01 vam deixar una xifra sobre la taula — 82-85 % d'exactitud del classificador de categories — i una promesa: batre-la gairebé sense escriure més codi. Aquest projecte final la compleix amb el transfer learning de 05-03: en lloc d'entrenar una CNN des de zero, agafarem MobileNetV2 preentrenada a ImageNet i l'adaptarem al nostre problema en dues fases (extracció de característiques i fine-tuning). En acabar compararàs tots dos enfocaments amb números a la mà, decidiràs quin desplega TecnoMarket i tancaràs el mòdul amb els cinc projectes lliurats.
Contingut
- Enunciat: refer 07-01 i batre'l
- Fase 1: dades — redimensionament i
preprocess_inputcorrecte - Fase 2: el model amb MobileNetV2 congelada
- Fase 3: entrenament en dues fases (extracció → fine-tuning)
- Fase 4: comparació de corbes entre fases
- Fase 5: comparació final honesta contra la CNN de 07-01
- Fase 6: quan surt a compte el transfer learning (la taula 2×2, revisada)
- Fase 7: empaquetament final i decisió de negoci
- Tancament del mòdul: el portfolio de TecnoMarket
Enunciat: refer 07-01 i batre'l
Mateix problema, mateixes dades, mateixa vara de mesurar: CIFAR-10 com a substitut de les categories de producte de TecnoMarket, el mateix conjunt de test congelat de 07-01 i la mateixa partició train/validació. Només canvia l'estratègia: en lloc d'aprendre a veure des de zero amb 45 000 imatges, partim d'una xarxa que ja va aprendre a veure amb 1.4 milions (ImageNet) i li ensenyem únicament les nostres categories. És l'aposta central de 05-03; avui la mesurem contra una alternativa real construïda per nosaltres mateixos — la comparació més honesta possible.
Objectiu quantitatiu: superar clarament el 85 % de 07-01. Resultat típic esperable: 90-93 %.
Fase 1: dades — redimensionament i preprocess_input correcte
MobileNetV2 no accepta 32×32: va ser preentrenada amb imatges grans i la seva cascada de reduccions deixaria mapes buits. Redimensionem a 160×160 (compromís entre fidelitat i cost; 05-03). I el punt que més projectes trenca: cada xarxa preentrenada exigeix el seu propi preprocessament. MobileNetV2 espera píxels en [-1, 1], no el /255 que vam fer servir a 07-01:
import tensorflow as tf
import numpy as np
tf.random.set_seed(42)
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.cifar10.load_data()
x_val, y_val = x_train[45000:], y_train[45000:] # mateixa partició que 07-01
x_train, y_train = x_train[:45000], y_train[:45000]
MIDA = 160
BATCH = 64
AUTOTUNE = tf.data.AUTOTUNE
augment = tf.keras.Sequential([ # mateix augment que 07-01 (05-04)
tf.keras.layers.RandomFlip("horizontal"),
tf.keras.layers.RandomTranslation(0.1, 0.1),
tf.keras.layers.RandomZoom(0.1),
])
def preparar(x, y):
x = tf.image.resize(tf.cast(x, tf.float32), (MIDA, MIDA))
x = tf.keras.applications.mobilenet_v2.preprocess_input(x) # -> [-1, 1]
return x, y
def dataset(x, y, entrenar=False):
ds = tf.data.Dataset.from_tensor_slices((x, y)).map(preparar, AUTOTUNE)
if entrenar:
ds = ds.shuffle(10_000).batch(BATCH).map(
lambda a, b: (augment(a, training=True), b), AUTOTUNE)
else:
ds = ds.batch(BATCH)
return ds.prefetch(AUTOTUNE)
train_ds = dataset(x_train, y_train, entrenar=True)
val_ds = dataset(x_val, y_val)
test_ds = dataset(x_test, y_test)Fer servir el preprocess_input de la mateixa família de model no és opcional: amb el /255 de 07-01, MobileNetV2 rebria entrades fora de la distribució amb què es va preentrenar i rendiria uns quants punts per sota sense donar cap error visible.
Fase 2: el model amb MobileNetV2 congelada
La recepta de 05-03: base preentrenada sense cap (include_top=False), congelada, més un cap nou mínim:
from tensorflow.keras import layers, models
base = tf.keras.applications.MobileNetV2(
input_shape=(MIDA, MIDA, 3),
include_top=False, # sense el cap de les 1000 classes d'ImageNet
weights="imagenet",
)
base.trainable = False # fase 1: congelada del tot
entrades = layers.Input(shape=(MIDA, MIDA, 3))
x = base(entrades, training=False) # training=False: BN en mode inferència (05-03)
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dropout(0.3)(x)
sortides = layers.Dense(10, activation="softmax")(x)
model = models.Model(entrades, sortides, name="tecnomarket_tl")
model.summary()
# Total: ~2.3 M de parametres; entrenables: ~13 000 (nomes el cap)Fixa't en la desproporció: la base aporta ~2.26 M de paràmetres ja apresos; nosaltres només n'entrenem ~13 000. El training=False en la crida a la base és el detall subtil de 05-03: manté les BatchNormalization en mode inferència fins i tot durant el fine-tuning posterior, protegint les estadístiques d'ImageNet.
Fase 3: entrenament en dues fases (extracció → fine-tuning)
Fase d'extracció de característiques — només el cap, lr normal:
model.compile(optimizer=tf.keras.optimizers.Adam(1e-3),
loss="sparse_categorical_crossentropy", metrics=["accuracy"])
callbacks = [
tf.keras.callbacks.EarlyStopping(monitor="val_accuracy", patience=5,
restore_best_weights=True),
tf.keras.callbacks.ModelCheckpoint("models/tl_extraccio.keras",
monitor="val_accuracy", save_best_only=True),
tf.keras.callbacks.TensorBoard(log_dir="logs/tl_fase1"),
]
hist1 = model.fit(train_ds, validation_data=val_ds, epochs=15,
callbacks=callbacks)
# Resultat típic: val_accuracy ~86-88 % en 8-12 èpoquesJa en aquesta fase — entrenant el 0.6 % dels paràmetres — se supera la CNN de 07-01. Les característiques d'ImageNet (vores, textures, formes d'objectes) transfereixen bé a CIFAR-10.
Fase de fine-tuning — descongelar el bloc final, lr baix:
base.trainable = True
for capa in base.layers[:100]: # MobileNetV2 té 154 capes: alliberem ~1/3 final
capa.trainable = False
model.compile(optimizer=tf.keras.optimizers.Adam(1e-5), # lr 100x més baix
loss="sparse_categorical_crossentropy", metrics=["accuracy"])
callbacks[1] = tf.keras.callbacks.ModelCheckpoint("models/tl_finetuning.keras",
monitor="val_accuracy", save_best_only=True)
callbacks[2] = tf.keras.callbacks.TensorBoard(log_dir="logs/tl_fase2")
hist2 = model.fit(train_ds, validation_data=val_ds, epochs=15,
callbacks=callbacks)
# Resultat típic: val_accuracy ~90-93 %Les dues regles d'or de 05-03, aplicades: recompilar després de canviar trainable (si no, el canvi no té efecte) i learning rate molt baix (1e-5): les capes descongelades ja contenen coneixement valuós; un lr alt el destruiria a les primeres iteracions (l'anomenat catastrophic forgetting). Descongelem només el bloc final perquè les capes primerenques (vores, colors) són universals i les tardanes són les que convé especialitzar en les nostres categories.
Fase 4: comparació de corbes entre fases
Concatena tots dos historials i pinta l'exactitud de validació amb una línia vertical en el canvi de fase:
import matplotlib.pyplot as plt
acc = hist1.history["val_accuracy"] + hist2.history["val_accuracy"]
plt.plot(acc, label="val_accuracy")
plt.axvline(len(hist1.history["val_accuracy"]) - 1, ls="--", c="gray",
label="inici fine-tuning")
plt.xlabel("epoca"); plt.legend(); plt.grid(True)Lectura típica de la corba:
- Fase 1: pujada ràpida les primeres èpoques i altiplà en ~87 % — el cap espreme tot el que donen unes característiques genèriques congelades.
- Canvi de fase: un salt visible de 2-4 punts a les primeres èpoques de fine-tuning — les capes finals s'adapten a textures de CIFAR — i un nou altiplà en ~91-92 %.
- Si a la fase 2 l'exactitud cau de cop, el lr era massa alt: és el símptoma clàssic.
Fase 5: comparació final honesta contra la CNN de 07-01
Avalua sobre el mateix test congelat de 07-01 i posa les xifres cara a cara. Valors típics (els teus variaran una mica; fes servir els que obtinguis de veritat):
test_loss, test_acc = model.evaluate(test_ds)
print(f"Exactitud test transfer learning: {test_acc:.3f}")| Criteri | CNN pròpia (07-01) | MobileNetV2 + fine-tuning |
|---|---|---|
| Exactitud en test | ~83 % | ~91 % |
| Paràmetres totals | ~1.2 M | ~2.3 M |
| Paràmetres entrenats | ~1.2 M (tots) | ~13 K + ~0.9 M (fase 2) |
| Èpoques fins al millor model | 40-50 | 10 + 8 |
| Temps d'entrenament (GPU) | ~20 min | ~25-35 min* |
| Mida en disc | ~14 MB | ~28 MB |
| Cost d'inferència | Menor (entrada 32×32) | Major (entrada 160×160) |
* Cada època del transfer learning és més cara (imatges 160×160), però en necessita moltes menys.
Conclusions honestes: +8 punts d'exactitud és una millora enorme (els errors baixen de ~17 % a ~9 %: gairebé la meitat); el preu és un model més gran i una inferència més cara. Repeteix també la matriu de confusió de 07-01: veuràs que les parelles conflictives (gat↔gos) continuen sent les pitjors, però amb la meitat de confusions — amb el llindar de 0.80 de 03-04, la cobertura automàtica típica puja del ~70 % al ~85 %.
Fase 6: quan surt a compte el transfer learning (la taula 2×2, revisada)
Reprenem la taula 2×2 de 05-03 i hi situem aquest projecte:
| Dades semblants a ImageNet | Dades molt diferents | |
|---|---|---|
| Poques dades | Extracció de característiques (només cap) | Fine-tuning profund amb compte, o buscar una altra base |
| Moltes dades | Fine-tuning parcial ← el nostre cas | Considerar entrenar des de zero |
CIFAR-10 cau a «moltes dades (45 K), semblants a ImageNet (objectes naturals)»: la casella del fine-tuning parcial, i els resultats ho confirmen. La CNN des de zero de 07-01 només hauria estat competitiva a la casella inferior dreta — per exemple, imatges mèdiques o espectrogrames amb milions d'exemples. Per a les fotos de producte reals de TecnoMarket (objectes quotidians, desenes de milers de fotos), la recepta d'avui és la correcta gairebé amb tota seguretat.
Fase 7: empaquetament final i decisió de negoci
Decisió: TecnoMarket desplega el model de transfer learning. La millora d'exactitud redueix a la meitat la càrrega de la cua de revisió (03-04), cosa que compensa amb escreix el cost d'inferència més alt. La CNN de 07-01 queda documentada com a baseline al repositori (git, 06-04) — tot model en producció necessita un baseline contra el qual justificar-se.
Empaquetament segons 06-05, amb el preprocessament dins del model:
entrada = tf.keras.layers.Input(shape=(32, 32, 3), dtype=tf.uint8) # imatge crua
x = tf.cast(entrada, tf.float32)
x = tf.keras.layers.Resizing(MIDA, MIDA)(x)
x = tf.keras.applications.mobilenet_v2.preprocess_input(x)
prob = model(x, training=False)
model_servei = tf.keras.Model(entrada, prob)
model_servei.save("models/classificador_categories_v2.keras")Redimensionament i preprocess_input viatgen dins del .keras: l'API de FastAPI de 06-05 rep la imatge crua i no es pot equivocar de preprocessament. Abans de substituir la v1, el protocol de 06-05: validar la v2 sobre el conjunt congelat, comparar contra la v1 amb les mateixes imatges, desplegar amb possibilitat de marxa enrere i recalibrar el llindar de confiança sobre validació.
Tancament del mòdul: el portfolio de TecnoMarket
Amb aquest cinquè projecte, l'equip de TecnoMarket (és a dir, tu) lliura el seu portfolio complet:
| Projecte | Problema de negoci | Tècnica principal | Estat |
|---|---|---|---|
| 07-01 | Alta automàtica d'articles | CNN pròpia + llindar i cua de revisió | Baseline documentat |
| 07-02 | Esborranys de descripcions | LSTM caràcter a caràcter + temperatura | Prototip amb revisió humana |
| 07-03 | Detecció de frau | Autoencoder + error de reconstrucció | En producció amb recalibratge periòdic |
| 07-04 | Creativitats generatives | DCGAN amb bucle GradientTape | Prototip educatiu; producció requereix difusió |
| 07-05 | Alta automàtica, v2 | Transfer learning MobileNetV2 | Desplegat, substitueix 07-01 |
Cinc projectes, quatre modalitats (imatges, text, dades tabulars, generació) i un mètode comú: fases clares, particions honestes, mètriques adequades al problema, humans al circuit i lliurament empaquetat.
Errors Comuns i Consells
- Fer servir
/255en lloc delpreprocess_inputde la família del model: l'error silenciós més comú del transfer learning; costa uns quants punts d'exactitud sense llançar cap excepció. - Oblidar recompilar després de canviar
trainable: Keras fixa quines variables s'entrenen en compilar; sense recompilar, el teu «fine-tuning» continua entrenant només el cap. - Fine-tuning amb el mateix lr de la fase 1: destrueix els pesos preentrenats en poques iteracions i l'exactitud es desploma. Abaixa el lr dos ordres de magnitud.
- Descongelar tota la base amb poques dades: més paràmetres lliures dels que les teves dades poden governar; sobreajust gairebé garantit. Descongela per blocs, del final cap enrere.
- Comparar models amb particions diferents: la comparació de la fase 5 només val perquè el test congelat i la partició train/val són idèntics als de 07-01. Canviar les dades entre comparacions invalida la taula.
Exercicis
- Repeteix el projecte entrenant només la fase d'extracció (sense fine-tuning) i compara la taula de la fase 5 amb tres columnes: CNN pròpia, extracció sola, extracció + fine-tuning. Quant aporta cada esglaó?
- Prova
MIDA = 96en lloc de 160 i mesura exactitud i temps per època. On queda en la comparació cost/benefici? - Descongela només les últimes 20 capes (en lloc de ~54) i, per separat, la base sencera. Compara l'exactitud final i el comportament de les corbes en els tres escenaris de descongelació.
Solucions
- N'hi ha prou de saltar-se la fase 2. Taula típica: CNN pròpia ~83 %, extracció ~87 %, extracció+fine-tuning ~91 %. Lectura: el gruix del salt el dona el preentrenament (característiques d'ImageNet); el fine-tuning hi afegeix el refinament final. Si el pressupost de còmput és mínim, l'extracció sola ja bat el model propi.
- Amb 96×96 el temps per època cau aproximadament a la meitat i l'exactitud típica baixa 1-2 punts (~89-90 %): menys resolució, menys detall per a les capes profundes. És un punt intermedi raonable per iterar ràpid i entrenar la versió final a 160.
- Amb 20 capes el resultat es queda ~1 punt per sota de l'escenari base (menys capacitat d'adaptació); amb la base sencera i lr=1e-5 pot igualar o millorar dècimes, però les corbes són més fràgils (més risc de sobreajust i de caiguda inicial) i l'entrenament és més lent. El terç final és el compromís robust: prou adaptació sense posar en risc les capes universals.
Conclusió
Projecte final lliurat i promesa complerta: el classificador v2 amb MobileNetV2 bat la CNN pròpia de 07-01 per uns 8 punts, amb una comparació honesta de costos i una decisió de desplegament justificada. Més important que la xifra és el criteri que t'emportes: la taula 2×2 per decidir quan transferir, les dues fases amb els seus dos learning rates, i la disciplina de comparar sempre contra un baseline sobre el mateix test congelat. Amb això es tanca el mòdul 7: cinc projectes de cap a cap al portfolio de TecnoMarket, integrant tot el que has après des de la primera xarxa densa de 02-05 fins al desplegament de 06-05. Però un professional no acaba quan el model funciona: el que hem construït — models que classifiquen productes, generen textos i imatges i assenyalen clients com a sospitosos — té conseqüències sobre persones reals. El mòdul 8 aborda exactament això: l'ètica, l'impacte i el futur del Deep Learning que tot practicant ha de dominar.
Curs de Deep Learning
Mòdul 1: Introducció al Deep Learning
- Què és el Deep Learning?
- Història i evolució del Deep Learning
- Aplicacions del Deep Learning
- Conceptes bàsics de xarxes neuronals
- Preparació de l'entorn de treball
Mòdul 2: Fonaments de Xarxes Neuronals
- Perceptró i Perceptró Multicapa
- Funció d'activació
- Propagació cap endavant i cap enrere
- Optimització i funció de pèrdua
- La teva primera xarxa neuronal completa
Mòdul 3: Xarxes Neuronals Convolucionals (CNN)
- Introducció a les CNN
- Capes convolucionals i de pooling
- Arquitectures populars de CNN
- Aplicacions de CNN en reconeixement d'imatges
Mòdul 4: Xarxes Neuronals Recurrents (RNN)
- Introducció a les RNN
- LSTM i GRU
- Aplicacions de RNN en processament del llenguatge natural
- Seqüències i sèries temporals
Mòdul 5: Tècniques Avançades en Deep Learning
- Xarxes Generatives Adversàries (GAN)
- Autoencoders
- Transfer Learning
- Regularització i tècniques de millora
- Mecanismes d'atenció i Transformers
Mòdul 6: Eines i Frameworks
- Introducció a TensorFlow
- Introducció a PyTorch
- Comparació de frameworks
- Entorns de desenvolupament i recursos addicionals
- Desar, carregar i desplegar models
Mòdul 7: Projectes Pràctics
- Classificació d'imatges amb CNN
- Generació de text amb RNN
- Detecció d'anomalies amb Autoencoders
- Creació d'una GAN per a generació d'imatges
- Fine-tuning d'un model preentrenat
