Considerando o código de exemplo .
Gostaria de saber como aplicar gradiente nessa rede no RNN onde existe a possibilidade de explodir gradientes.
tf.clip_by_value(t, clip_value_min, clip_value_max, name=None)
Este é um exemplo que poderia ser usado, mas onde posso apresentá-lo? Na defesa do RNN
lstm_cell = rnn_cell.BasicLSTMCell(n_hidden, forget_bias=1.0)
# Split data because rnn cell needs a list of inputs for the RNN inner loop
_X = tf.split(0, n_steps, _X) # n_steps
tf.clip_by_value(_X, -1, 1, name=None)
Mas isso não faz sentido porque o tensor _X é a entrada e não o grad que deve ser recortado?
Tenho que definir meu próprio Otimizador para isso ou existe uma opção mais simples?
fonte
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
e, em seguida, uma iteração do otimizador é feita como,optimizer.run()
mas o usooptimizer.run()
não parece funcionar neste caso?optimizer.apply_gradients(capped_gvs)
que precisa ser atribuído a algo,x = optimizer.apply_gradients(capped_gvs)
então dentro da sua sessão você pode treinar comox.run(...)
UserWarning: Converting sparse IndexedSlices to a dense Tensor with 148331760 elements. This may consume a large amount of memory.
Então, de alguma forma, meus gradientes esparsos são convertidos em densos. Alguma ideia de como superar esse problema?tf.clip_by_global_norm
, conforme sugerido por @danijarApesar do que parece ser popular, você provavelmente deseja cortar todo o gradiente por sua norma global:
Recortar cada matriz de gradiente individualmente altera sua escala relativa, mas também é possível:
No TensorFlow 2, uma fita calcula os gradientes, os otimizadores vêm de Keras e não precisamos armazenar a operação de atualização porque ela é executada automaticamente sem passá-la para uma sessão:
fonte
clip_by_global_norm()
! Isso também é descrito comothe correct way to perform gradient clipping
nos documentos do tensorflowtf.global_norm(gradients)
para ver seu alcance normal e, em seguida, cortar um pouco acima disso para evitar que outliers atrapalhem o treinamento.opt.minimize()
depois ou ligaria para algo diferente, comoopt.run()
sugerido em alguns dos comentários em outras respostas?optimizer.minimize(loss)
é apenas uma forma abreviada para calcular e aplicar gradientes. Você pode executar o exemplo em minha resposta comsess.run(optimize)
.tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op)
em uma função de experimento, seuoptimize
substituiria otrain_op
correto? No momento,train_op = optimizer.minimize(loss, global_step=global_step))
estou tentando ter certeza de ajustar de acordo ...Na verdade, isso é explicado de maneira adequada na documentação. :
E no exemplo que eles fornecem, eles usam estas 3 etapas:
Aqui
MyCapper
está qualquer função que limite seu gradiente. A lista de funções úteis (excetotf.clip_by_value()
) está aqui .fonte
opt.minimize()
depois ou ligaria para algo diferente, comoopt.run()
sugerido em alguns dos comentários em outras respostas?opt.apply_gradients(...)
a uma variável comotrain_step
por exemplo (exatamente como faria paraopt.minimize()
. E no seu loop principal você chama como de costume para treinarsess.run([train_step, ...], feed_dict)
tf.clip_by_global_norm(list_of_tensors)
).Para quem gostaria de entender a ideia de recorte gradiente (por norma):
Sempre que a norma do gradiente é maior do que um determinado limite, recortamos a norma do gradiente para que permaneça dentro do limite. Esse limite às vezes é definido como
5
.Seja o gradiente ge o max_norm_threshold seja j .
Agora, se || g || > j , nós fazemos:
g = ( j * g ) / || g ||
Esta é a implementação feita em
tf.clip_by_norm
fonte
IMO, a melhor solução é envolver seu otimizador com o decorador de estimadores do TF
tf.contrib.estimator.clip_gradients_by_norm
:Dessa forma, você só precisa definir isso uma vez e não executá-lo após cada cálculo de gradiente.
Documentação: https://www.tensorflow.org/api_docs/python/tf/contrib/estimator/clip_gradients_by_norm
fonte
O recorte de gradiente basicamente ajuda no caso de gradientes explodindo ou desaparecendo. Diga que sua perda é muito alta, o que resultará em gradientes exponenciais para fluir pela rede, o que pode resultar em valores Nan. Para superar isso, recortamos gradientes dentro de um intervalo específico (-1 a 1 ou qualquer intervalo conforme a condição).
clipped_value=tf.clip_by_value(grad, -range, +range), var) for grad, var in grads_and_vars
onde grads _and_vars são os pares de gradientes (que você calcula via tf.compute_gradients) e suas variáveis às quais eles serão aplicados.
Após o recorte, simplesmente aplicamos seu valor usando um otimizador.
optimizer.apply_gradients(clipped_value)
fonte