Trabajando un dataset
Clase 13 de 27 • Curso de Introducción a Machine Learning 2019
Contenido del curso
Clase 13 de 27 • Curso de Introducción a Machine Learning 2019
Contenido del curso
Usuario anónimo
Danilo Toro
Usuario anónimo
Christian Mahonry Colorado Bulbarela
David Fernando Parada Brijalba
David Alsina
Usuario anónimo
Usuario anónimo
Gabriel Salvador
Angel Armando Martínez Blanco
Erick Herrera
Pedro Escobar
VICTOR CASTILLO
Usuario anónimo
Usuario anónimo
Danilo Toro
Herman Castillo R
David Alsina
Jaime Ramos
Alexis Herasimiuk
Pedro Escobar
Usuario anónimo
Usuario anónimo
Usuario anónimo
Usuario anónimo
Mario Emiliano Gordon Pico
carlos fallaque
Usuario anónimo
Usuario anónimo
Luis Fernando Pedroza Taborda
Usuario anónimo
Usuario anónimo
Diego Forero
Ramiro José Bamaceda Janne
Massimo Di Berardino
Kevin Henriquez
JESUS ALBERTO CARREÑO MARTINEZ
Comparto el código completo desarrollado en esta sesión de clase.
data_path = 'data/' dataset = datasets.CIFAR10(data_path, train=True, download=True) validation_set = datasets.CIFAR10(data_path, train=False, download=True)
Se descarga uno para entrenar y otro que no es para entrenar pero sí para validar si el entrenamiento fue correcto. Se obtienen y describen todas las clases o clasificaciones del dataset que ha sido descargado y se observa el tamaño del dataset.
classes = ['plane','car','bird','cat','deer','dog','frog','horse','ship','truck'] len(dataset)
Se prueba algún componente del dataset, en este caso al ser imágenes se toma una de 50.000, también su etiqueta, y después se muestra la imagen con su etiqueta y clase. (todo esto para aprender y comprobar que todo está validado). Y se visualiza la imagen seleccionada.
mg, label = dataset[50] img, label, classes[label] plt.imshow(img)
Se transforma la imagen a tensor para su procesamiento posterior, usando para ello el método “transforms.ToTensor()” y se enlaza a una función a la cual se le arroja la imagen seleccionada, el tensor resultante de la transformación de la imagen (img) lo asignamos a img_tensor, en este caso.
tensor_transform = transforms.ToTensor() img_tensor = tensor_transform(img) img, img_tensor, img_tensor.shape
Despues de esto se puede observar el tensor y su forma (cantidad de dimensiones y de filas(x)columnas, en ese orden)
Una vez se entiende como transformar una sola imagen se aplica al todo el dataset, con este fin se vuelve a importar el dataset, agregando esta transformacion “transforms.ToTensor()”) a todo lo que se obtenga, de esta forma se tendrá todo el dataset en forma de tensores.
dataset = datasets.CIFAR10(data_path, train=True, download=True, transform=transforms.ToTensor())
Se puede comprobar que en efecto, los datos importados se encuentran en modo de tensor.
img, label = dataset[50] img
Lo anterior con la intención de obtener la media (mean) y la desviación estándar (std) de todo el dataset para así tener los parámetros necesarios de normalización y posteriormente hacer uso de estos datos para el entrenamiento, haciendo lo que sigue: -> Se indaga en qué rango se encuentran los datos que contienen los tensores, a través de “img.min(), img.max()”, valor máximo y mínimo.
Se debe tener en cuenta que para observar la imagen nuevamente, se hace uso del metodo “plt.imshow(img.permute(1,2,0))”, se hace así porque al transformar cambian columnas de lado y al ingresar esto al “plt.imshow()” sin permutarlo no lo entenderá el método y habrá un error, es decir, no lo entiende porque en lugar de ser [X][Y][Z] -> ([0][1][2]), es [Z][X][Y] -> ([0][1][2]), siendo entonces [Z] la dimensión [0], [X] la [1], y [Y] la [2], con el se ve entonces que recuadra todo permute([X][Y][Z]) = permute(1,2,0).
img.min(), img.max() plt.imshow(img.permute(1, 2, 0))
Ahora sí, continuando el proceso se hace lo siguiente, se apila todos los datos con “torch.stack([y dentro de un for se itera cada imagen convertida a tensor en el dataset], dim = 3 (con dimensión de 3))”, para un manejo más fácil de toda la informacion, y se guardan en “imgs”.
-> Se observa la forma de la pila (stack o apilado), revisando que sea correspondiente con los valores lógicamente esperados.
imgs = torch.stack([img_tensor for img_tensor, _ in dataset], dim=3) imgs.shape
Ahora que ya se tiene los tensores correspondientes a las imagenes cómodamente apilados y trabajables se realiza el calculo de los valores de las medianas y las desviaciones estándar para cada tensor. Primero la media (mean) con “imgs.view(3,-1).mean(dim=1)”, lo que hizo con el “imgs.view(3,-1)” fue reacomodar el arreglo de tensores para que tengan 3 filas y el número necesario de columnas con el “-1”. lo que hizo con el “.mean(dim=1)” es indicar que dimensión del tensor se le hace este calculo. Luego se hace el mismo proceso pero esta vez con el calculo de la desviación estándar “imgs.view(3,-1).std(dim=1)” para obtener el STandarDeviation std.
imgs.view(3, -1).mean(dim=1) imgs.view(3, -1).std(dim=1)
Con los datos de mediana (mean) y deviación estandar (std) ya se hace la transformación normalizada, como son varias las transformaciones que hay que hacer se hace una composición de transformaciones con el método ".Compose()" dentro de este se coloca como parametros la transformación a Tensor y la normalizacion con “.Normalize((mean), (std))”.
transform = transforms.Compose( [transforms.ToTensor(), transforms.Normalize((0.4915, 0.4823, 0.4468), (0.2470, 0.2435, 0.2616)) ])
Se realiza el mismo paso que antes para importar todo el dataset aplicandole la transformación a tensor con “transforms.ToTensor()”, solo que en lugar de transformarlo solo a tensor se le aplica la composición de transformaciones obtenida “transform”, así:
dataset = datasets.CIFAR10(data_path, train=True, download=True, transform=transform)
Por ultimo se trae otra imagen de el dataset recién creado con “transform” y probamos imprimir una imagen cualquiera, para verificar que todo está en orden.
img_transformed,label = dataset[125] plt.imshow(img_transformed.permute(1, 2, 0)) classes[label]
Excelente aporte para complementar al profe!!!
De donde sacaste la info de que hace imgs.view(3,-1)?? para poder leerlo porfaa
Gracias por el aporte ayuda a estudiar
Espero darme a entender por que si es un poco complicado seguir el ritmo de quien da la clase si nunca has trabajado con tensores: Cuando hacemos
imgs = torch.stack([img_tensor for img_tensor, _ in dataset], dim = 3) imgs.shape torch.Size([3, 32, 32, 50000])
Esto nos esta diciendo que tenemos un tensor de dimensiones [3,32,32,50000], un error muy común que veo en la mayoría de los comentarios es que quieren ver a un tensor como un vector o como algo que tiene una representación tridimensional , lo cual solo sera cierto hasta vectores de rango 3, pero después de eso pasan a ser abstracciones, interpretando esto nos quiere decir que, el tensor tiene una primera dimensión en 3 que para este caso corresponden a los colores RGB, cada una de esas dimensiones están formadas por dos dimensiones extras de 32, entonces tenemos 3 colores de 32 x 32 pixeles, lo que se almacena en cada uno de los campos es el valor del color es decir, la primera dimension [1,32,32,50000], corresponderia por decir a los valores en Rojo de cada pixel, asi [2,32,32,50000] corresponderian a los valores en azul de cada pixel, la ultima dimension solo nos indica el numero de imagenes.
Cuando hacemos
imgs.view(3,-1).mean(dim = 1)
Le estamos diciendo que vamos a separa los valores por cada color y tendremos un tensor de 3 filas correspondientes a los tres colores RGB, con 51200000 columnas que es la multiplicacion de 32x32 pixeles que tiene cada imagen por las 50000 imagenes, en resumen hacemos un promedio para el valor de cada color RGB de todas las imagenes
Gracias por la info :)
Todo el proceso del video explicado y ampliado teniendo encuenta lo que entiendo de este
//crea una ruta donde incicialmente guardar el dataset que va a descargar crea el dataset que proviene de la biblioteca datasets que importa con ayuda o marca o algo que no entiendo que es cifar10 este protocolo pide que se añada el donde se va a descargar, si el dataset es para entrenar y si es para descargar.
//descarga uno para entrenar y otro que no es para entrenar pero sí para validar si el entrenamiento fue correcto.
//obtenemos y escribimos todas las clases o clasificaciones de nuestro dataset que ha sido descargado observamos el tamaño del dataset.
//pruebo algún componente del dataset, en este caso al ser imagenes tomo una, también su etiqueta, y después muestro la imagen con su etiqueta y clase. (todo esto para aprender y comprobar que todo está OK)
//transformamos la imagen a tensor para su procesamiento posterior, usamos para ello el método "transforms.ToTensor()" y lo ligamos a una funcion a la cual le arrojaremos la imagen seleccionada, el tensor resultante de la transformacion de la img lo asignamos a img_tensor, en este caso. Acto seguido podemos observar el tensor y su forma (cantidad de dimensiones y de filas(x)columnas, en ese orden)
//una vez entendimos como transformar una sola imagen lo haremos con todo el dataset, con este fin volvemos a importar el dataset, solo que añadiendo esta transformacion ("transforms.ToTensor()") a todo lo que traigamos de esta forma tenemos todo el dataset en forma de tensores.
//podemos comprobar que en efecto, los datos importados se encuentran en modo de tensor.
//con la intención de obtener el mean y el std de todo el dataset para tener los parametros necesarios para normalizar y poder posteriormente hacer uso de estos datos para entrenar, hacemos lo que sigue:
->indagamos en qué rango se encuentran los datos que contienen nuestros tensores, a través de "img.min(), img.max()".
// pequeña digreción podemos observar nuestra imagen nuevamente, haciendo uso de "plt.imshow(img.permute(1,2,0))", lo hacemos así porque recordemos que al transformar cambian columnas de lado y al ingresar esto al "plt.imshow()" sin permutarlo no lo entenderá y habrá un error, es decir, no lo entiende porque en lugar de ser [X][Y][Z] -> ([0][1][2]), es [Z][X][Y] -> ([0][1][2]), siendo entonces [Z] la dimensión [0], [X] la [1], y [Y] la [2], con el permute vemos entonces que recuadra todo permute([X][Y][Z]) = permute(1,2,0).
->Ahora sí, continuando el proceso hacemos lo siguiente, apilamos todos los datos con "torch.stack([y dentro un for que no termino de entender], dim = 3(tridimencional my friend))", para un manejo más fácil de toda la informacion, y los metemos en "imgs".
->miramos la forma de nuestro stack o apilado, revisando que sea correspondiente con los valores lógicamente esperados
->Ahora que ya tenemos los tensores correspondientes a las imagenes cómodamente apilados y trabajables nos disponemos a calcular lo que siempre hemos querido calcular. primero el mean con "imgs.view(3,-1).mean(dim=1)", lo que hizo con el "imgs.view(3,-1)" fue reacomodar el arreglo de tensores para que tengan 3 filas y el número necesario de columnas con el "-1". lo que hizo con el ".mean(dim=1)" lo comenté en uno de mis aportes anteriores en esta clase.
->Acto seguido el mismo proceso pero esta vez con "imgs.view(3,-1).std(dim=1)" para obtener el STandarDeviation std
//Con los datos de Mean y Std ya podemos hacer nuestra transformación de normalización, como son varias las transformaciones que hay que hacer hacemos una composicion de transformaciones con el ".Compose()" dentro de ella ponemos la transformación a Tensor y la normalizacion con ".Normalize((mean), (std))"
//realizamos el mismo paso que antes para importar todo el dataset aplicandole la transformación a tensor con "transforms.ToTensor()", solo que en lugar de transformarlo solo a tensor le aplicamos nuestra composición de transformaciones "transform", así: dataset = datasets.CIFAR10(data_path, train=True, download=True, transform=transforms).
//podemos traer otra imagen de el dataset recién creado con "transform" y probamos imprimir una imagen cualquiera, para verificar que todo está en orden.
// Y fin :).
Super, gracias por el aporte. Me respondió varios interrogantes
extelente...Muchas gracias
El único proposito de esta clase es hallar la media y la desviación estándar. Lamentablemente incluye mucha informacion poco práctica y que termina confundiendo más que ayudando: nunca utiliza el arreglo de validación y define varias veces el dataset cuando si sólo quería hallar la media y la desviación estándar bastaba con definirlo bien una sola vez.
Estoy como Sócrates, "Yo sólo sé que no sé nada" :(
¿Por qué plt.imshow(img_transformed.permute(1, 2, 0))? Si hacen img_transformed.size(), obtendrán: torch.Size([3, 32, 32]) (Recuerden que es una imagen) Esto quiere decir que es un tensor que tiene 3 dimensiones (1° Red, 2° Green, 3° Blue), y un tamaño de 32 x 32 pixels. Si van a la documentación de plt.imshow(), se pueden dar cuenta que acepta imágenes en tensores con la forma de (M, N, 3), o sea M filas, N columnas y 3 dimensiones, en nuestro caso tenemos (3, 32, 32), por eso debemos permutar la imagen a (32, 32, 3). Y si se fijan en esto torch.Size([3, 32, 32]), el índice [0]: 3, indice [1]: 32 y el indice [2]: 32. Como queremos esta forma (32, 32, 3), movemos el indice [0]: 3 al final, quedando los índices [1][2][0] --> (32, 32, 3), por eso se usa permute(1, 2, 0). Espero les sirva, yo no sabía y lo averigüé, aquí la documentación
¿Por qué a transforms.Normalize((0.4915, 0.4823, 0.4468), (0.2470, 0.2435, 0.2616)) se le pasan esos valores? busqué en Internet pero veo que pasan valores distintos.
Me parece que es para normalizar los valores de entrenamiento que se obtuvieron previamente con el promedio y la desviación estándar.
transforms.Normalize( mean, std)
para nuestro ejercicio , al calcular mean y std nos retorna esos valores.... En otros ejercicios va a retornar otros valores porque son diferentes los números de los tensores.
El tema es muy interesante, aunque sigo sin entender de dónde salen algunas cosas
Para no escribir de forma manual en Normalize() las tuplas, pueden colocar variables
Normalize(mean, std)
Y las variables las pueden obtener así
mean = tuple(value.item() for value in imgs.view(3, -1).mean(dim=1)) std = tuple(value.item() for value in imgs.view(3, -1).std(dim=1))
CIFAR 10 es un dataset de 50000 imágenes as color, usadas normalmente para crear algoritmos de visión artificial a través de machine learning. Las dimensiones de estas imágenes es de 32 x 32 y se divide en 10 clases, [aviones, automóviles, pájaros, gatos, venados, perros, ranas, caballos, barcos y camiones]
Explican el uso de (dim=x) que no me había quedado nada claro -->https://towardsdatascience.com/understanding-dimensions-in-pytorch-6edf9972d3be
de dónde sale lo de permute(1,2,0)?
tengo la misma duda.
Es para visualizar la imagen contenida en el Tensor, usamos un tensor de 3 dimensiones en este ejemplo, el eje X esta representado por el numero 1, el eje Y por el 2, y el eje Z por el 0, si cambias de orden el 1 por el 2 la imagen se pone de cabeza
https://stackoverflow.com/questions/53623472/how-do-i-display-a-single-image-in-pytorch/53633017
Este sitio web nos ayuda a comprender mas lo que hay dentro del CIFAR10. Cabe notar que también hay código de esta biblioteca para Matlab y para lenguaje C: https://www.cs.toronto.edu/~kriz/cifar.html
Una pregunta, cuando haces el comando classes tú dices que las clases ya están predeterminadas ¿cómo podría yo ver cuáles son tales clases predeterminadas o cómo yo puedo determinarlas?. Mil gracias :D
tengo la misma duda, no queda claro en el video
Están definidas en la documentación de este dataset: https://www.cs.toronto.edu/~kriz/cifar.html
Por que? al obtener la STD y MEAN usa imgs.vie(3,-1) ? por qué esos valores ?
(3,-1) quiere decir de poner el tensor en columnas de 3 filas ( en y 3 y en x -1 que quiere decir hasta donde alcanze )
Genial
En este enlace queda más claro la parte de visualizar imgenes transformadas con Pytorch: https://stackoverflow.com/questions/53623472/how-do-i-display-a-single-image-in-pytorch/53633017
Jose genial aporte, gracias.
Las imágenes a continuación presentan los resultados obtenidos al ejecutar el código de esta sesión de clase:
Vista 1 ![](
Vista 2 ![](
Vista 3 ![](
Vista 4
Vista 5 ![](
¿Que otras transformaciones se pueden aplicar a las imágenes y que otras herramientas permite Pytorch para ello?
Hola en la documentación oficial de Pytorch encuentras todas las posibles transformaciones que puedes utilizar, te dejo el enlace https://pytorch.org/docs/stable/torchvision/transforms.html
Hay algún curso donde den profundidad en el tema de la "normalización" de los valores? quisiera saber cual es la necesidad de hacer esto y que representan exactamente los valores luego de la normalización.
Hola Ramiro, podrías ver en el curso de fundamentos de bases de datos en el módulo sobre normalización, te lo recomiendo mucho https://platzi.com/clases/bd/
¿Porque me sale esto?
Hola Creo que te faltó importar datasets
from torchvision import datasets
Saludos