Sunteți pe pagina 1din 33
Antes de comenzar: los bloques de construcción matemáticos de redes neuronales Este capítulo trata de

Antes de comenzar: los bloques de construcción matemáticos de redes

neuronales

Este capítulo trata de

Un primer ejemplo de una red neural

Tensores y sus operaciones

Cómo aprender a través de las redes neuronales de retropropagación y descenso de gradiente

La comprensión profunda de aprendizaje requiere estar familiarizado con muchos conceptos matemáticos simples: tensores, operaciones tensor, diferenciación, descenso de gradiente, y así sucesivamente. Nuestro objetivo en este capítulo será construir su intuición acerca de estas nociones sin conseguir demasiado técnico. En particular, vamos a alejarse de la notación matemática, que puede ser una experiencia desagradable para las personas sin ningún tipo de fondo y las matemáticas no es estrictamente necesario explicar bien las cosas. Para añadir un poco de contexto para tensores y descenso de gradiente, vamos a comenzar el capítulo con un ejemplo práctico de una red neuronal. A continuación vamos a repasar todos los nuevos conceptos

Con licencia para <null>

26

CCAPÍTULO 2Antes de comenzar: los bloques de construcción matemáticos de redes neuronales

25

que se han introducido de punto por punto. Tenga en cuenta que estos conceptos serán esenciales para que usted entienda los ejemplos prácticos que vendrán en los siguientes capítulos! Después de leer este capítulo, usted tendrá una comprensión intuitiva de trabajo de redes neuronales cómo, y serás capaz de pasar a aplicaciones prácticas -que se iniciará con el capítulo 3.

Con licencia para <null>

27

Un primer vistazo a una red neuronal

2.1 Un primer vistazo a una red neuronal

Echemos un vistazo a un ejemplo concreto de una red neuronal que utiliza la biblioteca de Python Keras para aprender a clasificar los dígitos escritos a mano. A menos que ya tenga experiencia con Keras o bibliotecas similares, que no va a entender todo acerca de este primer ejemplo de inmediato. Es probable que ni siquiera han instalado Keras todavía; esta bien. En el siguiente capítulo, vamos a revisar cada elemento en el ejemplo y los explicamos en detalle. Así que no se preocupe si algunos pasos parecen arbitrarias o aspecto como magia para usted! Tenemos que empezar por alguna parte. El problema que estamos tratando de resolver aquí es clasificar las imágenes en escala de grises de dígitos escritos a mano (28 × 28 píxeles) en sus 10 categorías (0 a 9). Vamos a utilizar el conjunto de datos MNIST, un clásico en la comunidad de aprendizaje de máquina, que ha existido casi tanto tiempo como el propio campo y ha sido estudiado intensamente. Es un conjunto de 60.000 imágenes de entrenamiento, además de 10.000 imágenes de prueba, reunidos por el Instituto Nacional de Estándares y Tecnología (NIST en MNIST) en la década de 1980. Se puede pensar en “resolver” MNIST como el “Hello World” de profundo aprendizaje que es lo que se hace para comprobar que los algoritmos están funcionando como se esperaba. Como convertirse en un practicante de aprendizaje de máquinas, verá MNIST llegar una y otra vez, en trabajos científicos, publicaciones de blog, y así sucesivamente. Se pueden ver algunas muestras MNIST en la figura 2.1.

Nota sobre las clases y etiquetas

En el aprendizaje de máquina, una categoría en un problema de clasificación se llama una clase. Los puntos de datos se denominan muestras. La clase asociada con una muestra específica se denomina una etiqueta.

con una muestra específica se denomina una etiqueta. Figura 2.1 los dígitos muestra MNIST No es

Figura 2.1 los dígitos muestra MNIST

No es necesario tratar de reproducir este ejemplo en su máquina hace un momento. Si se desea, primero debe configurar Keras, que se cubre en la sección 3.3. El conjunto de datos MNIST viene precargado en Keras, en la forma de un conjunto de cuatro arrays NumPy.

Listing 2.1

Cargando el conjunto de datos MNIST en Keras

de keras.datasets mnist importación (Train_images, train_labels), (test_images, test_labels) = mnist.load_data ()

Con licencia para <null>

28

CCAPÍTULO 2Antes de comenzar: los bloques de construcción matemáticos de redes neuronales

train_images y train_labels forman el conjunto de entrenamiento, los datos que el modelo va a aprender. El modelo a continuación, se probó en el aparato de prueba, test_images y test_labels.

Las imágenes se codifican como arrays NumPy, y las etiquetas son una serie de dígitos, que van de 0 a 9. Las imágenes y etiquetas tienen una correspondencia uno-a-uno. Echemos un vistazo a los datos de entrenamiento:

>>> train_images.shape (60000, 28, 28)

>>> len (train_labels)

60000

>>> train_labels array ([5, 0, 4,

,

5, 6, 8], dtype = uint8)

Y aquí está la prueba de los datos:

>>> test_images.shape (10000, 28, 28)

>>> len (test_labels)

10000

>>> test_labels array ([7, 2, 1,

,

4, 5, 6], dtype = uint8)

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'))

El bloque de construcción básico de las redes neuronales es la capa, un módulo de procesamiento de datos que se puede considerar como un filtro para los datos. Algunos datos que entra, y sale en una forma más útil. Específicamente, las capas de extraer las representaciones de los datos alimentados en ellos-es de esperar, las representaciones que son más significativo para el problema en cuestión. La mayoría de aprendizaje profundo consiste en encadenar capas juntas simples que implementarán una forma de destilación de datos progresiva. Un modelo de profundidad de aprendizaje es como un colador para el procesamiento de datos, hecho de una sucesión de cada vez más refinados filtros de los datos capas.

