hongfuqiang 2018-09-29
交叉验证是Data Scientist工具箱中的重要工具。它使我们能够更好地利用我们的数据。在我向您介绍使用交叉验证的五个理由之前,我想简要介绍一下交叉验证是什么,并展示一些常见的策略。
当我们使用一些数据构建机器学习模型时,我们经常将数据分成训练和验证/测试集。训练集用于训练模型,验证/测试集用于验证它以前从未见过的数据。经典方法是进行简单的80%-20%分割,有时使用不同的值,如70%-30%或90%-10%。在交叉验证中,我们进行了多次拆分。我们可以做3个,5个,10个或任何K个分割。我们可以通过很多策略来创建这些folds。
k = 4的k-fold交叉验证图
Simple K-Folds - 我们将数据分成K个部分,让我们用K = 3作为示例。如果我们的数据集中有3000个实例,我们将它分为三个部分,第1部分,第2部分和第3部分。然后我们构建三个不同的模型,每个模型在两个部分上进行训练,在第三个部分进行测试。我们的第一个模型在第1部分和第2部分进行了训练,并在第3部分进行了测试。我们的第二个模型在第1部分和第3部分进行了训练,并在第2部分进行了测等待。
Leave One Out - 这是进行交叉验证的最极端的方法。对于数据集中的每个实例,我们使用所有其他实例构建一个模型,然后在选中的实例上测试它。
分层交叉验证 - 当我们将数据分成folds时,我们希望确保每个fold都是整个数据的良好代表。最基本的例子是我们希望每个fold中不同类别的比例相同。大多数情况下,它只是随机发生,但有时,在复杂的数据集中,我们必须为每个fold强制执行正确的分布。
以下是我应该使用交叉验证的五个原因:
当我们的数据非常少时,将它分成训练和测试集可能会给我们留下一个非常小的测试集。假设我们只有100个例子,如果我们做一个简单的80-20分割,我们将在我们的测试集中得到20个实例。当我们遇到多类问题时,问题就更严重了。如果我们有10个类而且只有20个实例,那么我们每个类平均只有2个例子。只测试2个实例中的任何内容都不能得出任何真正的结论。
如果我们在这种情况下使用交叉验证,我们会构建K个不同的模型,因此我们可以对所有数据进行预测。对于每个实例,我们通过没有看到此实例的机器学习模型进行预测,因此我们在测试集中获得了100个实例。对于多类问题,我们平均每个类得到10个实例,它比2更好。
通过交叉验证,我们可以将所有100个实例用于训练和测试,同时在以前从未见过的实例中评估我们的机器学习学习算法。
如第一条所述,当我们使用我们的学习算法创建五个不同的模型并在五个不同的测试集上测试它时,我们可以对我们的算法性能更有信心。当我们对测试集进行一次评估时,我们只得到一个结果。这个结果可能是偶然的,也可能是由于某种原因而产生的偏差。通过训练5个(或10个)不同的机器学习模型,我们可以更好地理解发生了什么。假设我们训练了5个模型,我们使用精度作为我们的测量。我们可能会遇到几种不同的情况。最好的情况是,我们的所有folds精度都是相似的,比如92.0、91.5、92.0、92.5和91.8。这意味着我们的算法(和数据)是一致的,我们可以确信,通过在所有数据集上对其进行训练并将其部署到生产环境中,将会获得类似的性能。
然而,我们最终可能会遇到一个稍微不同的场景,比如92.0、44.0、91.5、92.5和91.8。这些结果看起来很奇怪。看起来我们的一个折线来自不同的分布,我们必须回去确保我们的数据是我们认为的那样。
最坏的情况是当我们的结果有很大的变化时,比如80 44 99 60 87。这里看起来我们的算法或数据(或两者)不一致,可能是我们的算法无法学习,或者我们的数据非常复杂。
通过交叉验证,我们可以得到更多的指标,并得出关于算法和数据的重要结论。
有时我们想(或不得不)建立一个模型管道来解决一些问题。以神经网络为例。我们可以创建很多层。每一层都可以使用previews层输出并学习我们数据的新表示,因此最终,它将能够产生良好的预测。我们能够训练这些不同的层,因为我们使用了反向传播算法。每一层计算其误差并将其传回前一层。
当我们做类似的事情但不使用神经网络时,我们不能以同样的方式训练它,因为我们不能总是传递一个明显的“error”(或导数)。
例如,我们可以创建一个随机森林模型来预测一些东西,在那之后,我们想做一个线性回归它将依赖于之前的预测并产生一些实数。
这里的关键部分是我们的第二个模型必须从第一个模型的预测中学习。这里的最佳解决方案是为每个模型使用两个不同的数据集。我们在数据集A上训练随机森林,然后使用数据集B进行预测。然后,我们使用数据集B预测来训练我们的第二个模型(逻辑回归),最后,我们使用数据集C来评估我们的完整解决方案。我们使用第一个模型进行预测,将它们传递给第二个模型,然后将其与ground truth进行比较。
当我们拥有有限的数据(在大多数情况下)时,我们无法真正做到这一点。而且,我们不能在同一个数据集中训练我们的两个模型,因为那样,我们的第二个模型根据我们的第一个模型已经看到的预测来学习。这些算法可能会被过度拟合,或者至少比另一组算法的结果更好。这可能会在我们的最终评估中导致不同的影响,这将很难理解。
通过使用交叉验证,我们可以像前面描述的那样对数据集进行预测,因此我们的第二个模型的输入将是对数据的真实预测,而我们的第一个模型从未见过这样的数据。
当我们对数据执行随机的训练测试分割时,我们假设我们的例子是独立的。这意味着通过了解/看到一些实例将不能帮助我们理解其他实例。然而,情况并非总是如此。
考虑一个语音识别系统。我们的数据可能包括不同的说话者说不同的词。让我们来看看语音数字识别。例如,在这个数据集中,有3个speakers和1500个录音(每个speaker 500个)。如果我们做一个随机的拆分,我们的训练和测试集将共享同一个演讲者说同样的话!当然,这将提高我们的算法性能,但一旦在一个新的speaker上测试,我们的结果将更糟。
正确的做法是分开speakers。,使用两个speakers进行训练,使用第三个speaker进行测试。然而,我们将只在一个speaker上测试我们的算法。这还不够。我们需要知道我们的算法在不同的speakers上的表现。
我们可以在speakers层面上使用交叉验证。我们将训练3个模型,每次使用一个speaker进行测试,另外两个用于训练。通过这种方式,我们能够更好地评估我们的算法(如上所述),并最终在所有speakers上构建我们的模型。
这是进行交叉验证的最常见和最明显的原因之一。大多数学习算法都需要一些参数调整。它可以是Gradient Boosting分类器中的树数,神经网络中的隐藏层大小或激活函数,SVM中的核类型等等。我们想为我们的问题找到最佳参数。我们通过尝试不同的值并选择最好的值来做到这一点。有很多方法可以做到这一点。它可以是手动搜索,网格搜索或更复杂的优化。但是,在所有这些情况下,我们不能在我们的训练测试中进行,当然也不能在我们的测试集上进行。我们必须使用第三组,验证集。
通过将我们的数据分成三组而不是两组,我们将解决之前讨论的所有相同问题,特别是如果我们没有大量数据。通过交叉验证,我们可以使用单个集合完成所有这些步骤。
交叉验证是一个非常强大的工具。它有助于我们更好地使用我们的数据,它为我们提供了有关算法性能的更多信息。在复杂的机器学习模型中,有时很容易没有足够的注意力并在管道的不同步骤中使用相同的数据。在大多数情况下,这可能会导致良好但不真实的表现,或者在其他情况下引入奇怪的副作用。当我们处理数据科学项目中的非平凡挑战时,交叉验证可以帮助我们。