验证数据和测试数据之间到底有什么区别

数据挖掘 Python 深度学习 神经网络 数据 验证
2022-02-22 06:09:30

我在堆栈溢出时问了这个问题,并被告知这是一个更好的地方。

我对验证和测试这两个术语感到困惑,验证模型是否与测试模型相同?是否可以使用测试数据进行验证?

更让我困惑的是何时使用验证?这是模型的必要步骤吗?是否可以进行验证而不是测试?

训练数据也可以与验证数据相同吗?

您还可以判断此代码​​是否进行测试吗?这真的让我很困惑

model.fit_generator(
    training_gen(1000,25),
    steps_per_epoch=50,
    epochs=10000,
    validation_data=validation_gen(1000, 25),
    validation_steps=1,
    callbacks=[checkpoint],
    verbose=2)

model.load_weights('./temp_trained_25.h5')
BER = []
for SNR in range(5, 30, 5):
    y = model.evaluate(
        validation_gen(10000, SNR),
        steps=1
    )
    BER.append(y[1])
    print(y)
print(BER)

注意 training_gen 和 validation_gen 是:

def training_gen(bs, SNRdb = 20):
    while True:
        index = np.random.choice(np.arange(train_size), size=bs)
        H_total = channel_train[index]
        input_samples = []
        input_labels = []
        for H in H_total:
            bits = np.random.binomial(n=1, p=0.5, size=(payloadBits_per_OFDM,))
            signal_output, para = ofdm_simulate(bits, H, SNRdb)
            input_labels.append(bits[0:16])
            input_samples.append(signal_output)
        yield (np.asarray(input_samples), np.asarray(input_labels))


def validation_gen(bs, SNRdb = 20):
    while True:
        index = np.random.choice(np.arange(train_size), size=bs)
        H_total = channel_train[index]
        input_samples = []
        input_labels = []
        for H in H_total:
            bits = np.random.binomial(n=1, p=0.5, size=(payloadBits_per_OFDM,))
            signal_output, para = ofdm_simulate(bits, H, SNRdb)
            input_labels.append(bits[0:16])
            input_samples.append(signal_output)
        yield (np.asarray(input_samples), np.asarray(input_labels))

我对深度学习很陌生,似乎一切都让我感到困惑,如果我的问题看起来很垃圾和不合理,请抱歉,但如果你能帮助我弄清楚这种困惑,我将不胜感激。

提前致谢!

3个回答

通常,您首先将数据集拆分为训练集/测试集,然后如果您的模型训练过程需要验证集,您可以进一步将训练集拆分为最终的训练集和验证集。一个简单的规则是,测试集永远不会出现在您的模型开发过程中,包括在您开发数据预处理步骤(例如数据规范化器)时。

在以下情况下,您需要一个验证集:

  1. 在启用早停的情况下训练梯度提升决策树(lgbm、xgboost 等)。因为它需要在每个训练步骤之后使用验证集评估您的模型,以查看是否满足提前停止标准

  2. 训练神经网络。这是可选的,但建议您这样做,因为除了始终存在的训练分数曲线之外,您还可以获得验证分数曲线来监控您的模型是否开始过度拟合。当您使用提前停止时,这是必需的。

  3. 你正在做交叉验证。这个想法是用相同的超参数集拟合模型 N 次,但每次它使用不同的训练集和验证集。通过这种方式,您可以了解同一组超参数如何适用于不同的数据场景。

一个验证集应该只用于一个目的,所以如果你同时做 1 和 3,那么你首先将你的数据分成训练/测试集。然后在每一轮交叉验证(N 轮中),你将你的训练集分成另一个训练集和验证集。然后在训练 GBDT 模型时,再次将训练集拆分为最终训练集和验证集。您的验证集用于交叉验证。您的验证集用于 GBDT 提前停止。1st2nd1st2nd

对于您的代码,我看到两个潜在的问题:

  1. 如果您的数据来源是channel_train,那么两者train_genvalid_gen都来自同一来源,但随机生成器的选择不同。这是一个问题,因为您不能保证您的火车和您的有效数据相互不同。

  2. 你打电话给你的有效基因两次。第一次它作为我在上面提到的第 2 点的目的。第二次它应该服务于测试的目的——这就是你问的。但同样,可能不确定测试数据和训练数据不重叠。

因此,您拥有可以完成所有工作的代码,但您可能无法确保训练/有效/测试数据是互斥的。

您可以使用测试数据执行超参数优化,以查看模型管道的哪些超参数效果最佳。然后验证数据仅使用一次,以查看整个模型管道如何处理样本数据外的数据。对于此过程,测试数据集不能再次使用,因为该数据已用于选择最佳超参数。测试和验证的过程是相同的(即在样本外数据上测试模型的性能),但是应用这些概念的模型开发阶段是不同的。

这个问题证明了科学方法在 ML 世界就模型进行交流的方式中已经迷失了方向,这导致学生在进入行业工作时会感到困惑。

让我们通过足球队为即将到来的赛季训练的比喻来说明差异。

  • 大部分时间将用于训练核心技能,如传球、踢球、防守等,以及训练阵型。这是训练数据。

  • 每次练习赛结束后,球队都会与自己进行一场混战,看看球员们如何将他们的技能付诸实践。这是验证数据。

  • 最后,球队可能会与邻近的对手进行一场季前赛表演赛,看看他们对赛季开始的准备情况如何。这是测试数据。

当你在学校时,你通常会从一大堆标记数据开始,然后将其随机划分为训练、验证和测试数据集。这不一定是坏事,但它掩盖了数据集服务的不同目的。

训练数据应该便宜、丰富且多样化——这是您的模型将用于实际学习的数据。验证数据的存在是为了确保您的模型在训练过程中确实变得更好——您不想要一支擅长训练但在实际比赛中表现糟糕的足球队。测试数据是最终检查,您的模型是否可以在尽可能接近其运行时所见的条件下执行。通常,测试看起来与训练和验证非常不同——例如,您可能会在标记的输入数据上训练和验证分类器,然后在使用分类器作为输入特征源的某些下游任务上测试模型。