0

我目前正在开展一个项目,该项目需要我在使用 Tensorflow 进行训练期间更改模型架构的一半。添加了新的权重,并删除了其他权重。该模型需要重新编译,以便优化器识别新的权重并为它们计算梯度。

但是我注意到,在编译网络后,损失仅在再次下降后才飙升(见此处)在编译后的第一步中,损失仍然与以前一样低,但它会迅速增加。 这个问题与我的类似,但只说你应该

使用来自先前训练的列表(手动或从 Callback 获得)初始化第二次训练验证准确度。

但我找不到任何关于如何做到这一点的资源。我的尝试包括:

  • 使用 SGD 代替 Adam,因为它不应该依赖于之前的状态
  • model.fit()添加上一次通话的历史记录
  • 设置model._train_counter为在上一次调用中执行的 epoch 数
  • 以上所有结合

我使用来自https://www.tensorflow.org/datasets/keras_example的修改示例重新创建了问题,并增加了网络复杂性,因为尖峰的高度似乎随着网络规模的增加而增加:

import tensorflow as tf
import tensorflow_datasets as tfds
import matplotlib.pyplot as plt
(ds_train, ds_test), ds_info = tfds.load(
    'cifar10',
    split=['train', 'test'],
    shuffle_files=True,
    as_supervised=True,
    with_info=True,
)

def normalize_img(image, label):
  """Normalizes images: `uint8` -> `float32`."""
  return tf.cast(image, tf.float32) / 255., label

ds_train = ds_train.map(
    normalize_img, num_parallel_calls=tf.data.experimental.AUTOTUNE)
ds_train = ds_train.cache()
ds_train = ds_train.shuffle(ds_info.splits['train'].num_examples)
ds_train = ds_train.batch(256)
ds_train = ds_train.prefetch(tf.data.experimental.AUTOTUNE).repeat()

ds_test = ds_test.map(
    normalize_img, num_parallel_calls=tf.data.experimental.AUTOTUNE)
ds_test = ds_test.batch(256)
ds_test = ds_test.cache()
ds_test = ds_test.prefetch(tf.data.experimental.AUTOTUNE)

#%% Define Model    
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(512,activation='relu'),
  tf.keras.layers.Dense(256,activation='relu'),
  tf.keras.layers.Dense(128,activation='relu'),
  tf.keras.layers.Dense(128,activation='relu'),
  tf.keras.layers.Dense(10)
])


#%% First compilation
model.compile(
    optimizer=tf.keras.optimizers.Adam(0.001),
    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    metrics=[tf.keras.metrics.SparseCategoricalAccuracy()],
)

history1 = model.fit(
    ds_train,
    epochs=8,
    steps_per_epoch=300,
    validation_data=ds_test,
)

#%% Compile again
model.compile(
    optimizer=tf.keras.optimizers.Adam(),
    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    metrics=[tf.keras.metrics.SparseCategoricalAccuracy()],
)

history2 = model.fit(
    ds_train,
    epochs=10,
    steps_per_epoch=1,
    validation_data=ds_test,
)
#%% plot results
plt.plot(history1.history['loss']+history2.history['loss'])
plt.show()

是结果图。在此示例中,我没有更改网络,而是使用不同的优化器进行编译,无论您选择哪种组合,我都测试了损失峰值。(如果您在不更改模型的情况下使用 model.optimizer 进行编译,损失不会增加,这让我觉得我必须更改优化器。但是 SGD 也不起作用,这让我感到困惑)

model.fit()这与使用另一个调用恢复后恢复模型训练的问题相同。

我正在使用 TensorFlow 2.5.0 版

有关如何解决或解决此问题的任何想法?

4

1 回答 1

0

更新:我没有解决问题,但使用学习率计划解决了这个问题,该计划在编译步骤后才慢慢开始再次增加。这可以防止模型离开已经存在的局部最小值。

如果您有类似的问题,您可以尝试编译模型,model.compile(...,run_eagerly=True)以便训练 TensorFlow 不会计算计算图。这意味着您不必在更改架构后重新编译模型。它对我不起作用,但我有一个非常具体的架构。

于 2021-11-15T11:24:15.600 回答