﻿1
00:00:00,000 --> 00:00:12,540
En esta lección, crearemos una red neuronal para clasificación,

2
00:00:12,740 --> 00:00:15,500
la cual usaremos para clasificar números escritos a mano.

3
00:00:16,500 --> 00:00:16,680
Comencemos.

4
00:00:18,700 --> 00:00:22,200
En esta lección, vamos a utilizar una red neuronal

5
00:00:22,200 --> 00:00:24,100
para hacer una clasificación.

6
00:00:24,420 --> 00:00:26,120
Y en lugar de una clasificación simple,

7
00:00:26,260 --> 00:00:28,340
vamos a hacer una mucho más interesante.

8
00:00:28,960 --> 00:00:30,400
Vamos a crear un nuevo archivo,

9
00:00:30,520 --> 00:00:33,300
lo voy a llamar red de clasificación.

10
00:00:34,140 --> 00:00:38,260
Y para eso vamos a utilizar un conjunto de datos existente llamado MNIST.

11
00:00:39,200 --> 00:00:45,460
Este conjunto es muy especial ya que nos permite identificar números escritos a mano.

12
00:00:46,160 --> 00:00:51,320
Este set de datos existe directamente en TensorFlow y lo puedes encontrar fácilmente buscando TensorFlow datasets MNIST.

13
00:00:51,320 --> 00:00:58,420
Y aquí podemos ver información relacionado al set, su tamaño, etc.

14
00:00:58,980 --> 00:01:07,380
Pero algo interesante es que el propio set ya viene separado en 60.000 imágenes para entrenamiento y 10.000 para pruebas.

15
00:01:07,900 --> 00:01:08,840
Y si bajamos un poco,

16
00:01:08,960 --> 00:01:11,080
podemos ver información de las imágenes.

17
00:01:11,200 --> 00:01:12,300
Las imágenes aquí nos dice la forma y nos dice 28,

18
00:01:12,300 --> 00:01:20,940
28, 1. Quiere decir que cada imagen tiene 28 píxeles por 28 píxeles de tamaño.

19
00:01:21,380 --> 00:01:24,200
Y este 1 simplemente son los canales de color.

20
00:01:24,620 --> 00:01:25,480
Como es blanco y negro,

21
00:01:25,600 --> 00:01:26,460
solo requiere 1.

22
00:01:26,580 --> 00:01:28,260
Pero si fueran a color serían 3,

23
00:01:28,660 --> 00:01:29,520
1 para rojo,

24
00:01:29,920 --> 00:01:31,080
verde y azul.

25
00:01:31,480 --> 00:01:36,240
Vamos a regresar a nuestro código y vamos a comenzar importando TensorFlow con import

26
00:01:36,320 --> 00:01:37,200
TensorFlow, haz TF y vamos a agregar una importación adicional llamada

27
00:01:38,020 --> 00:01:47,620
TensorFlow datasets y vamos a ponerle haz TensorFlow datasets de FDS.

28
00:01:48,280 --> 00:01:53,980
Y con esto podemos descargar de manera muy simple los sets de datos que se incluyen como parte de TensorFlow.

29
00:01:54,520 --> 00:02:00,180
Ahora, para eso podemos utilizar TFDS.load y le decimos el nombre del set de datos que queremos bajar,

30
00:02:00,180 --> 00:02:29,840
por ejemplo MNIST. Para lo que vamos a hacer, recomiendo agregar dos propiedades adicionales, haz Supervise y haz Supervise. Y vamos a ponerle a la parte de abajo, que es la parte de abajo del código. Y listo.

31
00:02:30,180 --> 00:02:31,720
el set de datos.

32
00:02:31,900 --> 00:02:35,340
Aquí me marcó un error ya que no corrí la primer celda para hacer las

33
00:02:35,680 --> 00:02:36,060
importaciones.

34
00:02:36,320 --> 00:02:38,400
Vamos a correrlo y después vamos a correr la segunda.

35
00:02:39,200 --> 00:02:40,320
Y listo, ya están descargados.

36
00:02:40,840 --> 00:02:46,280
Podemos utilizar, por ejemplo, escribiendo metadatos para ver cuáles son los metadatos del set.

37
00:02:46,420 --> 00:02:48,040
Y aquí nos dice el nombre,

38
00:02:48,140 --> 00:02:52,380
nombre completo incluyendo la versión del set e información adicional que

