¿Qué patrones encuentran las redes neuronales?

En esta publicación quiero hablar sobre los patrones que las redes neuronales pueden encontrar. Muchas guías para principiantes se centran en la técnica de escribir código para redes neuronales, mientras que las preguntas de "lógica" (¿qué pueden hacer las redes neuronales? ¿Qué arquitecturas son más adecuadas para qué tareas y por qué?) A menudo permanecen al margen. Espero que mi publicación ayude a los principiantes a comprender mejor las capacidades de las redes neuronales. Para hacer esto, trataremos de ver cómo hacen frente a algunas tareas modelo. El código de muestra se proporcionará en python utilizando la biblioteca keras.

Tarea 1. Comencemos con una simple. Construimos una red neuronal que se aproxima al seno.

import numpy as np import matplotlib import matplotlib.pyplot as plt from keras.models import Sequential from keras.layers import Dense def get_X_y(n): X = np.random.uniform(0, np.pi, n) y = np.sin(X) return X, y n = 40 X, y = get_X_y(n) print("X shape:", X.shape) model = Sequential() model.add(Dense(6, input_dim=1, activation='relu')) model.add(Dense(4, activation='relu')) model.add(Dense(1, activation='sigmoid')) model.compile(loss='mean_squared_error', optimizer='adam', metrics=['mean_squared_error']) model.fit(X, y, epochs=1000, batch_size=4) X_test = np.linspace(start=0, stop=np.pi, num=500) print("X test shape:", X_test.shape) y_test = model.predict(X_test) font = {'weight': 'bold', 'size': 25} matplotlib.rc('font', **font) axes = plt.gca() axes.set_ylim(0, 1) plt.plot(X_test, y_test, c='green', marker='o', markersize=5) plt.title("Sinus approximated by neural network") plt.yticks(np.arange(0, 1, 0.1)) plt.grid() plt.show() 

Obtenemos el siguiente cuadro:



Como puede ver, la red neuronal hizo frente con éxito a la tarea de aproximar una función simple.

Tarea 2. Veamos cómo la red neuronal hará frente a una tarea más compleja. Ingresaremos valores de x uniformemente distribuidos en el intervalo [0, 1], e y se establecerá aleatoriamente: para x <0.6, y será una variable aleatoria que tomará el valor 0 con una probabilidad de 0.75 y 1 con una probabilidad de 0.25 (es decir, un valor aleatorio binomial con p = 0,25). Para x> 0.6, y será una variable aleatoria que tomará el valor 0 con probabilidad 0.3 y el valor 1 con probabilidad 0.7. Como una función optimizada, tomamos el error estándar.

 import numpy as np import matplotlib import matplotlib.pyplot as plt from keras.models import Sequential from keras.layers import Dense def get_X_y(n): X = np.random.uniform(0, 1, n) y0 = np.random.binomial(size=n, n=1, p=0.25) y1 = np.random.binomial(size=n, n=1, p=0.7) y = np.where(X < 0.6, y0, y1) return X, y n_inputs = 1 n_hidden1 = 100 n_hidden2 = 50 n_outputs = 1 n = 2000 X, y = get_X_y(n) print("X shape:", X.shape) model = Sequential() model.add(Dense(n_hidden1, input_dim=1, activation='relu')) model.add(Dense(n_hidden2, activation='relu')) model.add(Dense(1, activation='sigmoid')) model.compile(loss='mean_squared_error', optimizer='adam', metrics=['accuracy']) model.fit(X, y, epochs=200, batch_size=100) X_test = np.linspace(start=0, stop=1, num=100) print("X test shape:", X_test.shape) y_test = model.predict(X_test) font = {'weight': 'bold', 'size': 25} matplotlib.rc('font', **font) axes = plt.gca() axes.set_ylim(0, 1) plt.plot(X_test, y_test, c='green', marker='o', markersize=5) plt.title("Binomial distribution approximated by neural network") plt.yticks(np.arange(0, 1, 0.1)) plt.grid() plt.show() 

