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)
Aprender conceptos iniciales de Deep Learning
¿Qué es el Deep Learning?
¿Qué son las redes neuronales artificiales?
¿Por qué el Deep Learning ahora?
Pytorch y los diferentes frameworks de Deep Learning
Setup en Google Colab
Entender la API de Pytorch
¿Qué son los tensores?
Tensores y datasets
Capas de una red neuronal en Pytorch
Crear una red neuronal en Pytorch
¿Cómo cargar datos en Pytorch?
¿Cómo entrenar una red en Pytorch?
Loop de entrenamiento de la red neuronal
Entrenar Redes Neuronales Profundas
Ciclo de trabajo para el Deep Learning
Espacio de modelos
Función de perdida
Método de optimización: SGD y Backpropagation
Autograd y métodos de optimización
¿Cómo evaluar la performance de la red neuronal?
Regularización de redes neuronales profundas
Implementando la Regularización
Optimización de hiperparametros
Transfer learning
Construir nuestro propio modelo
Presentación del problema
Definiendo la red generativa que construiremos: CycleGAN
Creando la red generadora convolucional
Creando el decoder de la red generadora
Construyendo las redes discriminativas
Preparando el entrenamiento
Instanciando redes, perdidas
Instanciando optimizadores y schedulers
Calculando las pérdidas
Entrenando
Cómo visualizar y debugear el entrenamiento
Cómo utilizar tu modelo una vez entrenado
Cómo utilizar una GPU personal con Google Cloud
Llegar más lejos
¿Por qué el Deep Learning es más poderoso que el Machine Learning Tradicional?
Para ir más lejos
Cierre del curso
Bonus
¿Por qué aprender Deep 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.
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:
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.
from torchvision import models
vgg = models.vgg16(pretrained=True)
vgg = vgg.to(device)
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
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.
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)
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:
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
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
Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Regístrate o inicia sesión para participar.