39
00:02:52,800 --> 00:02:55,120
podemos utilizar si quizá no vimos el sitio.

40
00:02:55,280 --> 00:02:58,080
Por ejemplo, el tamaño de las imágenes y label que

41
00:02:58,080 --> 00:03:02,180
vendría siendo la etiqueta nos dice que número de clases es igual a 10.

42
00:03:02,680 --> 00:03:07,000
Esto es porque estamos clasificando cada imagen en una de 10 clases,

43
00:03:07,140 --> 00:03:09,680
ya sea del número 0 hasta el 9.

44
00:03:10,060 --> 00:03:12,380
Al ser aprendizaje supervisado necesitamos

45
00:03:12,380 --> 00:03:16,500
siempre tener la característica que en este caso es la propia imagen y la

46
00:03:16,500 --> 00:03:19,100
etiqueta que nos dice qué número es.

47
00:03:19,540 --> 00:03:21,960
Vamos de una vez a separarlo en los

48
00:03:21,960 --> 00:03:23,760
datos de entrenamiento y datos de prueba.

49
00:03:23,900 --> 00:03:25,700
Podemos escribir algo simple como datos

50
00:03:25,960 --> 00:03:33,080
entrenamiento igual a datos train y datos pruebas igual a datos test.

51
00:03:33,220 --> 00:03:36,080
Lo ejecutamos y ya los tenemos separados.

52
00:03:36,580 --> 00:03:38,560
Y otra cosa que podemos ver aquí es,

53
00:03:38,740 --> 00:03:43,900
por ejemplo, de los metadatos utilizar features y marcar aquí que queremos label

54
00:03:43,900 --> 00:03:48,860
para obtener las etiquetas y algo como punto names para que nos diga cuáles son los nombres

55
00:03:48,860 --> 00:03:50,640
de las distintas etiquetas que tiene.

56
00:03:50,960 --> 00:03:51,680
Y tenemos los 10 valores desde el 0 hasta el 9.

57
00:03:51,680 --> 00:03:59,000
Vamos a guardar esto en una variable que se llame nombres clases igual a esto.

58
00:03:59,480 --> 00:04:00,800
Y así como en lecciones anteriores,

59
00:04:00,920 --> 00:04:03,340
tuvimos que hacer algo de preprocesamiento de los datos.

60
00:04:03,520 --> 00:04:05,100
En este caso requerimos muy poco,

61
00:04:05,280 --> 00:04:07,600
pero hay algo muy importante que tenemos que hacer,

62
00:04:08,000 --> 00:04:09,720
que es la normalización.

63
00:04:10,380 --> 00:04:14,160
Esto lo que significa es que finalmente estamos tratando con imágenes y las

64
00:04:14,160 --> 00:04:19,820
imágenes tienen un valor cada pixel desde 0 hasta 255,

65
00:04:19,900 --> 00:04:20,060
donde 0 es totalmente negro y 255 es totalmente negro.

66
00:04:20,060 --> 00:04:27,300
Y esto es porque cada pixel es representado por un byte.

67
00:04:27,840 --> 00:04:34,340
En la normalización lo que hacemos es transformar para que en lugar de que sea de 0 a 255,

68
00:04:34,720 --> 00:04:35,760
sea de 0 hasta 1,

69
00:04:35,960 --> 00:04:38,740
donde el 0 original sigue siendo igual a 0,

70
00:04:39,020 --> 00:04:41,080
pero el 255 va a ser igual a 1.

71
00:04:41,360 --> 00:04:43,360
Eso quiere decir que si tomamos el dato de en medio,

72
00:04:43,500 --> 00:04:45,040
que sería digamos 127 por ahí,

73
00:04:45,040 --> 00:04:56,080
sería igual a punto 5. Esta transformación lo hacemos por ejemplo, porque en general todos los modelos trabajan mucho mejor cuando todos los datos son escalados

74
00:04:56,080 --> 00:05:00,660
a números pequeños, de lo contrario pueden batallar más durante el proceso de entrenamiento.

75
00:05:01,020 --> 00:05:06,420
Y entonces lo que queremos es normalizar los datos de entrenamiento y pruebas

76
00:05:07,060 --> 00:05:07,760
con una función.

77
00:05:08,420 --> 00:05:09,040
¿Cómo sería eso?

