Documente Academic
Documente Profesional
Documente Cultură
bloques de construcción
matemáticos de redes
neuronales
El flujo de trabajo será el siguiente: En primer lugar, vamos a alimentar la red neuronal los
datos de entrenamiento, y train_images train_labels. La red será entonces aprender a asociar
imágenes y etiquetas. Por último, vamos a solicitar a la red para producir predicciones para
test_images, y vamos a verificar si estas predicciones coinciden con las etiquetas de
test_labels.
acumulación de permitir que la red de nuevo, recuerda que no se espera que entender todo
acerca de este ejemplo todavía.
Listing 2.2 La arquitectura de red
de Keras importar modelos
de Keras capas de
importación
red = models.Sequential () network.add (layers.Dense (512, la activación
= 'relu', input_shape = (28 * 28,))) network.add (layers.Dense (10,
activación = 'softmax'))
Para hacer que la red listo para el entrenamiento, tenemos que elegir tres cosas más, como
parte de la etapa de compilación:
Una función de pérdida-Como la red será capaz de medir su rendimiento en los datos
de entrenamiento, y por lo tanto cómo va a ser capaz de dirigir sí en la dirección
correcta.
un optimizador-El mecanismo a través del cual la red se actualizará en base a los datos
que ve y su función de pérdida.
Indicadores para el monitor durante el entrenamiento y las pruebas-Aquí, sólo le
importe por la precisión (la fracción de las imágenes que fueron clasificados
correctamente).
El propósito exacto de la función de pérdida y el optimizador se hará claro a lo largo de los
próximos dos capítulos.
Listing 2.3 El paso de compilación
network.compile (optimizador = 'rmsprop', pérdida =
'categorical_crossentropy', las métricas = [
'exactitud'])
También tenemos que codificar categóricamente las etiquetas, de un paso que explican en el
capítulo 3.
Añadir 2,5 Preparación de las etiquetas
de keras.utils to_categorical importación
La exactitud de la prueba-conjunto resulta ser 97,8% -que es un poco más baja que la exactitud
conjunto de entrenamiento. Esta brecha entre la precisión y la exactitud de la prueba de
entrenamiento es un ejemplo de un ajuste por exceso: el hecho de que los modelos de
máquinas de aprendizaje tienden a rendir menos en los nuevos datos que en sus datos de
entrenamiento. Sobreajuste es un tema central en el capítulo 3.
Con esto concluye nuestro primer ejemplo que acaba de ver cómo se puede construir y
entrenar una red neuronal para clasificar los dígitos escritos a mano en menos de 20 líneas de
código Python. En el siguiente capítulo, voy a entrar en detalles sobre cada pieza en
movimiento que acabamos de vista previa y aclarar lo que está pasando detrás de las escenas.
Usted aprenderá acerca de los tensores, los datos que almacenan los objetos que entran en la
red; operaciones tensor, que las capas están hechas de; y descenso de gradiente, lo que permite
a la red para aprender de sus ejemplos de entrenamiento.
Este vector tiene cinco entradas y así se llama un vector de 5 dimensiones. No se debe
confundir un vector 5D con un tensor 5D! A 5D vector sólo tiene un eje y tiene cinco
dimensiones a lo largo de su eje, mientras que un tensor 5D tiene cinco ejes (y puede tener
cualquier número de dimensiones a lo largo de cada eje). Dimensionalidad puede denotar el
número de entradas a lo largo de un eje específico (como en el caso de nuestro vector 5D) o
el número de ejes en un tensor (tales como un tensor 5D), que puede ser confuso a veces. En
este último caso, es técnicamente más correcto hablar de un tensor de rango 5 (el rango de un
tensor es el número de ejes), pero la notación ambigua 5D tensor es común
independientemente.
Las entradas desde el primer eje se llaman las filas, y las entradas desde el segundo eje se
llaman las columnas. En el ejemplo anterior, [5, 78, 2, 34, 0] es la primera fila de x, y [5, 6, 7]
es la primera columna.
Al comprimir 3D tensores en una matriz, se puede crear un tensor de 4D, y así sucesivamente.
En el aprendizaje profundo, podrás manipular general tensores que son 0D a 4D, aunque es
posible subir a 5D si procesa los datos de vídeo.
tensor carbón. Tenga en cuenta que los tensores de cadena no existen en Numpy (o en
la mayoría de otras bibliotecas), porque los tensores viven en preasignados, segmentos
de memoria contiguas: la mayor, siendo de longitud variable, impediría el uso de esta
aplicación.
Para que esto sea más concreto, vamos a mirar hacia atrás en los datos que procesa en el ejemplo
MNIST. En primer lugar, cargamos el conjunto de datos MNIST:
de keras.datasets mnist importación
Así que lo que tenemos aquí es un tensor 3D de enteros de 8 bits. Más precisamente, es una matriz de
60.000 matrices de 28 × 8 números enteros. Cada uno de tales matriz es una imagen en escala de grises,
con coeficientes entre 0 y 255.
Vamos a mostrar el cuarto dígito en este tensor 3D, usando la biblioteca Matplotlib (parte del
conjunto de Python científica estándar); véase la figura 2.2.
Añadir 2,6 Viendo el cuarto dígito
dígito = train_images [4]
matplotlib.pyplot importación como plt.imshow plt
(dígitos, CMAP = plt.cm.binary) plt.show ()
Es equivalente a esta notación más detallada, que especifica un índice inicial y el índice de
parada para el corte a lo largo de cada eje tensor. Tenga en cuenta que: es equivalente a
seleccionar todo el eje:
Equivalente a la
>>> my_slice = train_images [10: 100,:,:] ejemplo anterior
>>> my_slice.shape
(90, 28, 28)También equivalente a la
>>> my_slice = train_images [10: 100, 0:28, 0:28] ejemplo anterior
>>> my_slice.shape
(90, 28, 28)
En general, es posible seleccionar entre dos índices a lo largo de cada eje tensor. Por ejemplo,
con el fin de seleccionar 14 × 14 píxeles en la esquina inferior derecha de todas las imágenes,
hacer esto:
my_slice = train_images [:, 14 :, 14:]
También es posible utilizar índices negativos. Al igual que los índices negativos en las listas
de Python, indican una posición con respecto al extremo del eje actual. Con el fin de recortar
las imágenes a los parches de 14 × 14 píxeles centrada en el medio, esto se hace: my_slice =
train_images [:, 7: -7, 7: -7]
Caracteristi
cas
Las
muestras
timesteps Figura 2.3 Un tensor de datos 3D TimeSeries
El eje de tiempo es siempre el segundo eje (eje de índice 1), por convención. Echemos un
vistazo a algunos ejemplos:
Un conjunto de datos de precios de las acciones. Cada minuto, almacenamos el precio
actual de la acción, el precio más alto en el pasado minutos, y el precio más bajo en el
pasado minutos. Así, cada minuto se codifica como un vector 3D, todo un día de
operaciones se codifica como un tensor 2D de forma (390, 3) (hay 390 minutos en un
día de la operación), y el valor de datos de 250 días se puede almacenar en un tensor
3D de forma (250, 390, 3). A continuación, cada muestra tendría un valor de los datos
de un día.
Un conjunto de datos de tweets, en las que codifican cada tweet como una secuencia
de 280 caracteres de un alfabeto de 128 caracteres únicos. En esta configuración, cada
carácter puede ser codificada como un vector binario de tamaño 128 (un vector de todos
ceros excepto para una entrada de 1 en el índice correspondiente al carácter). Entonces
cada tweet puede ser codificada como un tensor 2D de forma (280, 128), y un conjunto
de datos de 1 millones de tweets se pueden almacenar en un tensor de forma (1000000,
280, 128).
Los canales de
color
Altura
Las
muestras
Figura 2.4A los datos de imagen 4D
Anchura tensor (convención canales-primeros)
la parte superior de uno al otro. A Keras miradas de instancia capa como esta:
Esta capa se puede interpretar como una función, que toma como entrada un tensor 2D y
devuelve otro 2D tensor-una nueva representación para el tensor de entrada. Específicamente,
la función es la siguiente (donde W es un tensor 2D y b es un vector, ambos atributos de la
capa):
salida = relu (punto (W, de entrada) + b)
Vamos a descomprimir esto. Tenemos tres operaciones tensor aquí: un producto de punto
(punto) entre el tensor de entrada y un tensor de nombre W; una adición (+) entre el tensor 2D
resultante y un vector b; y, por último, una operación relu. relu (x) es max (x, 0).
NOTA Aunque esta sección se ocupa en su totalidad con las expresiones de álgebra
lineal, que no encontrará en cualquier notación matemática aquí. Me he dado cuenta
que los conceptos matemáticos pueden ser más fácilmente dominado por los
programadores sin conocimientos matemáticos si están expresados como Python
corta de fragmentos en lugar de ecuaciones matemáticas. Así que vamos a utilizar
código Numpy largo.
return x
z = x + y Además Element-sabia
2.3.2 Radiodifusión
Nuestra aplicación anterior ingenua de naive_add sólo es compatible con la adición de los
tensores 2D con formas idénticas. Pero en la capa densa introdujo anteriormente, hemos
añadido un tensor con un vector 2D. ¿Qué ocurre con la adición cuando las formas de los dos
tensores que se añade difieren?
Cuando sea posible, y si no hay ambigüedad, el tensor más pequeña será transmitido para
que coincida con la forma del tensor de mayor tamaño. Radiodifusión consta de dos pasos:
1 Ejes (llamados ejes de transmisión) se añaden al tensor más pequeña para que coincida
con el Ndim del tensor más grande.
2 El tensor más pequeña se repite junto a estos nuevos ejes para que coincida con la
forma completa del tensor más grande.
Echemos un vistazo a un ejemplo concreto. Considere X con forma (32, 10) e Y con forma
(10,). En primer lugar, añadimos un primer eje vacío ay, cuya forma se convierte en (1, 10).
Luego, repetimos y 32 veces al lado de este nuevo eje, de modo que nos encontramos con un
tensor Y con forma de
evitar sobrescribir
para i en el rango (x.shape
[0]):
el tensor de entrada.
para j en el rango (x.shape [1]):
x [i, j] + = y [j]
return x
numpy importación
como np z = np.dot
(x, y)
Usted habrá notado que el producto escalar entre dos vectores es un escalar y que los únicos
vectores con el mismo número de elementos son compatibles para un producto escalar.
También puede tomar el producto escalar entre una matriz x y un vector y, que devuelve
un vector donde los coeficientes son los productos de puntos entre Y y las filas de x. Se
implementa de la siguiente manera:
También se podría reutilizar el código que escribimos anteriormente, que pone de relieve la
relación entre un producto matriz-vector y un producto vectorial:
def naive_matrix_vector_dot (x,
y): z = np.zeros (x.shape
[0]) para i en el rango
(x.shape [0]):
z [i] = naive_vector_dot (x [i,:], y)
z retorno
Tenga en cuenta que tan pronto como uno de los dos tensores tiene una mayor Ndim de 1,
punto ya no es simétrica, lo que quiere decir que punto (x, y) no es el mismo que el punto (y,
x).
Por supuesto, un producto de punto se generaliza a tensores con un número arbitrario de
ejes. Las aplicaciones más comunes pueden ser el producto escalar entre dos matrices. Puede
tomar el producto escalar de dos matrices x e y (punto (x, y)) si y sólo si x.shape [1] ==
y.shape [0]. El resultado es una matriz con forma (x.shape [0],
y.shape [1]), donde los coeficientes son los productos vectoriales
entre las filas de x y las columnas de y. Aquí está la aplicación
ingenua:def naive_matrix_dot (x, y):
y.shape:
(ante)
X.y=z s de
si Columna de y
si
x.shape: z.shape:
(a, b) (a, c)
u
n z [i, j] Figura 2.5 Matriz de puntos
Fila de x diagrama de subproducto
cajas
Y así.
Remodelación de un medio tensor reordenación de sus filas y columnas para que coincida con
una forma deseada. Naturalmente, el tensor reconfigurado tiene el mismo número total de
coeficientes como el tensor inicial. Remodelación se entiende mejor a través de ejemplos
simples:
>>> x = np.array ([[0., 1.],
[2., 3.],
[4., 5.]])
>>> print (x.shape)
(3, 2)
>>> x = x.reshape ((6, 1))
>>> x array
([[0.], [1.],
[2.],
[3.],
[4.],
[5.]])
Es un punto en un espacio 2D (véase la figura 2.6). Es común a la imagen un vector como una
flecha que une el origen hasta el punto, como se muestra en la figura 2.7.
1 U [0.5, 1] 1 U [0.5, 1]
N N
1 1
Vamos a considerar un nuevo punto, B = [1, 0,25], lo que vamos a añadir a la anterior. Esto
se hace geométricamente por el encadenamiento de juntas las flechas de vectores, con la
ubicación que resulta ser el vector que representa la suma de los dos vectores anteriores
(véase la figura 2.8).
A+B
1 U
N
si
1 Figura 2.8 Interpretación
geométrica de la suma de dos vectores
En esta expresión, W y b son tensores que son atributos de la capa. Se llaman los pesos o
parámetros entrenables de la capa (el Kernel y el sesgo de atributos, respectivamente). Estos
pesos contienen la información obtenida por la red de la exposición a los datos de
entrenamiento.
Inicialmente, estas matrices de peso se llenan con valores aleatorios pequeños (un paso
llamado inicialización aleatorio). Por supuesto, no hay razón para esperar que relu (punto (W,
de entrada) + b), cuando W y b son al azar, se dió ningún representaciones útiles. Las
representaciones resultantes no tienen sentido, pero son un punto de partida. Lo que sigue es
el ajuste gradual de estos pesos, en base a una señal de realimentación. Este ajuste gradual,
también llamado entrenamiento, es básicamente el aprendizaje que el aprendizaje automático
se trata.
Esto sucede dentro de lo que se llama un bucle de formación, que funciona de la siguiente
manera. Repita estos pasos en un bucle, mientras sea necesario:
1 Dibuje un lote de la formación de x muestras y los objetivos y correspondiente.
2 Ejecutar la red de a x (un paso llamado el pase hacia adelante) para obtener
predicciones y_pred.
3 Calcular la pérdida de la red en el lote, una medida de la falta de coincidencia entre
y_pred e y.
4 Actualizar todos los pesos de la red de una manera que reduce ligeramente la pérdida
en este lote.
Que finalmente va a terminar con una red que tiene una pérdida muy baja de sus datos de
entrenamiento: una falta de coincidencia entre las predicciones de baja y_pred y objetivos
previstos y. La red ha “aprendido” para mapear sus entradas a los objetivos correctos. Desde
lejos, puede parecer que la magia, pero cuando se reduce a pasos elementales, que resulta ser
simple.
Paso bastante-1 solo sonidos fáciles código de E / S. Los pasos 2 y 3 son meramente la
aplicación de un puñado de operaciones tensor, por lo que podría poner en práctica estos pasos
sólo a partir de lo que aprendió en la sección anterior. La parte difícil es el paso 4: actualización
de los pesos de la red. Teniendo en cuenta un coeficiente de peso individual en la red, ¿cómo
se puede calcular si el coeficiente debe ser aumentado o disminuido, y por cuánto?
Una solución ingenua sería congelar todos los pesos de la red, excepto el coeficiente escalar
uno está considerando, y probar diferentes valores de este coeficiente. Digamos que el valor
inicial del coeficiente es 0,3. Después de que el pase hacia adelante en un lote de datos, la
pérdida de la red en el lote es de 0,5. Si cambia el valor del coeficiente de 0,35 y vuelva a
ejecutar el paso hacia adelante, la pérdida aumenta a 0,6. Pero si se baja el coeficiente de
0,25, la pérdida cae a 0,4. En este caso, parece que la actualización del coeficiente de -0.05
contribuiría a minimizar la pérdida. Esto tendría que ser repetido para todos los coeficientes en
la red.
Sin embargo, este enfoque sería terriblemente ineficiente, ya que había necesidad de
computar dos pasos hacia adelante (que son caros) para cada coeficiente individuales (de los
cuales hay muchos, por lo general los miles ya veces hasta millones). Un mejor enfoque es tomar
ventaja del hecho de que todas las operaciones utilizadas en la red son diferenciables, y calcular
la pendiente de la pérdida con respecto a los coeficientes de la red. A continuación, puede mover
los coeficientes en la dirección opuesta a partir del gradiente, disminuyendo así la pérdida.
Si ya sabe lo que significa diferenciables y lo que es un gradiente, puede saltar a la sección
2.4.3. De lo contrario, las dos secciones siguientes le ayudarán a entender estos conceptos.
Además, ya que la función es suave (su curva no tiene ningún ángulos abruptos), cuando
epsilon_x es lo suficientemente pequeño, alrededor de un cierto punto P, es posible f aproximada
como una función lineal de la pendiente a, de modo que epsilon_y se convierte en una *
epsilon_x:
f (x + epsilon_x) = y + a * epsilon_x
lineal local
aproximación de f,
con pendiente
una
F
Figura 2.10 Derivado de F en pags
Para cada función (medios diferenciables “se pueden derivar”: por ejemplo, liso, funciones
continuas se pueden derivar) f diferenciable (x), existe una función derivada f '(x) que mapea los
valores de x para la pendiente de la locales aproximación lineal de f en esos puntos. Por ejemplo,
el derivado de cos (x) es -sen (x), la derivada de f (x) = a * x es f '(x) = A, y así sucesivamente.
Si usted está tratando de actualización de x por un factor de epsilon_x con el fin de minimizar
f (x), y usted sabe que la derivada de f, entonces su trabajo está hecho: la derivada describe por
completo la forma f (x) evoluciona a medida que cambian x. Si desea reducir el valor de f (x),
sólo tiene que mover x un poco en la dirección opuesta a la derivada.
Si x e y se congelan las entradas de datos, entonces esto se puede interpretar como un archivo
de valores de correlación de funciones de W a valores de pérdida:
loss_value = f (W)
que hacer es encontrar todos los puntos donde la derivada va a 0 y el cheque por el cual de estos
puntos de la función tiene el valor más bajo.
Aplicada a una red neuronal, que significa encontrar analíticamente la combinación de valores de peso
que produce la función de pérdida más pequeña posible. Esto se puede hacer mediante la resolución de
la gradiente de la ecuación (f) (W) = 0 para W. Esta es una ecuación polinómica de n variables, donde N
es el número de coeficientes en la red. Aunque sería posible resolver esta ecuación para N = 2 ó N = 3,
hacerlo es insuperable para las redes neuronales reales, donde el número de parámetros nunca es menor
que unos pocos miles y, a menudo puede ser de varias decenas de millones.
En su lugar, puede utilizar el algoritmo de cuatro etapas que se describe al principio de esta sección:
modificar los parámetros poco a poco en función del valor actual pérdida de un lote aleatorio de datos.
Debido a que usted está tratando con una función diferenciable, se puede calcular su gradiente, lo que le
proporciona una manera eficiente para implementar el paso 4. Si actualiza los pesos en la dirección
opuesta a la pendiente, la pérdida será un poco menos cada vez que:
1 Dibuje un lote de la formación de x muestras y los objetivos y correspondiente.
2 Ejecutar la red de x para obtener predicciones y_pred.
3 Calcular la pérdida de la red en el lote, una medida de la falta de coincidencia entre y_pred e y.
4 Calcular el gradiente de la pérdida con respecto a los parámetros de la red (un pase hacia atrás).
5 Mover los parámetros de un poco en la dirección opuesta a la W gradiente, por ejemplo - = paso
* reducir gradiente-así la pérdida en el lote un poco.
¡Suficientemente fácil! Lo que acabo de describir se llama minibatch estocástico pendiente de descenso
(minibatch SGD). El término estocástico refiere al hecho de que cada lote de datos se extrae al azar
(estocástico es un sinónimo científico de azar). La figura 2.11 ilustra lo que sucede en 1D, cuando la red
tiene un solo parámetro y tiene sólo una muestra de entrenamiento.
t=
1
t=
2 t=
3
Como se puede ver, de manera intuitiva que es importante escoger un valor razonable para el factor de
paso. Si es demasiado pequeño, el descenso por la curva tendrá muchas iteraciones, y podría quedar
atascado en un mínimo local. Si el paso es demasiado grande, las actualizaciones pueden terminar que
le llevará a lugares completamente al azar en la curva.
Tenga en cuenta que una variante del algoritmo SGD mini-lotes sería elaborar una sola muestra y el
objetivo en cada iteración, en lugar de dibujar una serie de datos. Esto sería cierto SGD (en contraposición
a SGD mini-lotes). Alternativamente, yendo al extremo opuesto, podría ejecutar cada paso en todos los
datos disponibles, que se llama SGD por lotes. Cada actualización sería entonces más preciso, pero mucho
más caro. El compromiso eficaz entre estos dos extremos es el uso de mini-lotes de tamaño razonable.
Aunque la figura 2.11 ilustra el descenso de gradiente en un espacio de parámetros 1D, en la práctica
va a utilizar descenso de gradiente en espacios altamente dimensionales: cada coeficiente de peso en una
red neuronal es una dimensión libre en el espacio, y puede haber decenas de miles o incluso millones de
ellos. Para ayudar a construir intuición sobre superficies de pérdida, podrá también ascendencia
Visualizar gradiente a lo largo de una superficie pérdida 2D, como se muestra en la figura 2.12. Pero
usted no puede visualizar lo que el proceso real de la formación de una red neural se ve como-usted no
puede representar un espacio 1.000.000 dimensiones de una manera que tenga sentido para los seres
humanos. Como tal, es bueno tener en cuenta que las intuiciones que se desarrollan a través de estas
representaciones de baja dimensión no siempre es exacta en la práctica. Esto ha sido históricamente una
fuente de problemas en el mundo de la investigación profunda de aprendizaje.
Punto de partida
45
40
35
30
25
20
15
10
5
Figura 2.12 descenso de gradiente abajo de una
superficie pérdida 2D (dos parámetros se pueden
Punto final aprender)
Además, existen múltiples variantes de SGD que difieren teniendo en cuenta las anteriores
actualizaciones de peso cuando se calcula la próxima actualización de peso, en lugar de sólo mirar el
valor actual de los gradientes. Hay, por ejemplo, SGD con el impulso, así como Adagrad, RMSProp, y
varios otros. Tales variantes se conocen como métodos de optimización o optimizadores. En particular,
el concepto de cantidad de movimiento, que se utiliza en muchas de estas variantes, merece su atención.
Momentum aborda dos problemas con SGD: velocidad de convergencia y mínimos locales. Considere la
figura 2.13, que muestra la curva de una pérdida como una función de un parámetro de red.
Pérdi
valor
da
Local
mínimo
Global
mínimo
Como se puede ver, en torno a un determinado valor del parámetro, hay un mínimo local:
alrededor de ese punto, moviéndose de izquierda resultaría en la pérdida cada vez mayor, pero
también lo sería moverse a la derecha. Si el parámetro bajo consideración se está optimizando a
través de SGD con una tasa de aprendizaje pequeña, entonces el proceso de optimización podría
atascarse en el mínimo local en lugar de hacer su camino hacia el mínimo global.
Puede evitar estos problemas mediante el uso de un impulso, que se inspira en la física. Una
imagen mental útil aquí es pensar en el proceso de optimización como una pequeña bola rodando
por la curva de pérdida. Si tiene suficiente impulso, la pelota no se queda bloqueado en un
barranco y terminará en el mínimo global. Momentum se implementa moviendo la bola en cada
paso basado no sólo en el valor actual de la pendiente (la aceleración actual) sino también de la
velocidad de la corriente (como resultado de la aceleración pasado). En la práctica, esto significa
actualizar el parámetro w basan no sólo en el valor del gradiente actual, sino también en la
actualización de parámetros anterior, como en esta implementación ingenua:
past_velocity = 0. factor de impulso
constante impulso = 0,1
bucle de optimización
mientras que la pérdida> 0,01:
w, pérdida, gradiente = get_current_parameters ()
velocidad = past_velocity * impulso + learning_rate * gradiente
de w = w + impulso * velocidad - learning_rate * gradient
past_velocity = velocidad update_parameter (w)
Cálculo nos dice que una cadena de funciones puede derivarse usando la siguiente identidad,
llamada la regla de la cadena: f (g (x)) = f '(g (x)) * g' (x). Aplicando la regla de la cadena para
el cálculo de los valores de gradiente de una red neuronal da lugar a un algoritmo llamado
retropropagación (también llamado a veces inversa modo diferenciación). Propagación hacia
atrás comienza con el valor de pérdida final y trabaja hacia atrás desde las capas superiores a las
capas inferiores, aplicando la regla de la cadena para calcular la contribución que cada parámetro
tenía en el valor de pérdida.
Hoy en día, y en los próximos años, la gente va a implementar redes en los marcos modernos que son
capaces de diferenciación simbólica, como TensorFlow. Esto significa que, dada una cadena de
operaciones con un conocido derivado, se puede calcular una función de gradiente para la cadena
(mediante la aplicación de la regla de la cadena) que asigna valores de los parámetros de red a los valores
de gradiente. Cuando se tiene acceso a la función de este tipo a, el pase hacia atrás se reduce a una llamada
a esta función del gradiente. Gracias a la diferenciación simbólica, que nunca tendrá que aplicar el
algoritmo de retropropagación con la mano. Por esta razón, no vamos a perder su tiempo y su enfoque en
derivar la formulación exacta del algoritmo de retropropagación en estas páginas. Todo lo que necesita
es una buena comprensión de cómo funciona la optimización basada en el gradiente.
Ahora usted entiende que las imágenes de entrada se almacenan en los tensores numpy, que
están formateados como Float32 tensores de forma (60000, 784) (datos de entrenamiento) y
(10000, 784) (datos de prueba), respectivamente. Esta fue nuestra red:
red = models.Sequential () network.add (layers.Dense (512, la activación
= 'relu', input_shape = (28 * 28,))) network.add (layers.Dense (10,
activación = 'softmax'))
Ahora usted entiende que esta red consiste en una cadena de dos capas densas, que cada capa
se aplica unas pocas operaciones simples con tensores a los datos de entrada, y que estas
operaciones implican tensores de peso. tensores de peso, que son atributos de las capas, son
donde el conocimiento de las persiste la red.
Este fue el paso de la red-compilación:
network.compile (optimizador = 'rmsprop', pérdida =
'categorical_crossentropy', las métricas = [
'exactitud'])
Ahora usted entiende lo que sucede cuando se llama ajuste: la red comenzará a iterar sobre los
datos de entrenamiento en mini-lotes de 128 muestras, 5 veces más (cada iteración sobre todos
los datos de entrenamiento se llama una época). En cada iteración, la red calcular los
gradientes de los pesos con respecto a la pérdida del lote, y actualizar los pesos en
consecuencia. Después de estos 5 épocas, la red habrá realizado 2.345 cambios de gradiente