我正在尝试学习结合VGG和Adrian Ung triplet loss的Paris6k图像的嵌入。问题在于,经过少量的迭代,在第一个时期,损失变为nan,然后精度和验证精度增加到1。
我已经尝试过降低学习率,增加批处理大小(仅由于内存导致16个),更改优化器(Adam和RMSprop),检查数据集中是否没有None值,将数据格式从'float32 '设为'float64',从而给它们增加了一些偏差并简化了模型。
这是我的代码:
base_model = VGG16(include_top = False, input_shape = (512, 384, 3))
input_images = base_model.input
input_labels = Input(shape=(1,), name='input_label')
embeddings = Flatten()(base_model.output)
labels_plus_embeddings = concatenate([input_labels, embeddings])
model = Model(inputs=[input_images, input_labels], outputs=labels_plus_embeddings)
batch_size = 16
epochs = 2
embedding_size = 64
opt = Adam(lr=0.0001)
model.compile(loss=tl.triplet_loss_adapted_from_tf, optimizer=opt, metrics=['accuracy'])
label_list = np.vstack(label_list)
x_train = image_list[:2500]
x_val = image_list[2500:]
y_train = label_list[:2500]
y_val = label_list[2500:]
dummy_gt_train = np.zeros((len(x_train), embedding_size + 1))
dummy_gt_val = np.zeros((len(x_val), embedding_size + 1))
H = model.fit(
x=[x_train,y_train],
y=dummy_gt_train,
batch_size=batch_size,
epochs=epochs,
validation_data=([x_val, y_val], dummy_gt_val),callbacks=callbacks_list)
图像为3366,其值的缩放范围为[0,1]。 该网络采用虚拟值,因为它试图从图像中学习嵌入,以使同一类别的图像之间的距离较小,而不同类别的图像之间的距离应较远,而真实类别则是训练的一部分。
我注意到我以前进行了不正确的类划分(并保留了应丢弃的图像),而且我没有nan损失问题。
我应该怎么做?
在此先感谢您的英语。
答案 0 :(得分:2)
在某些情况下,随机的NaN丢失可能是由您的数据引起的,因为如果您的批次中没有正对,您将获得NaN丢失。
正如您在Adrian Ung的笔记本中看到的那样(或在tensorflow addons三重损失中,它是相同的代码):
semi_hard_triplet_loss_distance = math_ops.truediv(
math_ops.reduce_sum(
math_ops.maximum(
math_ops.multiply(loss_mat, mask_positives), 0.0)),
num_positives,
name='triplet_semihard_loss')
除以正数对(num_positives
)的数量,这可能导致NaN。
我建议您尝试检查数据管道,以确保每个批次中至少有一对阳性对。 (例如,您可以调整triplet_loss_adapted_from_tf
中的某些代码以获取批次中的num_positives
,并检查其是否大于0。)
答案 1 :(得分:0)
尝试增加批量大小。这也发生在我身上。如上一个答案所述,网络无法找到任何num_positives。我上了250堂课,开始时就蒙受了损失。我将其增加到128/256,然后没有问题。
我看到Paris6k有15堂课或12堂课。将批次大小增加32,如果出现GPU内存,则可以尝试使用较少参数的模型。您可以使用高效B0模型进行启动。与具有138M参数的VGG16相比,它具有5.3M。