Con licencia para <null>

29

Aquí, nuestra red consiste en una secuencia de dos capas densas, que están conectados densamente (también llamado totalmente conectados) capas neuronales. El segundo (y último) capa es una capa softmax 10 vías, lo que significa que devolver una matriz de 10 puntuaciones de probabilidad (sumadores a 1). Cada puntuación será la probabilidad de que la imagen dígito actual pertenece a una de nuestras clases de 10 dígitos.

Un primer vistazo a una red neuronal

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'])

Antes del entrenamiento, vamos a preproceso de los datos mediante la remodelación en la forma de las Espera de red y la ampliación de tal manera que todos los valores están en el intervalo [0, 1]. Anteriormente, nuestras imágenes de entrenamiento, por ejemplo, se almacenan en una matriz de forma (60 000, 28, 28) de tipo uint8 con valores en el intervalo [0, 255]. Nos transformamos en una matriz float32 de forma (60000, 28 * 28) con valores entre 0 y 1.

Añadir 2,4

Preparación de los datos de imagen

train_images = train_images.reshape ((60000, 28 * 28)) train_images = train_images.astype ( 'float32') / 255 test_images = test_images.reshape ((10000, 28 * 28)) test_images = test_images.astype ( 'float32') / 255

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

train_labels = to_categorical (train_labels) test_labels = to_categorical (test_labels)

Con licencia para <null>

30

CCAPÍTULO 2Antes de comenzar: los bloques de construcción matemáticos de redes neuronales

Ahora estamos listos para entrenar la red, que a su Keras se realiza a través de una llamada a la red del ajuste método que se ajustan al modelo de sus datos de entrenamiento:

>>> network.fit (train_images, train_labels, épocas = 5, batch_size = 128) época 1/5

60000/60000 [==============================] - 9s - pérdida: 0.2524 - 0.9273 ACC:

época 2/5

51328/60000 [========================> ACC: 0,9692

] - ETA: 1s - pérdida: 0,1035 -

Dos cantidades se muestran durante la formación: la pérdida de la red a través de los datos de entrenamiento, y la exactitud de la red a través de los datos de entrenamiento. Nos llegar rápidamente a una precisión de 0,989 (98.9%) en los datos de entrenamiento. Ahora vamos a ver que realiza el modelo bien en la prueba, también:

>>> test_loss, test_acc = network.evaluate (test_images, test_labels)

>>> print ( 'test_acc:', test_acc) test_acc: 0,9785

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.

Con licencia para <null>

representaciones de datos para las redes neuronales

31

2.2representaciones de datos para las redes neuronales

En el ejemplo anterior, se partió de los datos almacenados en las matrices multidimensionales numpy, también llamados tensores. En general, todos los sistemas actuales de aprendizaje de máquinas utilizan tensores como su estructura de datos básica. Los tensores son fundamentales para el campo tan fundamental que TensorFlow de Google fue nombrado después de ellos. Entonces, ¿qué es un tensor? En su esencia, un tensor es un contenedor de datos numéricos datos desde casi siempre. Por lo tanto, es un contenedor para los números. Usted puede ser ya están familiarizados con matrices, que son tensores 2D: tensores son una generalización de matrices a un número arbitrario de dimensiones (nota que en el contexto de los tensores, una dimensión a menudo se llama un eje).

2.2.1 Escalares (tensores 0D)

Un tensor que contiene solamente un número se llama un escalar (o tensor escalar, o tensor 0- dimensional, o tensor 0D). En Numpy, un float32 o número float64 es un tensor escalar (o matriz escalar). Se puede visualizar el número de ejes de un tensor Numpy a través del atributo Ndim; un tensor escalar tiene 0 ejes (Ndim == 0). El número de ejes de un tensor también se llama su rango. Aquí está un escalar Numpy:

>>> numpy importación, como NP >>> x = np.array (12)

>>> x

array (12)

>>> x.ndim

0

2.2.2 Vectores (tensores 1D)

Una serie de números se llama un vector, o tensor 1D. Un tensor de 1D se dice que tiene exactamente un eje. Lo que sigue es un vector Numpy:

>>> x = np.array ([12, 3, 6, 14])

>>> x array ([12, 3, 6, 14]) >>> x.ndim

1

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.

Con licencia para <null>

32

CCAPÍTULO 2Antes de comenzar: los bloques de construcción matemáticos de redes neuronales

2.2.3 Matrices (tensores 2D)

Un conjunto de vectores es una matriz, o tensor 2D. Una matriz tiene dos ejes (a menudo se refiere a las filas y columnas). Se puede interpretar visualmente una matriz como una cuadrícula rectangular de números. Esta es una matriz Numpy:

>>> x = np.array ([[5, 78, 2, 34, 0], [6, 79, 3, 35, 1], [7, 80, 4, 36, 2]])

>>> x.ndim

2

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.

2.2.4tensores y tensores 3D de dimensiones superiores

Si empaca tales matrices en una nueva matriz, se obtiene un tensor 3D, que se puede interpretar visualmente como un cubo de números. A continuación se presenta un tensor Numpy 3D:

