keras KeyPoint检测网络中超出标准化范围的高验证损失和异常预测

e7arh2l6  于 2023-08-06  发布在  其他
关注(0)|答案(1)|浏览(120)

“大家好
我目前正在研究一个关键点检测网络,目标是预测每个关键点的正确x和y值。我遇到了预测值的问题。我已经成功地规范化了数据,确保关键点的值落在0到1的范围内。为了验证我提供给模型的数据是否正确(包括验证、训练和测试集),我使用了函数sk.show_keypoint,它们正是我所期望的。
然而,我遇到了一个问题,网络预测的值超出了预期范围。例如,我得到的预测是

[[ 1.5571796 -1.5212063 -1.5553608 1.5570908 -1.5887384 1.5819738 1.5625474 -1.5526751 -1.5711758 1.5739774 1.5815413 1.5541165 -1.5574389 -1.8088359 -1.5553869 1.5725775 1.5559578 -1.5867838 1.5536412 1.61665 -1.5670778 -1.5944076 1.5860206 1.5846121 -1.5490519 1.5757351 -1.5185088 -1.5199621]]

字符串
,它们不在预期的0到1范围内。
我已经尝试了不同的学习率(LR),我目前使用的值是:

  • 初始LR(lr_i)= 0.88
  • 最终LR(lr_f)= 0.01
  • 衰减因子(decay_f)= 39

尽管调整了LR,但问题仍然存在。我正在寻求您的帮助,了解为什么会发生这种情况,以及我如何解决它。
下面是我的代码片段以供参考:

from keras.applications import ResNet50
from tensorflow.data import TFRecordDataset
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dense, Flatten, BatchNormalization
from tensorflow.keras.optimizers import Adam, schedules
from tensorflow.keras.callbacks import EarlyStopping , LearningRateScheduler
import glob
import math
import matplotlib.pyplot as plt
import os

import lib.deserialize_example_cnn as des
import lib.show_keypoints as sk

def main(lr_i,lr_f,decay_f,bst):
    # parameters
    fs= " lr_i:"+str(lr_i)+"  lr_f:"+str(lr_f)+"  decay_f:"+str(decay_f)+"  bst:"+str(bst)
    print(fs)
    shape_image = 500
    input_shape = (shape_image,shape_image,1)
    num_classes = 28
    files_out_names = "early_stopping_shuffle_low_low_lr"
    
    dir_in = "C:/risorse/PDL/dataset_mini/"
    model_path = "C:/risorse/PDL/"
    num_epochs = 5
    batch_size_training = bst

    initial_learning_rate = lr_i
    decay_step = num_epochs*batch_size_training*decay_f
    end_learning_rate = lr_f

    dir_in_training = dir_in + "training/"
    dir_in_validation = dir_in + "validation/"
    dir_in_testing = dir_in + "testing/"

    # loading training dataset
    #print("dir_in_training:"+dir_in_training)
    filenames_train = glob.glob(dir_in_training + "*.tfrecord")
    ds_bytes = TFRecordDataset(filenames_train)
    dataset_training = ds_bytes.map(des.deserialize_example)
    dataset_training = dataset_training.shuffle(5340, reshuffle_each_iteration=True) #5340 is the seed

    # Visualizing training images
    xi = 0
    for image, label in dataset_training:
        #print(label)
        if sk.prob(1):
            draw_label = sk.inversion(label)
            sk.show_keypoints(image,draw_label,"cnn"+ str(xi)) #this is the function I've used to check the keypoint are correct
        xi += 1

    # loading validating dataset
    filename_validate = glob.glob(dir_in_validation + "*.tfrecord")
    ds_bytes = TFRecordDataset(filename_validate)
    dataset_validation = ds_bytes.map(des.deserialize_example)

    # batching data
    dataset_training = dataset_training.batch(batch_size_training)
    dataset_validation = dataset_validation.batch(1)

    # Model definition

    model = Sequential()

    resnet_model = ResNet50(include_top=False, weights=None, input_shape=input_shape)

    model.add(resnet_model)
    model.add(Flatten())
    model.add(Dense(128, activation='relu'))
    model.add(Dense(num_classes))

    lr = schedules.PolynomialDecay(
        initial_learning_rate,
        decay_step,
        end_learning_rate
    )

    callback = EarlyStopping(monitor='val_loss',mode="min",patience=2,restore_best_weights=True)
    lr_callback = LearningRateScheduler(verbose=1)
    optimizer = Adam(learning_rate=lr)

    # Compiling model
    #model.compile(loss='mse',optimizer=Adam(learning_rate = initial_learning_rate))
    model.compile(loss='mse',optimizer=optimizer)

    # Fit model
    print(fs)
    history = model.fit(dataset_training, epochs=num_epochs, batch_size=batch_size_training,callbacks=[lr_callback , callback],validation_data = dataset_validation,use_multiprocessing=True)

    model.save(model_path + "model_" + files_out_names + ".h5",save_format='h5')

    # plot graph
    x = []
    y = []
    for i in range(len(history.history['loss'])):
        x.append(i)
        y.append(history.history['loss'][i])

    # loading test dataset
    filename_test = glob.glob(dir_in_testing + "*.tfrecord")
    ds_bytes = TFRecordDataset(filename_test)
    dataset_test = ds_bytes.map(des.deserialize_example)

    # batch dataset
    dataset_test = dataset_test.batch(1)

    # Evaluate model on test dataset
    print("Evaluate on Test Dataset")
    eval_loss = model.evaluate(dataset_test)

    print("Evaluation loss:", eval_loss)
    return eval_loss


我认为修改LR可以解决这个问题,但我得到的val_loss和test_loss的最佳值是4.26。我训练了5个epoch:

Epoch 1/5
700/700 [==============================] - 54s 69ms/step - loss: 298610458624.0000 - val_loss: 4.2689
Epoch 2/5
700/700 [==============================] - 48s 68ms/step - loss: 4.1115 - val_loss: 4.2684
Epoch 3/5
700/700 [==============================] - 49s 68ms/step - loss: 4.1110 - val_loss: 4.2678
Epoch 4/5
700/700 [==============================] - 49s 69ms/step - loss: 4.1102 - val_loss: 4.2667
Epoch 5/5
700/700 [==============================] - 49s 68ms/step - loss: 4.1089 - val_loss: 4.2652

zfycwa2u

zfycwa2u1#

你有一个分类问题,所以donoforaiur建议categorical crossentropy作为损失函数是正确的。
此外,您的最后一层没有激活功能:

model.add(Dense(num_classes))

字符串
您可以使用softmax激活函数在[0,1]中获得分类预测,如下所示:

model.add(Dense(num_classes), activation='softmax')


如果目标数据不是one-hot编码的,而是标签编码的,则可以使用sparse_categorical_crossentropy作为损失函数。
如果你不想在最后一层使用softmax激活函数,你可以不激活它,在model.compile()中使用loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True)
编辑:如果没有分类问题,并且您需要输出范围为(0,1),请使用sigmoid激活函数。请注意,0和1永远不会到达这里。这样做也不是很常见,通常你只是让网络弄清楚它,然后进行线性激活,就像你的例子一样。
一般来说,如果没有激活函数,网络的输出范围就不受限制。使用正确的激活函数,可以限制输出值的范围。对于回归,你通常不希望这样做,但你可以尝试看看sigmoid是否适合你。
也可能是一个问题,你试图让网络预测14个变量,其中14个是成对连接的(x和y坐标)。这可不少您可以尝试减少网络必须预测的点的数量。

相关问题