78
00:05:09,280 --> 00:05:10,020
Por ejemplo, podemos decir datosEntrenamiento igual a datosEntrenamiento.map,

79
00:05:10,020 --> 00:05:17,380
y una función que tenemos que definir,

80
00:05:17,520 --> 00:05:19,820
digamos que le llamamos normalizar.

81
00:05:20,280 --> 00:05:24,780
Y vamos a hacer esto para los datos de entrenamiento y los datos de pruebas.

82
00:05:27,400 --> 00:05:30,360
Ahora, esta función la tenemos que definir aquí arriba,

83
00:05:30,920 --> 00:05:33,140
escribiendo algo como defNormalizar,

84
00:05:33,260 --> 00:05:33,840
que es la función,

85
00:05:34,480 --> 00:05:35,600
y aquí cada vez que se llame,

86
00:05:35,600 --> 00:05:43,840
los datos de entrenamiento finalmente cuentan con la propia identidad de la función. Y si nosotros llamamos map,

87
00:05:44,060 --> 00:05:47,340
lo que hace es que por cada uno de los registros que existen datos de entrenamiento,

88
00:05:47,460 --> 00:05:53,020
va a llamar a la función de normalizar con los datos para que se haga la transformación necesaria.

89
00:05:53,300 --> 00:05:55,720
Esto ya no es específico de redes neuronales,

90
00:05:55,780 --> 00:05:58,560
es simplemente de Python y como funciona de manera regular.

91
00:05:59,040 --> 00:05:59,580
Pero vamos a definir aquí que la función normalizar recibe las imágenes y las etiquetas.

92
00:05:59,580 --> 00:06:04,060
Y aquí vamos a hacer un ejemplo de una función que se llama normalizar. Vamos a definir aquí que la función normalizar recibe las imágenes y las etiquetas.

93
00:06:04,580 --> 00:06:06,980
Y aquí vamos a hacer el proceso de normalización.

94
00:06:07,460 --> 00:06:10,220
Imágenes igual a tf.cast,

95
00:06:10,640 --> 00:06:11,180
imágenes,

96
00:06:11,760 --> 00:06:13,780
tf.float32.

97
00:06:14,400 --> 00:06:19,240
Esto lo hacemos porque los datos de manera original finalmente son números enteros,

98
00:06:19,280 --> 00:06:20,580
desde 0 a 255,

99
00:06:20,660 --> 00:06:21,520
no hay puntos decimales.

100
00:06:22,020 --> 00:06:24,600
Pero como lo vamos a transformar a un número de 0 hasta 1,

101
00:06:25,040 --> 00:06:26,780
necesitamos puntos decimales.

102
00:06:26,780 --> 00:06:26,940
Entonces,

103
00:06:27,340 --> 00:06:31,540
primero que nada, lo convertimos todas las imágenes a que sean de tipo flotante.

104
00:06:32,020 --> 00:06:36,020
Y ahora sí podemos hacer la normalización escribiendo algo como imágenes

105
00:06:36,540 --> 00:06:39,720
igual a imágenes entre 255.

106
00:06:40,220 --> 00:06:41,620
Una vez que hicimos la transformación,

107
00:06:41,740 --> 00:06:44,380
debemos regresar los datos con return imágenes

108
00:06:44,480 --> 00:06:46,420
etiquetas, tal cual lo que recibimos.

109
00:06:47,460 --> 00:06:50,440
En resumen, los datos de entrenamiento traen datos con los

110
00:06:50,560 --> 00:06:55,920
píxeles de la imagen y cada píxel es representado con un número entero de 0 a 255.

111
00:06:56,380 --> 00:07:01,080
Utilizando map nos aseguramos que por cada dato de datos de entrenamiento se llame a esta función

112
00:07:01,080 --> 00:07:02,200
que le especificamos aquí.

113
00:07:02,720 --> 00:07:05,780
Y esta función lo único que se encarga es de convertir las imágenes,

114
00:07:06,340 --> 00:07:09,480
dividimos los datos entre 255 y lo regresamos.

115
00:07:09,700 --> 00:07:12,440
Y eso hacemos para los datos de entrenamiento y de pruebas.

116
00:07:13,660 --> 00:07:19,140
Finalmente, en este caso, voy a agregar otra línea adicional y esto es agregar en caché.

117
00:07:19,400 --> 00:07:24,240
Esto nos ayuda a que mientras está procesando los datos durante el entrenamiento,