>>> x = np.array ([[[5, 78, 2, 34, 0], [6, 79, 3, 35, 1], [7, 80, 4, 36, 2]], [[5, 78, 2, 34, 0], [6, 79, 3, 35, 1], [7, 80, 4, 36, 2]], [[5, 78, 2, 34, 0], [6, 79, 3, 35, 1], [7, 80, 4, 36, 2]]])

>>> x.ndim

3

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.

2.2.5 Atributos claves

Un tensor está definida por tres atributos clave:

Número de ejes (ranking)-Para ejemplo, un tensor 3D tiene tres ejes, y una matriz tiene dos ejes. Esto también se llama Ndim del tensor en Python librerías como Numpy.

Forma-Esta es una tupla de enteros que describe cuántas dimensiones tiene el tensor a lo largo de cada eje. Por ejemplo, el ejemplo de matriz anterior tiene forma (3, 5), y el ejemplo tensor 3D tiene forma (3, 3, 5). Un vector tiene una forma con un solo elemento, tal como (5,), mientras que un escalar tiene una forma vacía, ().

Tipo de datos(Normalmente llamado dtype en las bibliotecas de Python): es el tipo de los datos contenidos en el tensor; por ejemplo, el tipo de un tensor podría ser float32, uint8, float64, y así sucesivamente. En raras ocasiones, es posible que aparezca un

Con licencia para <null>

representaciones de datos para las redes neuronales

33

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

(Train_images, train_labels), (test_images, test_labels) = mnist.load_data ()

A continuación, se muestra el número de ejes de los train_images tensor, el atributo Ndim:

>>> print (train_images.ndim)

3

Aquí está su forma:

>>> print (train_images.shape) (60000, 28,

28)

Y este es su tipo de datos, el atributo dtype:

>>> print (train_images.dtype) uint8

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 ()

plt.imshow plt (dígitos, CMAP = plt.cm.binary) plt.show () Figura 2.2La cuarta muestra en nuestro conjunto de

Figura 2.2La cuarta muestra en nuestro conjunto de datos

Con licencia para <null>

34 CCAPÍTULO 2Antes de comenzar: los bloques de construcción matemáticos de redes neuronales

2.2.6La manipulación de tensores en Numpy

En el ejemplo anterior, se seleccionaron un dígito específico junto con el primer eje utilizando los train_images sintaxis [i]. Selección de elementos específicos en un tensor se llama tensor de corte. Echemos un vistazo a las operaciones de tensor sobre el tramo se puede hacer en matrices numpy. Los siguientes selecciona ejemplo dígitos # 10 a # 100 (# 100 no está incluido) y los pone en una matriz de forma (90, 28, 28):

>>> my_slice = train_images [10: 100]

>>> print (my_slice.shape) (90, 28, 28)

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:

>>> my_slice = train_images [10: 100,:,:] >>> my_slice.shape

(90, 28, 28)También equivalente a la

Equivalente a la ejemplo anterior
Equivalente a la
ejemplo anterior

>>> my_slice = train_images [10: 100, 0:28, 0:28] >>> my_slice.shape (90, 28, 28)

ejemplo anterior

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]

2.2.7 los noción de lotes de datos

En general, el primer eje (eje 0, debido a la indexación comienza en 0) en todos los tensores de datos que van a venir a través de un aprendizaje profundo será el eje de las muestras (a veces llamada la dimensión de las muestras). En el ejemplo MNIST, las muestras son imágenes de dígitos. Además, los modelos de aprendizaje profundo no procesan un conjunto de datos completo de una vez; más bien, se rompen los datos en pequeños lotes. Concretamente, aquí hay un lote de nuestros dígitos MNIST, con un tamaño de lote de 128:

lotes = [train_images: 128] Y

aquí está el siguiente lote:

Con licencia para <null>

representaciones de datos para las redes neuronales

35

lote = train_images [128: 256] y el lote de orden n:

lotes = train_images [128 * n: 128 * (n + 1)]

Al considerar tal tensor un lote, el primer eje (eje 0) se llama eje lote o dimensión del lote. Este es un término que se encontrará con frecuencia cuando se utilicen Keras y otras bibliotecas profundas-aprendizaje.

2.2.8Ejemplos del mundo real de los tensores de datos

Vamos a tensores de datos de forma más concreta con unos pocos ejemplos similares a lo que te vas a encontrar más adelante. Los datos que se va a manipular casi siempre caerá en una de las siguientes categorías:

Los datos vectorialestensores -2D de forma (muestras, características)

TimeSeries datos o datos de la secuenciatensores -3D de forma (muestras, timesteps, características)

imágenestensores -4D de forma (muestras, altura, anchura, canales) o (muestras, canales, altura, anchura)

Vídeotensores -5D de forma (muestras, marcos, altura, anchura, canales) o

(Muestras, marcos, canales, altura, anchura)

2.2.9Los datos vectoriales

Este es el caso más común. En tal un conjunto de datos, cada punto de datos único puede ser codificada como un vector, y por lo tanto un lote de datos se codifica como un tensor 2D (es decir, un conjunto de vectores), donde el primer eje es las muestras de eje y el segundo eje es el eje características. Vamos a echar un vistazo a dos ejemplos:

Un conjunto de datos actuarial de personas, donde se cuenta la edad de cada persona, código postal, y los ingresos. Cada persona puede ser caracterizado como un vector de 3 valores, y por lo tanto un conjunto de datos entero de 100.000 personas se puede almacenar en un tensor 2D de forma

(100 000, 3).

