Theano - Ejemplo de entrenamiento trivial
Theano es bastante útil en el entrenamiento de redes neuronales donde tenemos que calcular repetidamente el costo y los gradientes para lograr un óptimo. En grandes conjuntos de datos, esto se vuelve computacionalmente intensivo. Theano hace esto de manera eficiente debido a sus optimizaciones internas del gráfico computacional que hemos visto anteriormente.
Planteamiento del problema
Ahora aprenderemos cómo usar la biblioteca Theano para entrenar una red. Tomaremos un caso simple en el que comenzamos con un conjunto de datos de cuatro características. Calculamos la suma de estas características después de aplicar un cierto peso (importancia) a cada característica.
El objetivo de la capacitación es modificar los pesos asignados a cada característica para que la suma alcance un valor objetivo de 100.
sum = f1 * w1 + f2 * w2 + f3 * w3 + f4 * w4
Dónde f1, f2, ... son los valores de las características y w1, w2, ... son los pesos.
Permítanme cuantificar el ejemplo para comprender mejor el enunciado del problema. Asumiremos un valor inicial de 1.0 para cada característica y tomaremos w1 igual0.1, w2 es igual a 0.25, w3 es igual a 0.15y w4 es igual a 0.3. No hay una lógica definida para asignar los valores de peso, es solo nuestra intuición. Por lo tanto, la suma inicial es la siguiente:
sum = 1.0 * 0.1 + 1.0 * 0.25 + 1.0 * 0.15 + 1.0 * 0.3
Que suma a 0.8. Ahora, seguiremos modificando la asignación de peso para que esta suma se acerque a 100. El valor resultante actual de0.8 está muy lejos de nuestro valor objetivo deseado de 100. En términos de aprendizaje automático, definimos costcomo la diferencia entre el valor objetivo menos el valor de salida actual, típicamente al cuadrado para aumentar el error. Reducimos este costo en cada iteración calculando los gradientes y actualizando nuestro vector de pesos.
Veamos cómo se implementa toda esta lógica en Theano.
Declaración de variables
Primero declaramos nuestro vector de entrada x de la siguiente manera:
x = tensor.fvector('x')
Dónde x es una matriz unidimensional de valores flotantes.
Definimos un escalar target variable como se indica a continuación -
target = tensor.fscalar('target')
A continuación, creamos un tensor de pesos. W con los valores iniciales como se discutió anteriormente -
W = theano.shared(numpy.asarray([0.1, 0.25, 0.15, 0.3]), 'W')
Definición de la expresión de Theano
Ahora calculamos la salida usando la siguiente expresión:
y = (x * W).sum()
Tenga en cuenta que en la declaración anterior x y Wson los vectores y no simples variables escalares. Ahora calculamos el error (costo) con la siguiente expresión:
cost = tensor.sqr(target - y)
El costo es la diferencia entre el valor objetivo y la producción actual, al cuadrado.
Para calcular el gradiente que nos dice qué tan lejos estamos del objetivo, usamos el grad método de la siguiente manera -
gradients = tensor.grad(cost, [W])
Ahora actualizamos el weights vector tomando una tasa de aprendizaje de 0.1 como sigue -
W_updated = W - (0.1 * gradients[0])
A continuación, necesitamos actualizar nuestro vector de pesos utilizando los valores anteriores. Hacemos esto en la siguiente declaración:
updates = [(W, W_updated)]
Definición / invocación de la función Theano
Por último, definimos un function en Theano para calcular la suma.
f = function([x, target], y, updates=updates)
Para invocar la función anterior un cierto número de veces, creamos un for bucle de la siguiente manera:
for i in range(10):
output = f([1.0, 1.0, 1.0, 1.0], 100.0)
Como se dijo anteriormente, la entrada a la función es un vector que contiene los valores iniciales de las cuatro características; asignamos el valor de 1.0a cada función sin ningún motivo específico. Puede asignar diferentes valores de su elección y verificar si la función finalmente converge. Imprimiremos los valores del vector de peso y la salida correspondiente en cada iteración. Se muestra en el siguiente código:
print ("iteration: ", i)
print ("Modified Weights: ", W.get_value())
print ("Output: ", output)
Listado completo del programa
La lista completa de programas se reproduce aquí para su referencia rápida:
from theano import *
import numpy
x = tensor.fvector('x')
target = tensor.fscalar('target')
W = theano.shared(numpy.asarray([0.1, 0.25, 0.15, 0.3]), 'W')
print ("Weights: ", W.get_value())
y = (x * W).sum()
cost = tensor.sqr(target - y)
gradients = tensor.grad(cost, [W])
W_updated = W - (0.1 * gradients[0])
updates = [(W, W_updated)]
f = function([x, target], y, updates=updates)
for i in range(10):
output = f([1.0, 1.0, 1.0, 1.0], 100.0)
print ("iteration: ", i)
print ("Modified Weights: ", W.get_value())
print ("Output: ", output)
Cuando ejecute el programa, verá el siguiente resultado:
Weights: [0.1 0.25 0.15 0.3 ]
iteration: 0
Modified Weights: [19.94 20.09 19.99 20.14]
Output: 0.8
iteration: 1
Modified Weights: [23.908 24.058 23.958 24.108]
Output: 80.16000000000001
iteration: 2
Modified Weights: [24.7016 24.8516 24.7516 24.9016]
Output: 96.03200000000001
iteration: 3
Modified Weights: [24.86032 25.01032 24.91032 25.06032]
Output: 99.2064
iteration: 4
Modified Weights: [24.892064 25.042064 24.942064 25.092064]
Output: 99.84128
iteration: 5
Modified Weights: [24.8984128 25.0484128 24.9484128 25.0984128]
Output: 99.968256
iteration: 6
Modified Weights: [24.89968256 25.04968256 24.94968256 25.09968256]
Output: 99.9936512
iteration: 7
Modified Weights: [24.89993651 25.04993651 24.94993651 25.09993651]
Output: 99.99873024
iteration: 8
Modified Weights: [24.8999873 25.0499873 24.9499873 25.0999873]
Output: 99.99974604799999
iteration: 9
Modified Weights: [24.89999746 25.04999746 24.94999746 25.09999746]
Output: 99.99994920960002
Observe que después de cuatro iteraciones, la salida es 99.96 y después de cinco iteraciones, es 99.99, que está cerca de nuestro objetivo deseado de 100.0.
Dependiendo de la precisión deseada, puede concluir con seguridad que la red está entrenada en 4 a 5 iteraciones. Una vez finalizado el entrenamiento, busque el vector de pesos, que después de 5 iteraciones toma los siguientes valores:
iteration: 5
Modified Weights: [24.8984128 25.0484128 24.9484128 25.0984128]
Ahora puede usar estos valores en su red para implementar el modelo.