Obtenemos el siguiente gráfico de una red neuronal de función aproximada:



Como puede ver, la red neuronal se aproximó a la expectativa matemática de nuestra variable aleatoria y. Entonces, las redes neuronales pueden (en principio) aproximar los valores promedio de variables aleatorias que dependen de los parámetros. Por ejemplo, podemos esperar que resuelvan el siguiente problema: las personas con ingresos de hasta $ 1,000 están en promedio infelices, y las personas con ingresos superiores a $ 1,000 están en promedio felices; uno debe aprender a predecir el "nivel de felicidad" dependiendo de los ingresos. La red neuronal podrá encontrar la dependencia del nivel promedio de felicidad en los ingresos, a pesar del hecho de que entre las personas con cualquier nivel de ingresos hay tanto felices como infelices.

Problema 3. Ahora pasamos a la predicción de secuencias. Consideraremos secuencias de 0 y 1 dadas por la siguiente regla: 10 miembros - equiparablemente 0 o 1, y el undécimo es igual a 1 si el término anterior es 0, e igualmente probable 0 o 1 si el término anterior 1. Generaremos tales secuencias de longitud 11 (10 entradas miembros de secuencia y uno, el último, predecimos) y entrenarlos en nuestra red neuronal recurrente. Y después del entrenamiento, verifiquemos cómo se las arregla con la predicción de nuevas secuencias (también longitud 11).

 import numpy as np from keras.models import Sequential from keras.layers import LSTM, Dense def get_X_y(m, n): X = np.random.binomial(size=(m,n), n=1, p=0.5) y0 = np.ones(m) y1 = np.random.binomial(size=m, n=1, p=0.5) y = np.where(X[:, n-1]==0, y0, y1) X = np.reshape(X, (X.shape[0], X.shape[1], 1)) return X, y model = Sequential() model.add(LSTM(units=50)) model.add(Dense(units=1)) model.compile(optimizer = 'adam', loss = 'mean_squared_error') X_train, y_train = get_X_y(1000, 10) model.fit(X_train, y_train, epochs = 20, batch_size = 32) m_test = 12 n_test = 10 X_test, y_test = get_X_y(m_test, n_test) y_predicted = model.predict(X_test) for i in range(m_test): print("x_last=", X_test[i, n_test-1, 0], "y_predicted=", y_predicted[i, 0]) 

Veamos qué pronósticos ofrece nuestra red neuronal sobre las secuencias probadas (tendrá resultados diferentes, ya que existe una coincidencia en la elección de secuencias y en el entrenamiento de la red neuronal).

Número de secuenciaPenúltimo miembro de la secuenciaValor predicho
10 00,96
20 00,95
30 00,97
4 40 00,96
5 50 00,96
6 610,45
7 70 00,94
810,50
9 90 00,96
1010,42
1110,44
120 00,92


Como puede ver, si el penúltimo miembro de la secuencia es 0, entonces la red neuronal predice un valor cercano a 1, y si es 1, entonces un valor cercano a 0.5. Esto está cerca del pronóstico óptimo. Un ejemplo similar de "vida" podría verse así: "si hoy voy al cine, mañana almorzaré en un restaurante; si voy al teatro hoy, mañana almorzaré en cualquier lugar ". Como hemos visto, una red neuronal puede detectar patrones de este tipo y predecir un viaje a un restaurante al ir al cine (y al cine para predecir "algo intermedio").

Tarea 4. Complicamos la tarea de la red neuronal. Deje que todo sea como en el ejemplo anterior, solo el undécimo miembro de la secuencia estará determinado no por el anterior, sino por el segundo miembro de la secuencia (por la misma regla). No daremos el código aquí, ya que prácticamente no difiere del anterior. Mi experimento mostró que la red neuronal todavía encuentra un patrón, pero durante más tiempo (tuve que usar 100 épocas en lugar de 20 para el entrenamiento).
Por lo tanto, las redes neuronales pueden (nuevamente, en principio, aclarar) detectar dependencias a largo plazo (en nuestro "ejemplo de vida", pueden detectar patrones como "Voy a un restaurante hoy si estuve en una película hace una semana").