Un conjunto de datos de documentos de texto, en el que representamos cada documento por los cargos de cuántas veces aparece cada palabra en ella (de un diccionario de

20.000

palabras comunes). Cada documento se puede codificar como un vector de

20.000

valores (un cargo por palabra en el diccionario), y por lo tanto todo un conjunto

de datos de 500 documentos se puede almacenar en un tensor de forma (500, 20 000).

2.2.10 Series Temporales de datos o de datos de secuencias

Siempre que el tiempo es importante en sus datos (o la noción de orden de secuencia), que tiene sentido para almacenarlo en un tensor 3D con un eje de tiempo explícito. Cada muestra puede ser codificado como una secuencia de vectores (un tensor 2D), y por lo tanto un lote de datos se codifica como un tensor 3D (véase la figura 2.3).

Con licencia para <null>

36 CCAPÍTULO 2Antes de comenzar: los bloques de construcción matemáticos de redes neuronales

bloques de construcción matemáticos de redes neuronales Caracteristi Las timesteps Figura 2.3 Un tensor de datos
bloques de construcción matemáticos de redes neuronales Caracteristi Las timesteps Figura 2.3 Un tensor de datos
Caracteristi
Caracteristi
Las
Las

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).

2.2.11 Los datos de imagen

Imágenes típicamente tienen tres dimensiones: altura, anchura, y profundidad de color. Aunque las imágenes en escala de grises (como nuestro dígitos MNIST) tienen un solo canal de color y por lo tanto podrían ser almacenados en 2D tensores, por convención imagen tensores están siempre en 3D, con un canal de color unidimensional para imágenes en escala de grises. Un lote de 128 imágenes en escala de grises de tamaño 256 × 256 por lo tanto podría ser almacenado en un tensor de forma (128, 256, 256, 1), y un lote de 128 imágenes en color se podría almacenar en un tensor de forma (128, 256, 256, 3) (véase la figura 2.4).

Los canales de Altura Las
Los canales de
Altura
Las

Anchura

Figura 2.4A los datos de imagen 4D tensor (convención canales-primeros)

Con licencia para <null>

representaciones de datos para las redes neuronales

37

Hay dos formas de convenciones para imágenes tensores: la Convención canales-last (utilizado por TensorFlow) y la Convención canales y uno (utilizado por Teano). El marco de aprendizaje de máquinas TensorFlow, de Google, coloca el eje de profundidad de color al final: (muestras, altura, anchura, color_depth). Mientras tanto, Theano coloca el eje derecho profundidad de color después de la eje lote: (muestras, color_depth, altura, anchura). Con la convención Theano, los ejemplos anteriores se convertirían en (128, 1, 256, 256) y (128, 3, 256, 256). El marco Keras proporciona soporte para ambos formatos.

2.2.12 Los datos de vídeo

Los datos de vídeo es uno de los pocos tipos de datos del mundo real para el que necesitará tensores 5D. Un video puede ser entendido como una secuencia de tramas, cada trama de ser una imagen en color. Debido a que cada marco puede ser almacenado en un tensor 3D (altura, anchura, color_depth), una secuencia de tramas se puede almacenar en un tensor 4D (marcos, altura, anchura, profundidad color_), y por lo tanto un lote de diferentes vídeos se puede almacenar en un tensor 5D de la forma

(Muestras, marcos, altura, anchura, color_depth).

Por ejemplo, un clip de vídeo de YouTube de 60 segundos, 144 × 256 muestreado a 4 imágenes por segundo tendría 240 cuadros. Un lote de cuatro de tales clips de vídeo se almacena en un tensor de forma (4, 240, 144, 256, 3). Eso es un total de 106,168,320 valores! Si el dtype del tensor era float32, a continuación, cada valor se almacena en 32 bits, por lo que el tensor representaría 405 MB. ¡Pesado! Vídeos que encontrar en la vida real son mucho más ligeros, ya que no se almacenan en float32, y por lo general están comprimidas por un factor grande (como en el formato MPEG).

Con licencia para <null>

38 CCAPÍTULO 2Antes de comenzar: los bloques de construcción matemáticos de redes neuronales

2.3Los engranajes de redes neuronales: las operaciones tensor

Tanto como cualquier programa de ordenador puede ser en última instancia, reduce a un pequeño conjunto de operaciones binarias en las entradas binarias (AND, OR, NOR, etc.), todas las transformaciones aprendidas por las redes neuronales profundas pueden ser reducidos a un puñado de operaciones tensor aplicado a los tensores de datos numéricos. Por ejemplo, es posible añadir tensores, los tensores se multiplican, y así sucesivamente. En nuestro ejemplo inicial, estábamos construyendo nuestra red apilando capas densas en

la parte superior de uno al otro. A Keras miradas de instancia capa como esta:

keras.layers.Dense (512, activación = 'relu')

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.

2.3.1operaciones elemento a elemento

La operación relu y además son operaciones elemento a elemento: las operaciones que se aplican de forma independiente para cada entrada en los tensores se está considerando. Este medio de estas operaciones son altamente susceptibles a paralelo de forma masiva implementaciones (implementaciones vectorized, un término que proviene de la arquitectura superordenador procesador de vector desde el periodo 1970-1990). Si desea escribir una implementación de Python ingenua de una operación de elemento a elemento, se utiliza un bucle, como en esta aplicación ingenua de una operación relu elemento a elemento: def naive_relu (x):

assert

len (x.shape) ==

2

()Evitar sobrescribir el

