Update:2020/01/11
如果想要在 tf.keras 中使用 AdamW、SGDW 等優化器,請將 TensorFlow 升級到 2.0,之后在 tensorflow_addons 倉庫中可以找到該優化器,且可以正常使用,具體參照:【tf.keras】AdamW: Adam with Weight decay -- wuliytTaotao
Update:2019/09/21
在 TensorFlow 1.x 使用 tf.keras 時,請使用 tf.keras.optimizers 里面的優化器,不要使用 tf.train 里面的優化器,不然學習率衰減會出現問題。
使用 tf.keras 過程中,如果要使用 learning rate decay,不要使用 tf.train.AdamOptimizer() 等 tf.train 內的優化器,因為學習率的命名不同,導致 tf.keras 中學習率衰減的函數無法使用,一般都會報錯 “AttributeError: 'TFOptimizer' object has no attribute 'lr'”,這個時候即使我們對 "lr" 參數賦值,也沒有辦法在之后過程中更新真正的學習率,即學習率並沒有按照你想的那樣進行 decay。
在 tensorflow 1.10.0 中,tf.keras.optimizers 中的優化器參數命名和 tf.train 的優化器初參數命名中還不一樣,這個時候像 tf.keras 的參數命名和 Keras 一樣,使用 tf.keras.optimizers.Adam() 沒問題,但使用 tf.train.AdamOptimizer() 就沒法在 tf.keras 中學習率衰減。
在 tensorflow 1.14 中,tf.keras.optimizers 中的優化器參數命名和 tensorflow 一致了,但在初始化時都一行命令self._set_hyper('learning_rate', kwargs.get('lr', learning_rate))
,這一行命令將lr
屬性和learning_rate
屬性綁定,會一起更新,所以 tf.keras 中的優化器可以正常使用 tf.keras 中的 learning rate decay,而此時 tf.train.AdamOptimizer() 及 tf.contrib.opt.AdamWOptimizer() 等優化器還是沒法正常使用 tf.keras 中的 learning rate decay。
簡言之,在 tf.keras 要使用學習率衰減時,優化器不要選擇 tf.train 的,而是要 tf.keras 的。目前為止,兩者的轉化還不是很好,很容易出問題,發現學習率不能正常 decay 也是要了我的老命。
Update:2019/06/06
我的 tensorflow+keras 版本:
print(tf.VERSION) # '1.10.0'
print(tf.keras.__version__) # '2.1.6-tf'
tf.keras 沒有實現 AdamW,即 Adam with Weight decay。論文《DECOUPLED WEIGHT DECAY REGULARIZATION》提出,在使用 Adam 時,weight decay 不等於 L2 regularization。具體可以參見 當前訓練神經網絡最快的方式:AdamW優化算法+超級收斂 或 L2正則=Weight Decay?並不是這樣。
keras 中沒有實現 AdamW 這個 optimizer,而 tensorflow 中實現了,所以在 tf.keras 中引入 tensorflow 的 optimizer 就好。
如下所示:
import tensorflow as tf
from tensorflow.contrib.opt import AdamWOptimizer
mnist = tf.keras.datasets.mnist
(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(512, activation=tf.nn.relu),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
# adam = tf.train.AdamOptimizer()
# adam with weight decay
adamw = AdamWOptimizer(weight_decay=1e-4)
model.compile(optimizer=adamw,
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(x_train, y_train, epochs=10, validation_split=0.1)
print(model.evaluate(x_test, y_test))
如果只是像上面這樣使用的話,已經沒問題了。但是如果要加入 tf.keras.callbacks 中的某些元素,如 tf.keras.callbacks.ReduceLROnPlateau(),可能就會出現異常 AttributeError: 'TFOptimizer' object has no attribute 'lr'。
以下代碼將出現 AttributeError: 'TFOptimizer' object has no attribute 'lr',就是因為加入了 tf.keras.callbacks.ReduceLROnPlateau(),其它兩個 callbacks 不會引發異常。
import tensorflow as tf
from tensorflow.contrib.opt import AdamWOptimizer
mnist = tf.keras.datasets.mnist
(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(512, activation=tf.nn.relu),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
# 按照 val_acc 的值來保存模型的參數,val_acc 有提升才保存新的參數
ck_callback = tf.keras.callbacks.ModelCheckpoint('checkpoints/weights-improvement-{epoch:02d}-{val_acc:.2f}.hdf5', monitor='val_acc', mode='max',
verbose=1, save_best_only=True, save_weights_only=True)
# 使用 tensorboard 監控訓練過程
tb_callback = tf.keras.callbacks.TensorBoard(log_dir='logs')
# 在 patience 個 epochs 內,被監控的 val_loss 都沒有下降,那么就降低 learning rate,新的值為 lr = factor * lr_old
lr_callback = tf.keras.callbacks.ReduceLROnPlateau(patience=3)
adam = tf.train.AdamOptimizer()
# adam with weight decay
# adamw = AdamWOptimizer(weight_decay=1e-4)
model.compile(optimizer=adam,
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(x_train, y_train, epochs=10, validation_split=0.1, callbacks=[ck_callback, tb_callback, lr_callback])
print(model.evaluate(x_test, y_test))
(上述代碼在 tensorflow 1.10.0 之后的版本會出現莫名其妙的錯誤,以 tensorflow 1.14.0 舉例。)
Traceback (most recent call last):
File "/Users/wuliytTaotao/PycharmProjects/tmp/AdamOrAdamW.py", line 43, in <module>
model.fit(x_train, y_train, epochs=10, validation_split=0.1, callbacks=[ck_callback, tb_callback, lr_callback])
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/tensorflow/python/keras/engine/training.py", line 780, in fit
steps_name='steps_per_epoch')
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/tensorflow/python/keras/engine/training_arrays.py", line 363, in model_iteration
batch_outs = f(ins_batch)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/tensorflow/python/keras/backend.py", line 3292, in __call__
run_metadata=self.run_metadata)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 1458, in __call__
run_metadata_ptr)
tensorflow.python.framework.errors_impl.FailedPreconditionError: Error while reading resource variable training/beta2_power from Container: localhost. This could mean that the variable was uninitialized. Not found: Resource localhost/training/beta2_power/N10tensorflow3VarE does not exist.
[[{{node training/AdamW/update_dense/bias/ResourceApplyAdam/ReadVariableOp_1}}]]
References
當前訓練神經網絡最快的方式:AdamW優化算法+超級收斂 -- 機器之心
L2正則=Weight Decay?並不是這樣 -- 楊鎰銘
ReduceLROnPlateau with native optimizer: 'TFOptimizer' object has no attribute 'lr' #20619