118
00:07:24,820 --> 00:07:28,820
los guarde en memoria para que las siguientes vueltas sean más rápidas,

119
00:07:29,180 --> 00:07:31,800
en lugar de que esté constantemente cargándolas del disco.

120
00:07:32,400 --> 00:07:35,180
Entonces vamos a escribir datos entrenamiento.

121
00:07:37,260 --> 00:07:42,940
Igual a datos entrenamiento punto caché y voy a hacer lo mismo para los datos de pruebas.

122
00:07:42,940 --> 00:07:49,140
Y con esto ya se va a hacer el proceso de normalización.

123
00:07:49,560 --> 00:07:51,600
Vamos a ejecutarlo y ya queda listo.

124
00:07:52,040 --> 00:07:56,240
Ahora algo que podemos hacer es pintar por aquí uno de los números que vienen en el set

125
00:07:56,300 --> 00:07:57,640
para ver más o menos cómo vienen.

126
00:07:57,820 --> 00:08:03,700
Si yo, por ejemplo, escribo datos entrenamiento punto Teik 1 y lo ejecuto,

127
00:08:04,180 --> 00:08:08,860
Teik es una función que toma de los datos de entrenamiento simplemente un registro.

128
00:08:09,040 --> 00:08:11,800
Pero como normalmente podemos obtener muchos registros,

129
00:08:11,920 --> 00:08:14,600
esto nos regresa algo sobre lo que podemos iterar.

130
00:08:15,120 --> 00:08:20,220
Entonces lo que podemos hacer aquí es un for y como esta función nos regresa dos resultados,

131
00:08:20,680 --> 00:08:22,380
una imagen y una etiqueta,

132
00:08:23,100 --> 00:08:27,620
podemos decir for imagen etiqueta in Teik 1 y en realidad no

133
00:08:27,660 --> 00:08:28,700
tenemos que hacer nada.

134
00:08:28,920 --> 00:08:30,520
Podemos agregar directamente el break,

135
00:08:31,200 --> 00:08:31,720
ya que aquí cuando

136
00:08:31,720 --> 00:08:36,360
empiece la iteración va a decir declaro una nueva variable llamada imagen y una etiqueta,

137
00:08:36,820 --> 00:08:40,940
le asigno el primer registro que me encuentro y en realidad ya no tengo que hacer nada aquí.

138
00:08:40,940 --> 00:08:44,760
Entonces puedo simplemente especificar break y voy a utilizar esta imagen más adelante.

139
00:08:45,080 --> 00:08:52,260
Ahora para poder mostrarlo en pantalla voy a importar con import matplotlib punto piplot as plt

140
00:08:52,260 --> 00:08:56,600
y vamos a dibujarlo y mostrarlo en pantalla.

141
00:08:57,120 --> 00:08:59,740
Vamos a especificar aquí plt punto figure,

142
00:09:00,020 --> 00:09:02,600
podemos especificarle aquí un tamaño en específico.

143
00:09:02,680 --> 00:09:03,560
Ahorita lo voy a dejar así.

144
00:09:04,020 --> 00:09:05,460
Voy a utilizar imshow,

145
00:09:05,460 --> 00:09:12,540
que es parte de matplotlib y nos permite mostrar imágenes y lo que quiero es mostrar la imagen

146
00:09:13,020 --> 00:09:13,540
tal cual.

147
00:09:13,720 --> 00:09:18,840
Finalmente voy a agregar plt punto show para mostrarla y vamos a ver qué es lo que hace.

148
00:09:19,380 --> 00:09:21,720
Como puedes ver, ya nos muestra por aquí la imagen,

149
00:09:22,020 --> 00:09:24,360
el número 4, solo que aparece como morado

150
00:09:24,360 --> 00:09:28,060
con verde y eso es porque podemos cambiarle aquí el cmap,

151
00:09:28,260 --> 00:09:30,920
que es como el esquema de colores y como

152
00:09:30,920 --> 00:09:36,760
solamente tenemos blanco y negro puedo especificar plt punto cm punto binary, es decir binario,

153
00:09:37,120 --> 00:09:39,960
para que considere que solamente hay blanco y negro.

154
00:09:40,660 --> 00:09:42,900
Voy a ejecutarlo de nuevo y ya podemos ver que aquí

155
00:09:42,900 --> 00:09:43,800
hay un cuadro.

