Aprender conceptos iniciales de Deep Learning

1

¿Qué es el Deep Learning?

2

¿Qué son las redes neuronales artificiales?

3

¿Por qué el Deep Learning ahora?

4

Pytorch y los diferentes frameworks de Deep Learning

5

Setup en Google Colab

Entender la API de Pytorch

6

¿Qué son los tensores?

7

Tensores y datasets

8

Capas de una red neuronal en Pytorch

9

Crear una red neuronal en Pytorch

10

¿Cómo cargar datos en Pytorch?

11

¿Cómo entrenar una red en Pytorch?

12

Loop de entrenamiento de la red neuronal

Entrenar Redes Neuronales Profundas

13

Ciclo de trabajo para el Deep Learning

14

Espacio de modelos

15

Función de perdida

16

Método de optimización: SGD y Backpropagation

17

Autograd y métodos de optimización

18

¿Cómo evaluar la performance de la red neuronal?

19

Regularización de redes neuronales profundas

20

Implementando la Regularización

21

Optimización de hiperparametros

22

Transfer learning

Construir nuestro propio modelo

23

Presentación del problema

24

Definiendo la red generativa que construiremos: CycleGAN

25

Creando la red generadora convolucional

26

Creando el decoder de la red generadora

27

Construyendo las redes discriminativas

28

Preparando el entrenamiento

29

Instanciando redes, perdidas

30

Instanciando optimizadores y schedulers

31

Calculando las pérdidas

32

Entrenando

33

Cómo visualizar y debugear el entrenamiento

34

Cómo utilizar tu modelo una vez entrenado

35

Cómo utilizar una GPU personal con Google Cloud

Llegar más lejos

36

¿Por qué el Deep Learning es más poderoso que el Machine Learning Tradicional?

37

Para ir más lejos

38

Cierre del curso

Bonus

39

¿Por qué aprender Deep Learning?

Transfer learning

22/39

Lectura

Transfer Learning

Ya hemos visto que muchas técnicas permiten mejorar el aprendizaje de una red profunda en particular las técnicas de regularización.

En lo que sigue veremos otra técnica muy practica, que sin embargo escapa un poco de las técnicas regulares sobre hiperparámetros o capacidad del modelo.

Extracción de Features

Una primera forma de ver el transfer learning es considerar los valores de las neuronas de las capas interiores de la red son features. En particular nos interesamos en la penúltima capa de una red profunda ya entrenada:

  • Estas features al haber sido calculadas por el entrenamiento con gradiente en datasets públicos de gran tamaño como ImageNet contienen mucha información.
  • Vamos a utilizar la red neuronal solo como preprocesamiento para obtener las features de la penúltima capa.
  • La idea inteligente es construir por sobre estas features un clasificador tradicional (por ende no profundo) y entrenar este con nuestro dataset.

Recuerden que dijimos que casi siempre la última capa de una red neuronal profunda es una capa lineal -a.k.a fully connected- así que para realizar nuestro propósito nos bastaría con botar esta capa y añadir un clasificador por encima.

Los clasificadores tradicionales pueden ser: regresión logística, clasificación lineal, SVM, clasificadores basados en árboles, etc.

Las redes profundas pre-entrenadas ya son la mayoría muy complejas, y por lo tanto sus features son muy expresivas. Una solución simple pero eficaz es agregar una capa lineal al final de la red, es decir realizar una clasificación lineal simple por sobre las features.

Veamos esto en código.

  1. Cargo el modelo pre-entrenado
from torchvision import models
vgg = models.vgg16(pretrained=True)
vgg = vgg.to(device)
  1. Deshabilito el gradiente de todos los parametros de la red

Esto se hace porque no queremos seguir cambiando los valores de los parametros. La red ya tiene una buena combinación de valores para calcular features, y el entrenamiento lo realizaremos únicamente en la capa adicional que agregaremos.

for param in vgg.parameters():
  param.requires_grad = False
  1. Extraemos la última capa de la red

VGG fue construida usando nn.Sequential. Esto quiere decir que la “ultima capa” en realidad son muchas capas juntas. Por esto deberemos llamar dos veces el metódo children para acceder a la última capa lineal.

last_sequential_layer = list(vgg.children())[-1]
*list_of_layers, last_layer = list(last_sequential_layer.children())
in_features = last_layer.in_features