Tarea 5. Veamos cómo la red neuronal usa la información disponible para pronosticar.
Para hacer esto, realizaremos capacitación sobre secuencias de longitud 4. En total, tendremos 3 secuencias diferentes igualmente probables:

0, 0, 1, 1
0, 1, 0, 1
0, 1, 1, 0


Por lo tanto, después de la combinación inicial de 0, 0, siempre encontramos dos unidades, después de la combinación de 0, 1 es igualmente probable que encontremos 0 o 1, pero sabremos con seguridad el último número. Ahora le pediremos a nuestra red neuronal que devuelva secuencias estableciendo return_sequences = True. Como las secuencias predichas, tomamos nuestras mismas secuencias desplazadas en un paso y complementadas por cero a la derecha. Ahora ya podemos suponer lo que sucederá: en el primer paso, la red neuronal producirá un número cercano a 2/3 (ya que con una probabilidad de 2/3 el segundo término es 1), y luego para una combinación de 0, 0 producirá dos números cercanos a unidad, pero para 0, 1 primero dará un número cercano a 0.5, y luego dará un número cercano a 0 o 1, dependiendo de si obtuvimos la secuencia 0, 1, 0 o 0, 1, 1. Al final de la red neuronal siempre producirá un número cercano a 0. Verificar con el siguiente código muestra que nuestras suposiciones son correctas.

 import numpy as np from keras.models import Sequential from keras.layers import LSTM, Dense import random def get_X_y(n): X = np.zeros((n, 4)) z = np.array([random.randint(0, 2) for i in range(n)]) X[z == 0, :] = [0, 0, 1, 1] X[z == 1, :] = [0, 1, 0, 1] X[z == 2, :] = [0, 1, 1, 0] y = np.zeros((n, 4)) y[:, :3] = X[:, 1:] X = np.reshape(X, (X.shape[0], X.shape[1], 1)) y = np.reshape(y, (y.shape[0], y.shape[1], 1)) return X, y model = Sequential() model.add(LSTM(units=20, return_sequences=True)) model.add(Dense(units=1)) model.compile(optimizer = 'adam', loss = 'mean_squared_error') X_train, y_train = get_X_y(1000) model.fit(X_train, y_train, epochs = 100, batch_size = 32) X_test = np.zeros((3, 4)) X_test[0, :] = [0, 0, 1, 1] X_test[1, :] = [0, 1, 0, 1] X_test[2, :] = [0, 1, 1, 0] X_test = np.reshape(X_test, (3, 4, 1)) y_predicted = model.predict(X_test) print(y_predicted) 


A partir de este ejemplo, vemos que la red neuronal puede cambiar dinámicamente el pronóstico dependiendo de la información recibida. Haríamos lo mismo, tratando de predecir una cierta secuencia: cuando la información disponible nos permite estimar las probabilidades de resultados en el siguiente paso, predecimos con base en esta información; pero cuando descubrimos información adicional en el siguiente paso, cambiamos el pronóstico dependiendo de ello.
Entonces, si vemos que alguien viene a nosotros desde la oscuridad, entonces decimos "esta es una persona, no lo sabemos con más detalle"; Cuando comenzamos a distinguir el cabello largo en la oscuridad, decimos "esta es probablemente una mujer". Pero si después de eso consideramos que una persona tiene bigote, entonces decimos que probablemente sea un hombre (aunque con el pelo largo). Como hemos visto, una red neuronal actúa de manera similar, utilizando la totalidad de la información actualmente disponible para el pronóstico.

Entonces, observamos ejemplos simples de cómo funcionan las redes neuronales y qué patrones pueden encontrar. En general, vimos que a menudo las redes neuronales se comportan de manera bastante "razonable", haciendo predicciones cercanas a las que haría una persona. Aunque, debe tenerse en cuenta, para captar patrones simples, necesitan mucha más información que las personas.

Source: https://habr.com/ru/post/467895/


All Articles