CORE CONCEPT------Cross-Validation

Motivation

根据特定数据集训练模型很容易,但是在引入新数据时该模型如何执行? 你怎么知道使用哪种机器学习模型? 交叉验证通过确保模型产生准确结果并将这些结果与其他模型进行比较来回答这些问题。交叉验证超越了常规验证,即通过评估模型对新数据的处理方式,分析模型如何对其自己的训练数据进行的过程。 以下各节将讨论几种不同的交叉验证方法:

Holdout Method

保持交叉验证方法涉及移除训练数据的某一部分并将其用作测试数据。 首先针对训练集训练模型,然后要求预测测试集的输出。 这是最简单的交叉验证技术形式,如果您有大量数据或需要快速,轻松地实现验证,这将非常有用。

通常,保持方法涉及将数据集分成20-30%的测试数据,其余的作为训练数据。 这些数字可能会有所不同 - 较大比例的测试数据会使您的模型更容易出错,因为它具有较少的培训经验,而较小百分比的测试数据可能会使您的模型对培训数据产生不必要的偏差。 缺乏训练或偏见会导致我们模型的欠拟合/过度拟合。

K-Fold Cross Valienation

K-fold交叉验证通过在数据集的k个子集上重复保持方法,帮助从模型中消除这些偏差。 通过K-Fold交叉验证,数据集可以分解为几个独特的测试和训练数据。 使用每个数据组合执行保持方法,并且对结果求平均以找到总误差估计。

这里的“折叠”是测试数据的唯一部分。 例如,如果您有100个数据点并使用10个折叠,则每个折叠包含10个测试点。 K-fold交叉验证非常重要,因为它允许您使用完整的数据集进行培训和测试。 在使用小型或有限数据集评估模型时,它尤其有用。

Leave-P-Out / Leave-One-Out Cross Validation

Leave-P-Out交叉验证(LPOCV)通过在模型上使用P测试数据点的每种可能组合来测试模型。 举个简单的例子,如果你有4个数据点并使用2个测试点,模型将按如下方式进行训练和测试:

“T”是测试点,“ - ”是训练点。 以下是LPOCV的另一个可视化:

LPOCV可以提供极其准确的误差估计,但可以快速成为大型数据集的详尽信息。 模型必须使用LPOCV进行的测试迭代量可以使用数学组合n C P来计算,其中n是我们的数据点总数。 例如,我们可以看到,使用10个点和3个测试点的数据集运行LPOCV将需要10 C 3 = 120次迭代。

因此,Leave-One-Out交叉验证(LOOCV)是一种常用的交叉验证方法。 它只是LPOCV的一个子集,P为1.这使我们能够以与数据点相同的步数来评估模型。 LOOCV也可以看作K-Fold交叉验证,其中折叠数等于数据点的数量。

与K-Fold交叉验证类似,LPOCV和LOOCV使用完整数据集训练模型。 当您使用小型数据集时,它们特别有用,但会产生性能折衷。

Conclusion

交叉验证是一种根据新数据验证模型的方法。 最有效的交叉验证形式包括针对数据集重复测试模型,直到每个点或点组合都用于验证模型,尽管这会带来性能权衡。 我们讨论了分割数据集以进行交叉验证的几种方法:

*保持方法:将一定百分比的数据拆分为测试数据
*K-Fold方法:将数据划分为多个部分,每个部分用作测试/训练拆分
*Leave-P-Out方法:使用多个点(P)的每个组合作为测试数据

Code Examples

提供的代码显示了如何使用Scikit-Learn(一种Python机器学习库)使用三种讨论的交叉验证方法来分割一组数据。

holdout.py使用Holdout方法分割一组样本糖尿病数据。 在scikit-learn中,这是使用名为train_test_split()的函数完成的,该函数将一组数据随机分成两部分:

# An example of the Holdout Cross-Validation split

import pandas
from sklearn import datasets
from sklearn.model_selection import train_test_split

# The percentage (as a decimal) of our data that will be training data
TRAIN_SPLIT = 0.7

# The diabetes dataset contains the following columns:
columns = [
    'age', 'sex', 'bmi', 'map', 'tc', 'ldl', 'hdl', 'tch', 'ltg', 'glu'
]

# Load the diabetes dataset
dataset = datasets.load_diabetes()

# Create a pandas DataFrame from the diabetes dataset
dataframe = pandas.DataFrame(dataset.data, columns=columns)

# Split via the holdout method
x_train, x_test, y_train, y_test = train_test_split(
    dataframe, dataset.target, train_size=TRAIN_SPLIT, test_size=1-TRAIN_SPLIT)