156
00:09:44,020 --> 00:09:50,640
Incluso puedo agregarle aquí con plt punto color bar para que nos muestre una barra

157
00:09:50,640 --> 00:09:54,260
a la derecha en donde podemos ver que va desde 0 hasta 1,

158
00:09:54,580 --> 00:09:56,700
pero ya no tenemos de 0 a 255 sino

159
00:09:56,820 --> 00:09:58,840
solamente desde 0 hasta 1.

160
00:09:59,260 --> 00:10:00,880
Y de hecho podemos mostrar más.

161
00:10:01,160 --> 00:10:03,520
Voy a copiar este código y

162
00:10:03,580 --> 00:10:06,100
pegarlo aquí abajo y lo voy a cambiar un poco.

163
00:10:06,660 --> 00:10:08,780
Esta importación en realidad ya no la necesito

164
00:10:08,780 --> 00:10:14,400
y voy a empezar escribiendo plt punto figure con una tamaño de figura,

165
00:10:14,620 --> 00:10:17,560
fix size, digamos de 10,10

166
00:10:17,560 --> 00:10:20,680
para que sea un poco más grande y lo que quiero es pintar varios.

167
00:10:20,880 --> 00:10:22,480
Por ejemplo, vamos a pintar hasta 25

168
00:10:22,680 --> 00:10:25,340
imágenes para ver cómo se ven.

169
00:10:25,880 --> 00:10:27,240
Ahora, cuando queremos imprimir varias,

170
00:10:27,320 --> 00:10:28,820
tenemos que utilizar subplots,

171
00:10:28,940 --> 00:10:31,960
que es algo de matplotlib para poder mostrar varias imágenes.

172
00:10:32,440 --> 00:10:34,160
Sin embargo, me iré parte por parte.

173
00:10:34,560 --> 00:10:38,700
Para empezar, voy a quitar aquí figure y voy a escribir plt punto subplot

174
00:10:38,800 --> 00:10:44,600
y le voy a especificar que quiero 5 filas y 5 columnas y le debo especificar un índice,

175
00:10:44,820 --> 00:10:46,340
pero aquí todavía no tengo un índice.

176
00:10:46,480 --> 00:10:49,700
Esto simplemente, esta iteración me está regresando la imagen y la etiqueta.

177
00:10:49,700 --> 00:10:52,080
Si yo quiero tener una variable adicional,

178
00:10:52,420 --> 00:10:53,780
que sea por ejemplo el índice,

179
00:10:54,160 --> 00:10:55,840
yo puedo agregar que sea el índice,

180
00:10:56,100 --> 00:10:58,380
pongo la imagen y la etiqueta como una tupla,

181
00:10:58,500 --> 00:11:00,300
que es lo que me regresan los datos de entrenamiento,

182
00:11:00,780 --> 00:11:05,800
y aquí cambiar la iteración por el número de rates para poder tener el índice.

183
00:11:06,000 --> 00:11:10,460
Esta es una forma en Python para poder en una iteración tener el índice y poder utilizarlo.

184
00:11:10,540 --> 00:11:14,660
Y aquí voy a escribir y más uno para que sepa cómo pintarlo en la pantalla.

185
00:11:15,240 --> 00:11:18,680
Finalmente, el plt punto show lo voy a dejar atrás para que no sea parte de la iteración.

186
00:11:18,680 --> 00:11:23,040
Y lo voy a ejecutar a ver si no se me pasó escribir algo por aquí.

187
00:11:23,520 --> 00:11:24,020
Y listo.

188
00:11:24,400 --> 00:11:27,560
Está mostrando por aquí una cuadrícula con varias de las imágenes.

189
00:11:27,740 --> 00:11:29,200
El 4 que teníamos ahí arriba,

190
00:11:29,320 --> 00:11:29,860
que era el primero,

191
00:11:30,000 --> 00:11:30,780
pero tenemos un 1,

192
00:11:30,860 --> 00:11:32,520
un 0, un 7, 8, etc.

193
00:11:33,100 --> 00:11:36,100
Todos estos números fueron escritos por personas reales.

194
00:11:36,580 --> 00:11:40,960
El set de datos de MNIST se hizo con 70 mil números escritos a mano de personas

195
00:11:40,960 --> 00:11:46,180
y la tomaron para poder hacer este set y utilizarlo para entrenar y probar modelos de Machine Learning.