(x): assert len (x.shape) == 2 () Evitar sobrescribir el x.copy para i en el rango

x.copy

para i en el rango (x.shape [0]):

x es un tensor 2D Numpy. x tensor de entrada.

=

para j en el rango (x.shape [1]):

x [i, j] = máx (x [i, j], 0)

Con licencia para <null>

representaciones de datos para las redes neuronales

return x

Con licencia para <null>

39

40

CCAPÍTULO 2Antes de comenzar: los bloques de construcción matemáticos de redes

neuronales

Que haga lo mismo para la adición:

def naive_add (x, y): assert len (x.shape) == 2 aserción x.shape == y.shape

y): assert len (x.shape) == 2 aserción x.shape == y.shape x = x.copy () para i

x = x.copy () para i en el rango (x.shape [0]):

para j en el rango (x.shape [1]): x [i, j] + = y [i, j] retorno x

x

NumPy.

e

y

son

tensores

2D

Evitar sobrescribir el tensor de entrada.

Según el mismo principio, se puede hacer elemento a elemento de multiplicación, resta, y así sucesivamente. En la práctica, cuando se trata de matrices numpy, estas operaciones están disponibles como welloptimized funciones integradas de numpy, que a su vez delegar el trabajo pesado a una básicas de álgebra lineal subprogramas (Blas) aplicación si tiene uno instalado (que debería). BLAS son de bajo nivel, eficientes rutinas altamente paralelas, tensor de manipulación que se implementan típicamente en Fortran o C. Así, en Numpy, se puede realizar la siguiente operación elemento a elemento, y será rápida ardiente:

importar numpy como NP

2.3.2

z =

x + y

rápida ardiente: importar numpy como NP 2.3.2 z = x + y z = np.maximum (z,

z = np.maximum (z, 0.)

Radiodifusión

Además Element-sabia

z = np.maximum (z, 0.) Radiodifusión Además Element-sabia En cuanto al elemento relu Nuestra aplicación anterior

En cuanto al elemento relu

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

Con licencia para <null>

Los engranajes de redes neuronales: las operaciones tensor

41

(32, 10), donde Y [i,:] == y para i en el rango (0, 32). En este punto, podemos proceder a añadir X e Y, debido a que tienen la misma forma.

En términos de implementación, no se crea un nuevo tensor de 2D, porque eso sería terriblemente ineficiente. La operación de repetición es completamente virtual: se da a nivel algorítmico en lugar de en el nivel de memoria. Pero el pensamiento del vector que se repite 10 veces junto a un nuevo eje es un modelo mental útil. Esto es lo que una aplicación ingenua se vería así: naive_add_matrix_and_vector def (x, y):x es un tensor 2D Numpy. assert len

(x.shape) == 2 aserción len (y.shape) assert x.shape [1] == y.shape

[0] x = x.copy ()

== 1 y es un vector Numpy. == 1

evitar

para i en el rango (x.shape

[0]):

es un vector Numpy. evitar para i en el rango (x.shape [0]): sobrescribir el tensor de

sobrescribir

el tensor de entrada.

para j en el rango (x.shape [1]):

x [i, j] + = y [j]

return x

Con la radiodifusión, generalmente puede aplicar operaciones elemento a elemento de dos

m) y el otro tiene la forma (n, n + 1,

m). La radiodifusión será entonces sucederá de forma automática para los ejes a través de

n - 1.

El siguiente ejemplo se aplica el funcionamiento máximo elemento en cuanto a dos tensores de diferentes formas a través de la difusión:

importar numpy como NP