print("""\
The holdout method removes a certain portion of the training data and uses it as test data.
Ideally, the data points removed are random on each run.
The following output shows a set of sample diabetes data split into test and training data:
""")

# Print our test and training data
print("Total diabetes data points: {}".format(len(dataframe.index)))
print("# of training data points: {} (~{}%)".format(len(x_train), TRAIN_SPLIT*100))
print("# of test data points: {} (~{}%)\n".format(len(x_test), (1-TRAIN_SPLIT)*100))

print("If you'd like to see the actual data points, uncomment the print statements at the bottom of this script.")
# print("Training data:\n{}\n".format(x_train))
# print("Test data:\n{}".format(x_test))

请注意,您可以通过更改顶部的TRAIN_SPLIT值来更改用于培训的数据部分。 这应该是从0到1的数字。此文件的输出显示用于拆分的训练和测试点的数量。 查看实际数据点可能是有益的 - 如果您想查看这些数据点,请取消注释脚本中的最后两个打印语句。

 k-fold.py使用K-Fold方法分割一组数据。 这是通过创建一个使用要分割的数量初始化的KFold对象来完成的。 Scikit-learn可以通过调用KFold的split()方法轻松分割数据:

# An example of K-Fold Cross Validation split

import numpy
from sklearn.model_selection import KFold

# Configurable constants
NUM_SPLITS = 3

# Create some data to perform K-Fold CV on
data = numpy.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]])

# Perform a K-Fold split and print results
kfold = KFold(n_splits=NUM_SPLITS)
split_data = kfold.split(data)

print("""\
The K-Fold method works by splitting off 'folds' of test data until every point has been used for testing.
The following output shows the result of splitting some sample data.
A bar displaying the current train-test split as well as the actual data points are displayed for each split.
In the bar, "-" is a training point and "T" is a test point.
""")

print("Data:\n{}\n".format(data))
print('K-Fold split (with n_splits = {}):\n'.format(NUM_SPLITS))

for train, test in split_data:
    output_train = ''
    output_test = ''

    bar = ["-"] * (len(train) + len(test))

    # Build our output for display from the resulting split
    for i in train:
        output_train = "{}({}: {}) ".format(output_train, i, data[i])

    for i in test:
        bar[i] = "T"
        output_test = "{}({}: {}) ".format(output_test, i, data[i])

    print("[ {} ]".format(" ".join(bar)))
    print("Train: {}".format(output_train))
    print("Test:  {}\n".format(output_test))

返回值是一系列列车和测试点。 请注意,您可以通过更改脚本顶部的关联值来播放拆分数。 此脚本不仅输出训练/测试数据,还输出一个不错的栏,您可以在其中跟踪当前折叠的进度:

leave-p-out.py使用Leave-P-Out和Leave-One-Out方法拆分一组数据。 这是通过创建LeavePOut / LeaveOneOut对象来完成的,LPO使用要分割的数量进行初始化。 与KFold类似,使用split()方法创建列车测试数据拆分:

# Example of LOOCV and LPOCV splitting

import numpy
from sklearn.model_selection import LeaveOneOut, LeavePOut

# Configurable constants
P_VAL = 2


def print_result(split_data):
    """
    Prints the result of either a LPOCV or LOOCV operation
    Args:
        split_data: The resulting (train, test) split data
    """
    for train, test in split_data:
        output_train = ''
        output_test = ''

        bar = ["-"] * (len(train) + len(test))

        # Build our output for display from the resulting split
        for i in train:
            output_train = "{}({}: {}) ".format(output_train, i, data[i])

        for i in test:
            bar[i] = "T"
            output_test = "{}({}: {}) ".format(output_test, i, data[i])
            
        print("[ {} ]".format(" ".join(bar)))
        print("Train: {}".format(output_train))
        print("Test:  {}\n".format(output_test))


# Create some data to split with
data = numpy.array([[1, 2], [3, 4], [5, 6], [7, 8]])

# Our two methods
loocv = LeaveOneOut()
lpocv = LeavePOut(p=P_VAL)

split_loocv = loocv.split(data)
split_lpocv = lpocv.split(data)

print("""\
The Leave-P-Out method works by using every combination of P points as test data.
The following output shows the result of splitting some sample data by Leave-One-Out and Leave-P-Out methods.
A bar displaying the current train-test split as well as the actual data points are displayed for each split.
In the bar, "-" is a training point and "T" is a test point.
""")

print("Data:\n{}\n".format(data))

print("Leave-One-Out:\n")
print_result(split_loocv)

print("Leave-P-Out (where p = {}):\n".format(P_VAL))
print_result(split_lpocv)

请注意,您可以更改脚本顶部的P值,以查看不同值的运行方式。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九妹123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值