Para mantener orden dejo en el mismo atributo classifier todas las últimas capas que iban en nn.Sequential, menos evidentemente la última, más la capa nueva lineal que si quiero entrenar y que por lo tanto le habilito el gradiente.

vgg.fc = nn.Linear(in_features,6)
vgg.fc.requires_grad = True
vgg.classifier = nn.Sequential(*(list_of_layers+[vgg.fc]))

El transfer learning consiste basicamente en inicializar los parametros de una red con buenos valores iniciales, extraidos del entrenamiento de la red sobre un dataset publico.

Existen 4 formas de hacer transfer learning y estas dependen directamente del dominio y el tamano del dataset de imagenes.

  1. Lanzo el entrenamiento

Un pequeño consejo. En general las redes pre-entrenadas fueron entrenadas con datasets que tenían cierta media y desviación estándar. Es recomendable usar esa media y varianza en el pipeline de preprocesamiento.

transform = transforms.Compose(
  [transforms.RandomHorizontalFlip(), #data augmentation
   transforms.ToTensor(),
   transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])    
  ]
)

trainset = SIGNSDataset('/gdrive/My Drive/dl-pytorch/datasets/64x64_SIGNS', split="train", transform = transform)
trainloader = DataLoader(trainset,batch_size=32)

valset = SIGNSDataset('/gdrive/My Drive/dl-pytorch/datasets/64x64_SIGNS', split="val", transform = transform)
valloader = DataLoader(trainset,batch_size=32)

testset = SIGNSDataset('/gdrive/My Drive/dl-pytorch/datasets/64x64_SIGNS', split="test", transform = transform)
testloader = DataLoader(trainset,batch_size=32)

dataloaders = {'train':trainloader,
              'val':valloader,
              'test':testloader}

Ocupamos la función train_and_evaluate que ya construimos y que nos facilita la vida:

loss_fn = nn.NLLLoss()
optimizer = optim.SGD(net.parameters(), lr=1e-3, momentum = 0.9)

train_and_evaluate(vgg, optimizer, loss_fn, dataloaders, device, num_epochs = 100)

Inicialización de parámetros

Una forma más general de ver el Transfer Learning es entenderlo cómo una forma de inicializar los parámetros de manera inteligente (weight initialization).

Existen más formas de inicializar estos parámetros, como una inicialización random, o la Xavier initialization. Sin embargo el transfer learning es por lejos la inicialización más potente ya que los parámetros de una red profunda contienen información muy valiosa. En el paper siguiente podemos entender más de esto y ver que:

  • En una red convolucional los parámetros vistos en su conjunto (parámetros de un mismo canal) pueden ser entendidos como un filtro. Así es cómo los filtros que conoces y transforman el look de una imagen.
  • Los filtros de las primeras capas en una red profunda realizan acciones muy generales: pueden extraer colores, texturas y bordes.
  • Los filtros de las capas más profundas están muy ligados al dominio del cual provienen las fotos y ya son más específico y por lo tanto menos abstractos que los primeros filtros. Por ejemplo en el caso de un dataset de caras, los filtros van a reconocer conceptos ligados a una cara como narices, ojos, orejas, etc. Estos filtros se dice que son específicos al dominio de caras, que claramente sería menos útil para reconocer autos por ejemplo.

La técnica que utilizamos anteriormente (extracción de features) corresponde a un caso particular de Transfer Learning. Este se ocupa por ejemplo cuando el dataset que tienes es pequeño (el nuestro tiene algunos miles de imagenes), o cuando el dominio de tu dataset es muy distinto al que se utilizó para entrenar la red.

En total hay 4 casos a considerar para el Transfer Learning:

Tamaño del dataset Dominio Transferencia
Pequeño Similar Remplazar capa final. Sólo entrenar última capa.
Grande Similar Remplazar capa final. Entrenar toda la red.
Pequeño Diferente Botar múltiples capas finales y poner capa adicional únicamente sobre una capa que tenga features no espécificas al dominio. Sólo entrenar última capa.
Grande Diferente Remplazar capa final. Entrenar toda la red.

Les dejo también este excelente link: Transfer Learning CS231n

Aportes 3

Preguntas 1

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Regístrate o inicia sesión para participar.

Una pregunta:

¿No deberiamos de usar los parametros de la red vgg en la siguiente linea, en lugar de la red que estamos creando net?

optimizer = optim.SGD(net.parameters(), lr=1e-3, momentum = 0.9)

El curso referenciado de Stanford es espectacular. Muy bueno para complementar con este.

excelente