tensores si uno tensor tiene la forma (a, b,

n, n + 1,

NP tensores si uno tensor tiene la forma (a, b, n, n + 1, x =

x = np.random.random ((64, 3, 32,

3, 32, 10). y = np.random.random ((32,

((64, 3, 32, 3, 32, 1 0). y = np.random.random ((32, z = np.maximum (x, y)

z = np.maximum (x, y)con

forma (32, 10).

x es un tensor aleatoria con 10))de forma (64,

10))

y es un tensor azar

El z de salida tiene forma (64, 3, 32, 10) como x.

2.3.3 tensor de puntos

La operación de punto, también llamado un producto tensor (que no debe confundirse con un producto elementwise) es el más común, la operación más útil tensor. Contrariamente a las operaciones elemento a elemento, que combina las entradas de los tensores de entrada. Un producto de elemento a elemento se hace con el operador * en Numpy, Keras, Teano,

y TensorFlow. dot utiliza una sintaxis diferente en TensorFlow, pero en ambos Numpy y Keras se hace usando el operador punto estándar:

Con licencia para <null>

42

CCAPÍTULO 2Antes de comenzar: los bloques de construcción matemáticos de redes neuronales

numpy importación

como np z = np.dot

(x, y)

En la notación matemática, tendría en cuenta la operación con un punto (.):

z

= x. y

Matemáticamente, ¿qué hace la operación de puntos? Vamos a empezar con el producto escalar de dos vectores x e y. Se calcula de la siguiente manera:

def

naive_vector_dot

(x,

y):

(x.shape) == 1

x e y son vectores

assert len (y.shape) == 1 aserción x.shape [0] == y.shape

assert

NumPy.

[0] z = 0. Para i en el rango (x.shape [0]):

z

z retorno

+ =

x [i] * y [i]

len

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:

importar numpy como NP

Se implementa de la siguiente manera: importar numpy como NP X es una matriz Numpy. def

X es una matriz Numpy.

def naive_matrix_vector_dot (x, y): assert len (x.shape)

== 2

assert len (y.shape) == 1 aserción x.shape [1] == y.shape [0]

y es un vector Numpy.

La primera dimensión de x debe ser el la dimensión de 0º y! para i en el

= np.zeros (x.shape [0])misma que rango (x.shape [0]):

z

para j en el rango (x.shape [1]):Esta operación devuelve un vector

de z [i] + = x [i, j] * y [j]

z retorno

0s con la misma forma como y.

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

Con licencia para <null>

Los engranajes de redes neuronales: las operaciones tensor

43

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):

X y

la aplicación ingenua: def naive_matrix_dot (x, y): X y Y a s s e r t

Y assert len (x.shape) == 2 sonassert len (y.shape) == 2

numpyassert x.shape [1] == y.shape [0]

La primera dimensión de x debe ser el misma que la dimensión de 0º y!

de x debe ser el misma que la dimensión de 0º y! Esta operación devuelve una

Esta operación devuelve una matrices de

matriz. z = np.zeros ((x.shape [0], y.shape [1])) de 0s con una forma específica. para i

en el rango (x.shape [0]): Repite las filas de x

y sobre las columnas de y.

para j en el rango (y.shape [1]):

row_x = x [i,:] column_y = y [:, j] z [i, j] = naive_vector_dot (row_x, column_y) z retorno

Para entender la compatibilidad forma de punto-producto, que ayuda a visualizar los tensores de entrada y salida mediante la alineación de ellos como se muestra en la figura 2.5.

C y.shape: ( ante )
C
y.shape:
(
ante
)

Columna de y

en la figura 2.5. C y.shape: ( ante ) Columna de y X . y =
X . y = z si si
X . y = z
si
si
Fila de x
Fila de x
u
u
x.shape: (a, b)
x.shape:
(a, b)
z.shape: (a, c) z [i, j]
z.shape:
(a, c)
z [i, j]

Figura 2.5

diagrama de

Matriz de puntos

x, y, y z se representan como rectángulos (cajas literales de coeficientes). Debido a que las filas y x y las columnas de y deben tener el mismo tamaño, se sigue que el ancho de x debe coincidir con la altura de y. Si vas en el desarrollo de nuevos algoritmos

Con licencia para <null>

44

CCAPÍTULO 2Antes de comenzar: los bloques de construcción matemáticos de redes neuronales

de aprendizaje automático, es probable que vaya a dibujar diagramas tales frecuencia.

De manera más general, se puede tomar el producto escalar entre los tensores de

dimensiones superiores, siguiendo las mismas reglas para la compatibilidad de la forma como

se describe anteriormente para el caso 2D:

(a B C D) . (D,) -> (a, b, c) (a, b,

c, d). (D, e) -> (a, b, c, e)

Y así.

2.3.4 tensor de remodelación

Un tercer tipo de tensor de operación que es esencial para entender es tensor de remodelación.

A

pesar de que no se utilizó en las capas densas en nuestro primer ejemplo de redes neuronales,

lo

usamos cuando nos preprocesado de los datos de los dígitos antes de introducirlo en nuestra

red: train_images = train_images.reshape ((60000, 28 * 28))

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.]])

>>> x = x.reshape ((2, 3))

>>> x array ([[0., 1.,

2.],

[3., 4., 5.]])

Un caso especial de remodelación que se encuentra comúnmente es la transposición. La

transposición de un medio de matriz que intercambian sus filas y sus columnas, de modo que

x [i,:] se convierte en x [:, i]:

>>> x = np.zeros ((300, 20))

de modo que x [i,:] se convierte en x [:, i]: >>> x = np.zeros ((300,

Con licencia para <null>

Los engranajes de redes neuronales: las operaciones tensor Crea una matriz de todos los ceros de forma (300, 20)

>>> x = np.transpose (x) >>> print (x.shape) (20, 300)

45

2.3.5Interpretación geométrica de las operaciones del tensor

Debido a que los contenidos de los tensores manipulados por tensor de operaciones pueden ser interpretadas como coordenadas de puntos en algún espacio geométrico, todas las operaciones de tensor tienen una interpretación geométrica. Por ejemplo, consideremos adición. Vamos a empezar con el siguiente vector:

A = [0,5, 1]

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.

U 1 [0.5, 1] 1
U
1
[0.5, 1]
1

Figura 2.6

Un punto en un espacio 2D

U 1 [0.5, 1] 1
U
1
[0.5, 1]
1

Figura 2.7

Un punto en un espacio 2D

representado como una flecha

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 si 1
A + B
1 U
si
1

Figura 2.8

geométrica de la suma de dos vectores

Interpretación

Con licencia para <null>

46

CCAPÍTULO 2Antes de comenzar: los bloques de construcción matemáticos de redes neuronales

En, operaciones geométricas elementales generales, tales como transformaciones afines, rotaciones, escalado, y así sucesivamente se puede expresar como operaciones tensor. Por ejemplo, una rotación de un vector 2D por un ángulo theta se puede lograr a través de un

producto de punto con un 2 × 2 matriz R = [u, v], donde u y v son ambos vectores del plano:

u = [cos ( theta),

sen (theta)] y v = [-sen (theta), cos (theta)].

2.3.6Una interpretación geométrica de aprendizaje profundo

Que acaba de aprender que las redes neurales consisten enteramente en cadenas de tensor de operaciones y que todas estas operaciones tensores son simplemente transformaciones geométricas de los datos de entrada. De ello se desprende que se puede interpretar una red neuronal como muy compleja transformación geométrica en un espacio de alta dimensión, implementado a través de una larga serie de pasos simples. En 3D, la siguiente imagen mental puede resultar útil. Imaginemos dos hojas de papel de colores: uno rojo y otro azul. Poner una encima de la otra. Ahora les arrugue juntos en una

pequeña bola. Esa bola de papel arrugado es los datos de entrada, y cada hoja de papel es una clase de datos en un problema de clasificación. Lo que una red neuronal (o cualquier otro modelo de aprendizaje automático) está destinado a hacer es encontrar una transformación de

la bola de papel que uncrumple que, a fin de hacer las dos clases limpiamente separables de

nuevo. Con el aprendizaje profundo, esto se implementa como una serie de transformaciones simples del espacio 3D, como las que se podría aplicar en la bola de papel con los dedos, un movimiento a la vez.

en la bola de papel con los dedos, un movimiento a la vez. Figura 2.9 complicado

Figura 2.9

complicado colector de datos

un Uncrumpling

Uncrumpling bolas de papel es lo que la máquina de aprendizaje es acerca de: la búsqueda de representaciones aseado para complejos, colectores de datos altamente plegadas. En este punto, usted debe tener una muy buena intuición para sobresale de aprendizaje por qué profundidad en esto: se toma el enfoque de descomponer de forma incremental una transformación geométrica complicada en una larga cadena de los elementales, que es más o menos la estrategia de un ser humano seguiría hasta una bola de papel uncrumple. Cada capa en una red profunda se aplica una transformación que desenreda los datos un poco y una profunda pila de capas marcas tratable un proceso de desenmarañado extremadamente complicado.

Con licencia para <null>

Los engranajes de redes neuronales: las operaciones tensor

2.4 El motor de las redes neuronales:

47

optimización basada en gradiente

Como se vio en la sección anterior, cada capa neuronal de nuestro primer ejemplo de red transforma sus datos de entrada de la siguiente manera:

salida = relu (punto (W, de entrada) + b)

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

Con licencia para <null>

48

CCAPÍTULO 2Antes de comenzar: los bloques de construcción matemáticos de redes neuronales

0,25, la pérdida cae a 0,4. En este caso, parece que la actualización del coeficiente de -0.05

Con licencia para <null>

El motor de las redes neuronales: optimización basada en gradiente

49

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.

2.4.1 Lo que es un derivado?

Considere un continuo, liso función f (x) = y, la asignación de un número real x a un nuevo

número real y. Debido a que la función es continua, un pequeño cambio en x sólo puede llevar

a un pequeño cambio en y-esa es la intuición detrás de continuidad. Digamos que aumenta x por un pequeño factor de epsilon_x: esto da lugar a un pequeño cambio a epsilon_y y:

f (x + epsilon_x) = y + epsilon_y

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

Obviamente, esta aproximación lineal es válida sólo cuando x es lo suficientemente cerca de p. La pendiente a se llama la derivada de f en p. Si a es negativa, significa que un cambio pequeño de x alrededor de p resultará en una disminución de f (x) (como se muestra en la figura 2.10); y si a es positivo, un pequeño cambio en x se traducirá en un aumento de f (x). Además, el valor absoluto de un (la magnitud de la derivada) le indica la rapidez con este aumento o disminución sucederán.

F
F

lineal local aproximación de f, con pendiente

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

Con licencia para <null>

50 CCAPÍTULO 2Antes de comenzar: los bloques de construcción matemáticos de redes neuronales

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.

2.4.2 Derivado de una operación de tensor: el gradiente

Un gradiente es la derivada de una operación de tensor. Es la generalización del concepto de derivados para funciones de las entradas multidimensionales: es decir, a las funciones que toman como entradas tensores. Considérese un vector de entrada x, una matriz W, un objetivo y, y una pérdida de función de pérdida. Se puede utilizar para calcular W candidato objetivo y_pred, y calcular la pérdida o falta de coincidencia, entre el candidato de destino y el objetivo y_pred y:

y_pred = punto (W, x) loss_value = pérdida (y_pred,

y)

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)

Digamos que el valor actual de W es W0. Entonces la derivada de f en el punto W0 es un gradiente tensor (f) (W0) con la misma forma que W, donde cada gradiente coeficiente (f) (W0) [i, j] indica la dirección y la magnitud del cambio en loss_value se observa cuando se modifica W0 [i, j]. Eso gradiente tensor (f) (W0) es el gradiente de la función f (W) = loss_value en W0. Usted vio anteriormente que la derivada de una función f (x) de un único coeficiente puede ser interpretado como la pendiente de la curva de f. Del mismo modo, gradiente (f) (W0) puede interpretarse como el tensor de describir la curvatura de f (W) alrededor de W0. Por esta razón, casi de la misma manera que, para una función f (x), puede reducir el valor de f (x) moviendo poco xa en la dirección opuesta a la derivada, con una función f (W) de una tensor, puede reducir f (W) moviendo W en la dirección opuesta a partir del gradiente: por ejemplo, W1 = W0 - paso * gradiente (f) (W0) (donde el paso es un pequeño factor de escala). Eso significa ir en contra de la curvatura, que intuitivamente debe poner a bajar en la curva. Tenga en cuenta que se necesita el paso factor de escala debido a gradiente (f) (W0) sólo se aproxima a la curvatura cuando se está cerca de W0, por lo que no quiere estar demasiado lejos de W0.

2.4.3 descenso de gradiente estocástico

Dada una función diferenciable, es teóricamente posible encontrar su mínimo analítica: se sabe que el mínimo de una función es un punto donde la derivada es 0, por lo que todo lo que tiene

Con licencia para <null>

El motor de las redes neuronales: optimización basada en gradiente

51

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.

Pérdi Paso, también llamada tasa de valor Comenza punto (t = 0) t = t
Pérdi
Paso, también llamada tasa de
valor
Comenza
punto (t = 0)
t =
t =
t =
Parámetro

pérdida de 1D valor

Figura 2.11

curva (un parámetro learnable)

SGD por una

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.

Con licencia para <null>

52 CCAPÍTULO 2Antes de comenzar: los bloques de construcción matemáticos de redes neuronales

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 Punto final
Punto de partida
45
40
35
30
25
20
15
10
5
Punto final

Figura 2.12

superficie pérdida 2D (dos parámetros se pueden aprender)

descenso de gradiente abajo de una

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.

Con licencia para <null>

El motor de las redes neuronales: optimización basada en gradiente

Pérdi valor
Pérdi
valor
Local mínimo Global mínimo
Local
mínimo
Global
mínimo

Parámetro Figura 2.13 un mínimo local valor y un mínimo global

53

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.

constante impulso =

ingenua: past_velocity = 0. constante impulso = 0,1 mientras que la pérdida> 0,01: factor de impulso

0,1

mientras que la pérdida> 0,01:

factor de impulso

bucle de optimización

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)

2.4.4Encadenamiento de derivados: el algoritmo de retropropagación

En el algoritmo anterior, asumimos que casualmente porque una función es diferenciable, podemos calcular explícitamente su derivado. En la práctica, una función de red neural consta de muchas operaciones tensor encadenados juntos, cada uno de los cuales tiene una simple, conocido derivado. Por ejemplo, este es un f red compuesta de tres operaciones de tensor, a, b, y c, con el peso matrices de W1, W2, W3 y:

f (W1, W2, W3) = a (W1, b (W2, c (W3)))

Con licencia para <null>

54 CCAPÍTULO 2Antes de comenzar: los bloques de construcción matemáticos de redes neuronales

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.

Con licencia para <null>

55

Mirando hacia atrás en nuestro primer ejemplo

2.5Mirando hacia atrás en nuestro primer ejemplo

Usted ha llegado al final de este capítulo, y que ahora debe tener un conocimiento general de lo que está pasando detrás de las escenas en una red neuronal. Volvamos al primer ejemplo y revisar cada parte de ella a la luz de lo que ha aprendido en las tres secciones anteriores. Esto era los datos de entrada:

(Train_images, train_labels), (test_images, test_labels) = mnist.load_data ()

train_images = train_images.reshape ((60000, 28 * 28)) train_images = train_images.astype ( 'float32') / 255 test_images = test_images.reshape ((10000, 28 * 28)) test_images = test_images.astype ( 'float32') / 255

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 que categorical_crossentropy es la función de pérdida que se utiliza como señal de realimentación para el aprendizaje de los tensores de peso y que la fase de entrenamiento intentará reducir al mínimo. También sabe que esta reducción de la pérdida que ocurre a través de descenso de gradiente estocástico minibatch. Las reglas exactas que rigen un uso específico de descenso de gradiente se definen por el optimizador rmsprop pasado como primer argumento. Por último, este fue el bucle de formación: network.fit (train_images, train_labels, épocas = 5, batch_size = 128)

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

Con licencia para <null>

56 CCAPÍTULO 2Antes de comenzar: los bloques de construcción matemáticos de redes neuronales

(469 por época), y la pérdida de la red será suficientemente baja para que la red será capaz de clasificar dígitos escritos a mano con alta precisión. En este punto, usted ya sabe la mayoría de lo que hay que saber acerca de las redes neuronales.

Con licencia para <null>

Mirando hacia atrás en nuestro primer ejemplo

en del capítulo

Aprendizaje significa encontrar una combinación de los parámetros del modelo que minimiza una función de pérdida para un determinado conjunto de muestras de datos de entrenamiento y sus objetivos correspondientes.

El aprendizaje ocurre mediante la elaboración lotes al azar de muestras de datos

y sus objetivos, y calculando el gradiente de los parámetros de red con respecto la pérdida en el lote. Los parámetros de red se mueven entonces un bit (la magnitud del movimiento se define por la tasa de aprendizaje) en la dirección opuesta a la del gradiente.

Todo el proceso de aprendizaje se hace posible por el hecho de que las redes neuronales son cadenas de operaciones tensores diferenciables, y por lo tanto es osible aplicar la regla de la cadena de derivación para hallar la función gradiente de mapeo de los parámetros actuales y lote actual de datos a un valor de gradiente.

Dos conceptos clave que verá con frecuencia en capítulos futuros son la pérdida

y optimizadores. Estas son las dos cosas que hay que definir antes de comenzar

a alimentación de datos en una red.

La pérdida es la cantidad que va a intentar minimizar durante el entrenamiento, or lo que debe representar una medida del éxito de la tarea que estamos tratando de resolver.

Los optimizador especifica la manera exacta en la que se utilizará el gradiente de

a pérdida de parámetros de actualización: por ejemplo, podría ser el optimizador RMSProp, SGD con ímpetu, y así sucesivamente.

Con licencia para <null>

57