私はTensorFlowを使ってニューラルネットワークを訓練しています。これが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)
ここで重要なのは、学習率の更新ルールやその減衰値を設定する方法がわからないということです。
ここでは適応学習率をどのように使用できますか?
まず第一に、tf.train.GradientDescentOptimizer
はすべてのステップですべての変数に対して一定の学習率を使うように設計されています。 TensorFlowは、 tf.train.AdagradOptimizer
および tf.train.AdamOptimizer
を含む、すぐに使用可能なアダプティブオプティマイザも提供します。これらは、ドロップイン置換として使用できます。
ただし、そうでなければVanilla勾配降下法を使用して学習率を制御する場合は、 learning_rate
コンストラクター へのtf.train.GradientDescentOptimizer
引数をTensor
オブジェクトにすることができます。これにより、各ステップの学習率に対して異なる値を計算できます。次に例を示します。
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})
あるいは、学習率を保持するスカラーtf.Variable
を作成し、学習率を変更するたびにそれを割り当てることもできます。
Tensorflowは自動的に指数関数的減衰を学習率テンソルに適用する操作を提供します: tf.train.exponential_decay
。使用されている例については、 MNISTたたみ込みモデルの例のこの行 を参照してください。次に、上記の@ mrryの提案を使用して、選択したオプティマイザのlearning_rateパラメータとしてこの変数を指定します。
注目すべき抜粋は次のとおりです。
# 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)
最小化するglobal_step=batch
パラメータに注意してください。これはオプティマイザーにトレーニングの度に 'batch'パラメーターを便利に増やすように伝えます。
勾配降下アルゴリズムでは、 初期化中 で指定できる一定の学習率が使用されます。あなたはMrryによって示された方法で様々な学習率を渡すことができます。
しかし代わりに より高度なオプティマイザ を使うこともできます。これらはより速い収束速度を持ち、状況に適応します。
これが私の理解に基づく簡単な説明です。
Adamまたは適応運動量はAdaDeltaに似たアルゴリズムです。しかし、パラメータごとに学習率を保存することに加えて、パラメータごとに運動量の変化も別々に保存します。
A 視覚化が少ない :
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))
0 < a < b < c < ...
のようにエポックの間隔に特定の学習率を設定したい場合。次に、学習率を大域ステップを条件とする条件付きテンソルとして定義し、これを最適化プログラムに通常どおりに入力します。
これはtf.cond
ステートメントをネストしてまとめることで実現できますが、テンソルを再帰的に構築する方が簡単です。
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,)
)
それを使用するには、1つのEpochにいくつのトレーニングステップがあるかを知る必要があります。そうすれば、グローバルなステップを使用して適切なタイミングで切り替え、最後に必要なエポックと学習率を定義できます。それで、[0.1, 0.01, 0.001, 0.0001]
のエポック間隔の間にそれぞれ[0, 19], [20, 59], [60, 99], [100, \infty]
の学習率が欲しいなら、私はそうするでしょう:
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)