第一个纪元后非常快的训练

数据挖掘 喀拉斯 张量流 训练 成立之初 合作实验室
2021-09-20 23:27:59

我使用植物图像训练了一个 InceptionV3 模型。我使用了 Keras 库。开始训练时,第一个 epoch 每步耗时 29 秒,然后其他步骤每步耗时约 530 毫秒。所以这让我怀疑我的代码中是否存在错误。我检查了我的代码几次,但它的逻辑对我来说似乎是正确的。我在 Google Colab 上训练了我的模型。我想知道是否有记忆机制或我的代码包含错误。这是我的代码:

# Yields one image-target pair when called
def image_target_generator(files, labels):
assert len(files) == len(labels), 'Files and labels sizes don\'t match!'

for step in range(len(files)):
    img = cv2.imread(dataset_path + files[step])
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    item = (img, labels[step])
    yield item

# Generating batch
 def batch_generator(gen):

    batch_images = []
    batch_targets = []

    for item in gen:

      if len(batch_images) == BATCH_SIZE:
        yield batch_images, batch_targets
        batch_images = []
        batch_targets = []

      preprocessed_img = preprocess_image(item[0])
      batch_images.append(preprocessed_img)
      batch_targets.append(item[1])      

    yield batch_images, batch_targets

# Training generator
def training_generator(files, labels):

  # So that Keras can loop it as long as required
  while True:

    for batch in batch_generator(image_target_generator(files, labels)):
      batch_images = np.stack(batch[0], axis=0)
      batch_targets = keras.utils.np_utils.to_categorical(batch[1], NUM_CLASSES)
      yield batch_images, batch_targets


# Create model
def create_model():
  model = keras.applications.InceptionV3(include_top=False, input_shape= IMG_SIZE, IMG_SIZE, 3), weights='imagenet')

  new_output = keras.layers.GlobalAveragePooling2D()(model.output)
  new_output = keras.layers.Dense(NUM_CLASSES, activation='softmax') (new_output)
  model = keras.engine.training.Model(model.inputs, new_output)

  for layer in model.layers:
    layer.Trainable = True

    if isinstance(layer, keras.layers.BatchNormalization):
      layer.momentum = 0.9

  for layer in model.layers[:-50]:
    if not isinstance(layer, keras.layers.BatchNormalization):
      layer.trainable = False

  return model

# Compiling model
model = create_model()

model.compile(loss='categorical_crossentropy',optimizer=keras.optimizers.adamax(lr=1e-2), metrics=['accuracy'])

# Fitting model
model.fit_generator(
  training_generator(train_x, train_y),
  steps_per_epoch=len(train_x) // BATCH_SIZE,
  epochs = 30,
  validation_data=training_generator(test_x, test_y),
  validation_steps=len(test_x) // BATCH_SIZE
  ) 
3个回答

Keras 支持延迟执行。create_model和代码在model.compile一个训练时期之前绝对需要时才会执行。第一个 epoch 增加的时间包括根据create_model函数中的计划构建 TensorFlow 计算图。所有剩余的时期都重复使用相同的计算图,这就是它们明显更快的原因。

尽管在接受的答案中有有效点,但我认为在这种情况下它是不正确的。

提到的时间差异是在训练的第一个 epoch 和剩余的 epoch 之间。当您调用时,模型和计算图只编译一次,model.compile()这不是训练本身的一部分。

时间上的差异是由于在第一个 epoch之前和期间生成并加载到内存中的数据。Keras(或其后端)尽可能多地缓存这些数据,这意味着所有后续的 epoch 训练速度更快。

问题可能是由于 Tensorflow 对每个数据使用运行 cudnn 基准并将它们存储在缓存中的时间。这发生在第一个时期并且由于图像大小的差异。