python - machine - tensorflow neural network
¿Cómo establecer la tasa de aprendizaje adaptativo para GradientDescentOptimizer? (5)
De los documentos oficiales de tensorflow
global_step = tf.Variable(0, trainable=False)
starter_learning_rate = 0.1
learning_rate = tf.train.exponential_decay(starter_learning_rate, global_step,
100000, 0.96, staircase=True)
# Passing global_step to minimize() will increment it at each step.
learning_step = (
tf.train.GradientDescentOptimizer(learning_rate)
.minimize(...my loss..., global_step=global_step))
Estoy usando TensorFlow para entrenar una red neuronal.
Así es como estoy inicializando el
GradientDescentOptimizer
:
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)
mse = tf.reduce_mean(tf.square(out - out_))
train_step = tf.train.GradientDescentOptimizer(0.3).minimize(mse)
Lo que ocurre aquí es que no sé cómo establecer una regla de actualización para la tasa de aprendizaje o un valor de disminución para eso.
¿Cómo puedo usar una tasa de aprendizaje adaptativo aquí?
El algoritmo de descenso de gradiente utiliza la tasa de aprendizaje constante que puede proporcionar durante la inicialización . Puede pasar varias tasas de aprendizaje de la manera que Mrry muestra.
Pero en lugar de eso, también puede usar optimizadores más avanzados que tienen una tasa de convergencia más rápida y se adaptan a la situación.
Aquí hay una breve explicación basada en mi comprensión:
- El impulso helps SGD a navegar a lo largo de las direcciones relevantes y suaviza las oscilaciones en lo irrelevante. Simplemente agrega una fracción de la dirección del paso anterior a un paso actual. Esto logra la amplificación de la velocidad en la dirección correcta y suaviza la oscilación en direcciones incorrectas. Esta fracción generalmente está en el rango (0, 1). También tiene sentido usar el impulso adaptativo. Al comienzo del aprendizaje, un gran impulso solo obstaculizará su progreso, por lo que tiene sentido usar algo como 0.01 y una vez que todos los gradientes altos desaparecieron, puede usar un mayor impulso. Hay un problema con el impulso: cuando estamos muy cerca de la meta, nuestro impulso en la mayoría de los casos es muy alto y no sabe que debería disminuir. Esto puede hacer que se pierda u oscile alrededor de los mínimos.
- El gradiente acelerado de nesterov supera este problema al comenzar a reducir la velocidad temprano. En el momento, primero calculamos el gradiente y luego hacemos un salto en esa dirección amplificado por cualquier momento que hayamos tenido previamente. NAG hace lo mismo pero en otro orden: al principio hacemos un gran salto en función de nuestra información almacenada, y luego calculamos el gradiente y hacemos una pequeña corrección. Este cambio aparentemente irrelevante ofrece aceleraciones prácticas significativas.
- AdaGrad o gradiente adaptativo permite que la tasa de aprendizaje se adapte según los parámetros. Realiza actualizaciones más grandes para parámetros poco frecuentes y actualizaciones más pequeñas para uno frecuente. Debido a esto, es muy adecuado para datos dispersos (PNL o reconocimiento de imagen). Otra ventaja es que básicamente limita la necesidad de ajustar la tasa de aprendizaje. Cada parámetro tiene su propia tasa de aprendizaje y, debido a las peculiaridades del algoritmo, la tasa de aprendizaje está disminuyendo monotónicamente. Esto causa el mayor problema: en algún momento la tasa de aprendizaje es tan pequeña que el sistema deja de aprender
- AdaDelta resuelve el problema de disminuir monotónicamente la tasa de aprendizaje en AdaGrad. En AdaGrad, la tasa de aprendizaje se calculó aproximadamente como uno dividido por la suma de las raíces cuadradas. En cada etapa, agrega otra raíz cuadrada a la suma, lo que hace que el denominador disminuya constantemente. En AdaDelta, en lugar de sumar todas las raíces cuadradas pasadas, usa una ventana deslizante que permite que la suma disminuya. RMSprop es muy similar a AdaDelta
-
Adam o el momento adaptativo es un algoritmo similar a AdaDelta. Pero además de almacenar las tasas de aprendizaje para cada uno de los parámetros, también almacena los cambios de impulso para cada uno de ellos por separado.
En primer lugar,
tf.train.GradientDescentOptimizer
está diseñado para usar una tasa de aprendizaje constante para todas las variables en todos los pasos.
TensorFlow también proporciona optimizadores adaptativos
tf.train.AdagradOptimizer
para
tf.train.AdagradOptimizer
incluyen el
tf.train.AdagradOptimizer
y el
tf.train.AdamOptimizer
, y estos se pueden usar como reemplazos
tf.train.AdamOptimizer
.
Sin embargo, si desea controlar la tasa de aprendizaje con un descenso de gradiente de vainilla, puede aprovechar el hecho de que el argumento
learning_rate
para el
constructor
tf.train.GradientDescentOptimizer
puede ser un objeto
Tensor
.
Esto le permite calcular un valor diferente para la tasa de aprendizaje en cada paso, por ejemplo:
learning_rate = tf.placeholder(tf.float32, shape=[])
# ...
train_step = tf.train.GradientDescentOptimizer(
learning_rate=learning_rate).minimize(mse)
sess = tf.Session()
# Feed different values for learning rate to each training step.
sess.run(train_step, feed_dict={learning_rate: 0.1})
sess.run(train_step, feed_dict={learning_rate: 0.1})
sess.run(train_step, feed_dict={learning_rate: 0.01})
sess.run(train_step, feed_dict={learning_rate: 0.01})
Alternativamente, puede crear una
tf.Variable
escalar que contenga la tasa de aprendizaje y asignarla cada vez que desee cambiar la tasa de aprendizaje.
Si desea establecer tasas de aprendizaje específicas para intervalos de épocas como
0 < a < b < c < ...
Luego puede definir su tasa de aprendizaje como un tensor condicional, condicional en el paso global, y alimentarlo de manera normal al optimizador.
Puede lograr esto con un montón de sentencias
tf.cond
anidadas, pero es más fácil construir el tensor de forma recursiva:
def make_learning_rate_tensor(reduction_steps, learning_rates, global_step):
assert len(reduction_steps) + 1 == len(learning_rates)
if len(reduction_steps) == 1:
return tf.cond(
global_step < reduction_steps[0],
lambda: learning_rates[0],
lambda: learning_rates[1]
)
else:
return tf.cond(
global_step < reduction_steps[0],
lambda: learning_rates[0],
lambda: make_learning_rate_tensor(
reduction_steps[1:],
learning_rates[1:],
global_step,)
)
Luego, para usarlo, necesita saber cuántos pasos de capacitación hay en una sola época, para que podamos usar el paso global para cambiar en el momento adecuado y finalmente definir las épocas y las tasas de aprendizaje que desea.
Entonces, si quiero las tasas de aprendizaje
[0.1, 0.01, 0.001, 0.0001]
durante los intervalos de época de
[0, 19], [20, 59], [60, 99], [100, /infty]
respectivamente, lo haría :
global_step = tf.train.get_or_create_global_step()
learning_rates = [0.1, 0.01, 0.001, 0.0001]
steps_per_epoch = 225
epochs_to_switch_at = [20, 60, 100]
epochs_to_switch_at = [x*steps_per_epoch for x in epochs_to_switch_at ]
learning_rate = make_learning_rate_tensor(epochs_to_switch_at , learning_rates, global_step)
Tensorflow proporciona una opción para aplicar automáticamente una disminución exponencial a un tensor de velocidad de aprendizaje:
tf.train.exponential_decay
.
Para ver un ejemplo en uso, vea
esta línea en el ejemplo del modelo convolucional MNIST
.
Luego, use la sugerencia de @ mrry anterior para proporcionar esta variable como el parámetro learning_rate a su optimizador de elección.
El extracto clave a tener en cuenta es:
# Optimizer: set up a variable that''s incremented once per batch and
# controls the learning rate decay.
batch = tf.Variable(0)
learning_rate = tf.train.exponential_decay(
0.01, # Base learning rate.
batch * BATCH_SIZE, # Current index into the dataset.
train_size, # Decay step.
0.95, # Decay rate.
staircase=True)
# Use simple momentum for the optimization.
optimizer = tf.train.MomentumOptimizer(learning_rate,
0.9).minimize(loss,
global_step=batch)
Tenga en cuenta el parámetro
global_step=batch
para minimizar.
Eso le dice al optimizador que incremente de manera útil el parámetro ''lote'' para usted cada vez que entrena.