训练-测试拆分程序用于估计机器学习算法在用于预测模型未使用的模型时所产生的性能。
这是一个快速简便的执行过程,其结果可用于比较机器学习算法在您的预测建模问题上的性能。尽管使用和解释都很简单,但有时不应使用此过程,例如当您有一个小型数据集时,以及在需要其他配置的情况下,例如将其用于分类且数据集不平衡时。
在本教程中,您将学习如何使用训练-测试拆分来评估机器学习模型。
完成本教程后,您将了解:
- 当您拥有非常大的数据集、训练成本高昂的模型或需要快速获得良好的模型性能估计时,训练-测试拆分程序是合适的。
- 如何使用 scikit-learn 机器学习库来执行训练-测试拆分过程。
- 如何使用训练-测试拆分来评估分类和回归的机器学习算法。
开启您的项目,阅读我的新书《Python 机器学习精通》,其中包含分步教程和所有示例的Python 源代码文件。
让我们开始吧。

用于评估机器学习算法的训练-测试划分
照片由 Paul VanDerWerf 拍摄,部分权利保留。
教程概述
本教程分为三个部分;它们是:
- 训练-测试拆分评估
- 何时使用训练-测试拆分
- 如何配置训练-测试拆分
- Scikit-Learn 中的训练-测试拆分程序
- 可重复的训练-测试拆分
- 分层训练-测试拆分
- 使用训练-测试拆分评估机器学习模型
- 分类的训练-测试拆分
- 回归的训练-测试拆分
训练-测试拆分评估
训练-测试拆分是一种评估机器学习算法性能的技术。
它可用于分类或回归问题,也可用于任何监督学习算法。
该过程包括获取一个数据集并将其分成两个子集。第一个子集用于拟合模型,称为训练数据集。第二个子集不用于训练模型;相反,将数据集的输入元素提供给模型,然后进行预测并将预测与预期值进行比较。第二个数据集称为测试数据集。
- 训练数据集:用于拟合机器学习模型。
- 测试数据集:用于评估拟合的机器学习模型。
目标是估计机器学习模型在新数据上的性能:即未用于训练模型的数据。
这就是我们期望在实践中如何使用模型。即,在具有已知输入和输出的可用数据上进行拟合,然后在未来新的示例中进行预测,而我们没有预期的输出或目标值。
当有足够大的数据集可用时,训练-测试过程是合适的。
何时使用训练-测试拆分
“足够大”的想法特定于每个预测建模问题。这意味着有足够的数据将数据集分成训练和测试数据集,并且每个训练和测试数据集都能充分代表问题域。这要求原始数据集也能充分代表问题域。
问题域的充分代表性意味着有足够的记录来涵盖领域中的所有常见情况和大多数不常见情况。这可能意味着在实践中观察到的输入变量的组合。这可能需要数千、数十万或数百万个示例。
反之,当可用数据集很小时,训练-测试过程不合适。原因是当数据集被分成训练集和测试集时,训练数据集中将没有足够的数据供模型学习输入到输出的有效映射。测试集中也将没有足够的数据来有效评估模型性能。估计的性能可能过于乐观(好)或过于悲观(坏)。
如果您数据不足,那么合适的替代模型评估程序将是 k 折交叉验证程序。
除了数据集大小之外,使用训练-测试拆分评估程序的另一个原因是计算效率。
某些模型的训练成本非常高,在这种情况下,其他过程中使用的重复评估是不可行的。例如深度神经网络模型。在这种情况下,通常使用训练-测试过程。
或者,一个项目可能有高效的模型和海量数据集,但可能需要快速估算模型性能。同样,在这种情况下会采用训练-测试拆分程序。
通过随机选择将原始训练数据集中的样本拆分成两个子集。这是为了确保训练和测试数据集能够代表原始数据集。
如何配置训练-测试拆分
该过程有一个主要的配置参数,即训练集和测试集的大小。这通常表示为训练集或测试集的大小在 0 到 1 之间的百分比。例如,大小为 0.67(67%)的训练集意味着剩余的 0.33(33%)百分比将分配给测试集。
没有最佳的拆分百分比。
您必须选择一个满足您项目目标的拆分百分比,并考虑以下因素:
- 模型训练的计算成本。
- 模型评估的计算成本。
- 训练集的代表性。
- 测试集的代表性。
尽管如此,常见的拆分百分比包括:
- 训练:80%,测试:20%
- 训练:67%,测试:33%
- 训练:50%,测试:50%
现在我们熟悉了训练-测试拆分模型评估过程,让我们看看如何在 Python 中使用此过程。
Scikit-Learn 中的训练-测试拆分程序
scikit-learn Python 机器学习库通过 train_test_split() 函数提供了训练-测试拆分评估过程的实现。
该函数以加载的数据集为输入,并返回拆分后的两个子集。
1 2 3 |
... # 拆分为训练测试集 train, test = train_test_split(dataset, ...) |
理想情况下,您可以将原始数据集拆分为输入(X)和输出(y)列,然后调用函数并同时传递这两个数组,以便它们被适当地拆分成训练集和测试集。
1 2 3 |
... # 拆分为训练测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, ...) |
可以通过“test_size”参数指定拆分的大小,该参数接受一个行数(整数)或数据集大小的百分比(浮点数),范围在 0 到 1 之间。
后者是最常见的,使用的值为 0.33,其中 33% 的数据集将分配给测试集,67% 分配给训练集。
1 2 3 |
... # 拆分为训练测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33) |
我们可以使用一个包含 1,000 个示例的合成分类数据集来演示这一点。
完整的示例如下所示。
1 2 3 4 5 6 7 8 |
# 将数据集拆分为训练集和测试集 from sklearn.datasets import make_blobs from sklearn.model_selection import train_test_split # 创建数据集 X, y = make_blobs(n_samples=1000) # 拆分为训练测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33) print(X_train.shape, X_test.shape, y_train.shape, y_test.shape) |
运行此示例将数据集拆分为训练集和测试集,然后打印新数据集的大小。
正如我们指定的,我们可以看到 670 个示例(67%)被分配给了训练集,330 个示例(33%)被分配给了测试集。
1 |
(670, 2) (330, 2) (670,) (330,) |
或者,可以通过指定“train_size”参数来拆分数据集,该参数可以是行数(整数)或原始数据集的百分比(介于 0 和 1 之间),例如 0.67 表示 67%。
1 2 3 |
... # 拆分为训练测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.67) |
可重复的训练-测试拆分
另一个重要的考虑是行是随机分配到训练集和测试集中的。
这样做是为了确保数据集是原始数据集的代表性样本(例如随机样本),而原始数据集本身应该是问题域观察的代表性样本。
在比较机器学习算法时,理想情况下(甚至可能要求)它们应该在相同的数据集子集上进行拟合和评估。
可以通过固定拆分数据集时使用的伪随机数生成器的种子来实现这一点。如果您不熟悉伪随机数生成器,请参阅教程
可以通过将“random_state”设置为整数值来实现。任何值都可以,它不是可调的超参数。
1 2 3 |
... # 再次拆分,我们应该看到相同的拆分结果 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1) |
下面的示例演示了这一点,并显示了两次独立的数据拆分会产生相同的结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# 演示训练-测试拆分过程的可重复性 from sklearn.datasets import make_blobs from sklearn.model_selection import train_test_split # 创建数据集 X, y = make_blobs(n_samples=100) # 拆分为训练测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1) # 总结前 5 行 print(X_train[:5, :]) # 再次拆分,我们应该看到相同的拆分结果 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1) # 总结前 5 行 print(X_train[:5, :]) |
运行此示例将拆分数据集并打印训练数据集的前五行。
数据集再次被拆分,并打印训练数据集的前五行,显示的值相同,这证实了当我们固定伪随机数生成器的种子时,我们会获得原始数据集的相同拆分。
1 2 3 4 5 6 7 8 9 10 11 |
[[-2.54341511 4.98947608] [ 5.65996724 -8.50997751] [-2.5072835 10.06155749] [ 6.92679558 -5.91095498] [ 6.01313957 -7.7749444 ]] [[-2.54341511 4.98947608] [ 5.65996724 -8.50997751] [-2.5072835 10.06155749] [ 6.92679558 -5.91095498] [ 6.01313957 -7.7749444 ]] |
分层训练-测试拆分
最后一个考虑是仅针对分类问题。
某些分类问题对于每个类别标签没有平衡的样本数量。因此,理想情况下,应将数据集拆分成训练集和测试集,以保留每个类别中样本的比例与原始数据集中的比例相同。
这称为分层训练-测试拆分。
我们可以通过将“stratify”参数设置为原始数据集的 y 分量来实现这一点。train_test_split() 函数将使用它来确保训练集和测试集都具有提供的“y”数组中每个类别的样本比例。
1 2 3 |
... # 拆分为训练测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.50, random_state=1, stratify=y) |
我们可以通过一个包含 94 个样本在一个类别和 6 个样本在第二个类别的分类数据集的示例来演示这一点。
首先,我们可以在没有“stratify”参数的情况下将数据集拆分为训练集和测试集。完整的示例列在下面。
1 2 3 4 5 6 7 8 9 10 11 |
# 在没有分层的情况下将不平衡数据集拆分为训练集和测试集 from collections import Counter from sklearn.datasets import make_classification from sklearn.model_selection import train_test_split # 创建数据集 X, y = make_classification(n_samples=100, weights=[0.94], flip_y=0, random_state=1) print(Counter(y)) # 拆分为训练测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.50, random_state=1) print(Counter(y_train)) print(Counter(y_test)) |
运行此示例后,首先报告按类别标签划分的数据集组成,显示预期的 94% 对 6%。
然后拆分数据集并报告训练集和测试集的组成。我们可以看到训练集有 45/5 个样本,测试集有 49/1 个样本。训练集和测试集的组成不同,这是不理想的。
1 2 3 |
Counter({0: 94, 1: 6}) Counter({0: 45, 1: 5}) Counter({0: 49, 1: 1}) |
接下来,我们可以对训练-测试拆分进行分层,并比较结果。
1 2 3 4 5 6 7 8 9 10 11 |
# 使用分层将不平衡数据集拆分为训练集和测试集 from collections import Counter from sklearn.datasets import make_classification from sklearn.model_selection import train_test_split # 创建数据集 X, y = make_classification(n_samples=100, weights=[0.94], flip_y=0, random_state=1) print(Counter(y)) # 拆分为训练测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.50, random_state=1, stratify=y) print(Counter(y_train)) print(Counter(y_test)) |
考虑到我们对训练集和测试集使用了 50% 的拆分,我们期望训练集和测试集分别有 47/3 个样本。
运行此示例,我们可以看到在这种情况下,训练-测试拆分的层次化版本创建的训练集和测试集都具有我们预期的 47/3 个样本。
1 2 3 |
Counter({0: 94, 1: 6}) Counter({0: 47, 1: 3}) Counter({0: 47, 1: 3}) |
现在我们熟悉了 train_test_split() 函数,让我们看看如何使用它来评估机器学习模型。
使用训练-测试拆分评估机器学习模型
在本节中,我们将探讨使用训练-测试拆分程序在标准的分类和回归预测建模数据集上评估机器学习模型。
分类的训练-测试拆分
我们将演示如何使用训练-测试拆分在声纳数据集上评估随机森林算法。
声纳数据集是一个标准机器学习数据集,由 208 行数据组成,包含 60 个数值输入变量和一个目标变量,目标变量有两个类别值,例如二元分类。
该数据集涉及预测声纳回波是否指示岩石或模拟水雷。
无需下载数据集;我们将在工作示例中自动下载它。
下面的示例下载数据集并汇总其形状。
1 2 3 4 5 6 7 8 9 |
# 汇总声纳数据集 from pandas import read_csv # 加载数据集 url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv' dataframe = read_csv(url, header=None) # 分割输入和输出元素 data = dataframe.values X, y = data[:, :-1], data[:, -1] print(X.shape, y.shape) |
运行此示例将下载数据集并将其拆分为输入和输出元素。正如预期的那样,我们可以看到有 208 行数据和 60 个输入变量。
1 |
(208, 60) (208,) |
我们现在可以使用训练-测试拆分来评估模型。
首先,必须将加载的数据集拆分为输入和输出组件。
1 2 3 4 |
... # 分割输入和输出 X, y = data[:, :-1], data[:, -1] print(X.shape, y.shape) |
接下来,我们可以拆分数据集,其中 67% 用于训练模型,33% 用于评估它。此拆分是任意选择的。
1 2 3 4 |
... # 拆分为训练测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1) print(X_train.shape, X_test.shape, y_train.shape, y_test.shape) |
然后我们可以定义模型并在训练数据集上进行拟合。
1 2 3 4 |
... # 拟合模型 model = RandomForestClassifier(random_state=1) model.fit(X_train, y_train) |
然后使用拟合的模型进行预测,并使用分类准确率性能指标评估预测。
1 2 3 4 5 6 |
... # 进行预测 yhat = model.predict(X_test) # 评估预测 acc = accuracy_score(y_test, yhat) print('Accuracy: %.3f' % acc) |
将这些结合起来,完整的示例列在下面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# 在声纳数据集上进行训练-测试拆分评估随机森林 from pandas import read_csv from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score # 加载数据集 url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv' dataframe = read_csv(url, header=None) data = dataframe.values # 分割输入和输出 X, y = data[:, :-1], data[:, -1] print(X.shape, y.shape) # 拆分为训练测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1) print(X_train.shape, X_test.shape, y_train.shape, y_test.shape) # 拟合模型 model = RandomForestClassifier(random_state=1) model.fit(X_train, y_train) # 进行预测 yhat = model.predict(X_test) # 评估预测 acc = accuracy_score(y_test, yhat) print('Accuracy: %.3f' % acc) |
运行此示例,首先加载数据集并确认输入和输出元素的行数。
注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能有所不同。考虑多次运行示例并比较平均结果。
数据集被拆分为训练集和测试集,我们可以看到训练有 139 行,测试集有 69 行。
最后,在测试集上评估模型,模型在新数据上进行预测的性能约为 78.3% 的准确率。
1 2 3 |
(208, 60) (208,) (139, 60) (69, 60) (139,) (69,) Accuracy: 0.783 |
回归的训练-测试拆分
我们将演示如何使用训练-测试拆分来评估住房数据集上的随机森林算法。
住房数据集是一个标准机器学习数据集,由 506 行数据组成,包含 13 个数值输入变量和一个数值目标变量。
该数据集涉及根据美国波士顿郊区的房屋细节来预测房价。
无需下载数据集;我们将在工作示例中自动下载它。
下面的示例下载并加载数据集为 Pandas DataFrame,并汇总数据集的形状。
1 2 3 4 5 6 7 |
# 加载和汇总住房数据集 from pandas import read_csv # 加载数据集 url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.csv' dataframe = read_csv(url, header=None) # 总结形状 print(dataframe.shape) |
运行此示例可确认 506 行数据以及 13 个输入变量和单个数字目标变量(共 14 个)。
1 |
(506, 14) |
我们现在可以使用训练-测试拆分来评估模型。
首先,必须将加载的数据集拆分为输入和输出组件。
1 2 3 4 |
... # 分割输入和输出 X, y = data[:, :-1], data[:, -1] print(X.shape, y.shape) |
接下来,我们可以拆分数据集,其中 67% 用于训练模型,33% 用于评估它。此拆分是任意选择的。
1 2 3 4 |
... # 拆分为训练测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1) print(X_train.shape, X_test.shape, y_train.shape, y_test.shape) |
然后我们可以定义模型并在训练数据集上进行拟合。
1 2 3 4 |
... # 拟合模型 model = RandomForestRegressor(random_state=1) model.fit(X_train, y_train) |
然后使用拟合模型进行预测,并使用平均绝对误差 (MAE) 性能指标评估预测。
1 2 3 4 5 6 |
... # 进行预测 yhat = model.predict(X_test) # 评估预测 mae = mean_absolute_error(y_test, yhat) print('MAE: %.3f' % mae) |
将这些结合起来,完整的示例列在下面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# 在住房数据集上进行训练-测试拆分评估随机森林 from pandas import read_csv from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestRegressor from sklearn.metrics import mean_absolute_error # 加载数据集 url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.csv' dataframe = read_csv(url, header=None) data = dataframe.values # 分割输入和输出 X, y = data[:, :-1], data[:, -1] print(X.shape, y.shape) # 拆分为训练测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1) print(X_train.shape, X_test.shape, y_train.shape, y_test.shape) # 拟合模型 model = RandomForestRegressor(random_state=1) model.fit(X_train, y_train) # 进行预测 yhat = model.predict(X_test) # 评估预测 mae = mean_absolute_error(y_test, yhat) print('MAE: %.3f' % mae) |
运行此示例,首先加载数据集并确认输入和输出元素的行数。
注意:由于算法或评估过程的随机性,或数值精度的差异,您的结果可能有所不同。考虑多次运行示例并比较平均结果。
数据集被拆分为训练集和测试集,我们可以看到训练有 339 行,测试集有 167 行。
最后,在测试集上评估模型,模型在新数据上进行预测的性能是平均绝对误差约为 2.211(千美元)。
1 2 3 |
(506, 13) (506,) (339, 13) (167, 13) (339,) (167,) MAE: 2.157 |
进一步阅读
如果您想深入了解,本节提供了更多关于该主题的资源。
- sklearn.model_selection.train_test_split API.
- sklearn.datasets.make_classification API.
- sklearn.datasets.make_blobs API.
总结
在本教程中,您学习了如何使用训练-测试拆分来评估机器学习模型。
具体来说,你学到了:
- 当您拥有非常大的数据集、训练成本高昂的模型或需要快速获得良好的模型性能估计时,训练-测试拆分程序是合适的。
- 如何使用 scikit-learn 机器学习库来执行训练-测试拆分过程。
- 如何使用训练-测试拆分来评估分类和回归的机器学习算法。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
极好的教程。谢谢。
谢谢 Usman。
解释得很好的教程 ????
谢谢!
你好 Jason,这是我听过的关于 train-test-split 函数的最精彩的解释。我只是对代码进行了一些修改,以找到准确率最高的精确点,并找出一些额外的见解。
谢谢。
太棒了
谢谢!
非常有用。非常感谢。
我正在寻找在 Python 回归问题中实现 Stackedautoencoder(高层去噪)的实现,请指导。
不客气。
感谢您的建议,我希望将来能写关于这个主题的文章。
非常感谢您的快速回复。我应该如何与您沟通?我有一些关于我项目的问题,请。
您可以随时联系我,我很乐意回答问题,但我无法审查代码/数据/论文。
https://machinelearning.org.cn/contact/
我有一个疑问。如何分割带有日期作为 X 变量的数据?因为 svr 模型不适合日期变量。在这种情况下我们该怎么做?
通常,我们在建模之前从数据中移除日期。
先生,如果我们为分类层在 sigmoid 函数之上添加 softmax 函数进行二元分类?softmax 函数是否比 sigmoid 有任何优势?
不,二元分类不是。它可能效率稍低。
读博士期间,您是否在训练集/测试集划分中使用 random_state?
抱歉,我不明白。博士学位与训练/测试划分有什么关系?
您可以根据自己的喜好设计实验,只要您能证明自己的决定即可。
我的意思是,在划分数据时,如果我使用 Random state,那么我的结果将始终是相同的。
但是,如果 Random state = None,那么每次我都会得到不同的分类器结果。
我可以使用 random state=1234,我的结果会超过 80%。
使用 random state=none,结果可能在 60-80 之间。
对于博士生来说,将 random state 设置为能获得最佳结果的数字,是常见的做法吗?
正确。
这取决于您项目的具体情况,而不是您正在进行的学位。正如我所说,只要您能证明您的决定,就可以选择任何您喜欢的方法。
嗨 Jason,我不想将数据分成训练集和测试集。我想用我所有的记录来训练我的数据集。如何用 Python 编写代码,因为 test_size 必须大于 0?谢谢。
好问题,请看本教程
https://machinelearning.org.cn/make-predictions-scikit-learn/
如何确保训练样本不在测试样本中重复出现?
只要每一行是唯一的,训练集/测试集划分就会为您完成此操作。
嗨,Jason,
这篇文章写得很好,信息量很大。感谢您分享您的想法,并让这个主题更加清晰。
但是,关于以上主题,我还有一些疑问,如下所示:
a) 现在观察到一个趋势,即数据集被分成三部分——训练集、测试集和验证集。
但是,交叉提问——这种三向划分是必要的,还是两向划分就足够了?
i) 如果答案是肯定的,为什么您这样做,三向划分相比两向划分有哪些优势?
ii) 如果您的回答是否定的,为什么不三向划分给定的数据集?
b) 三向划分是否优于两向划分?请解释。
c) 三向划分是否会导致以下情况:
i) 原始数据是否会丢失?
ii) 是否会导致偏差与方差的权衡,即模型的过拟合?
d) 什么是 k 折交叉验证?您是否有推荐的参考资料?
您执行的划分取决于您的项目和数据集。
验证集用于调整模型超参数。
您可以在此处了解更多关于验证数据集的信息。
https://machinelearning.org.cn/difference-test-validation-datasets/
还有一个疑问——
为什么在 Python 中,我们会将数据集划分为 X_train、X_test、y_train、y_test?
我之所以问这个问题,是因为我一直以来都使用 R 工具。在 R 中,您只需将数据集划分为训练集和测试集?
同样,我相信您可以通过使用 & 然后执行以下代码来实现:
train_set,test_set = train_test_split(dataset_name, test_size = 0.3)
print(train_set)
但是,为什么或者出于什么原因,您在上述教程中提到的方法更受欢迎或被广泛使用?我可以看到其他网站也使用了类似的重复代码。
上面的代码有什么问题或存在什么局限性?
需要理解其逻辑和原因。
我们在训练集上训练模型,并在测试集上评估其性能。
训练/测试划分的局限性在于其方差很高。这可以通过使用 k 折交叉验证来克服。
训练-测试样本的随机划分概念是否适用于使用时间步来人为地为数据集增加第三个维度的情况,例如在卷积神经网络或循环神经网络中?或者在这种情况下,是否更倾向于进行顺序的训练-测试划分?
是的。请看这里。
https://machinelearning.org.cn/backtest-machine-learning-models-time-series-forecasting/
大家好,我的数据包含 63 个特征和 70 行。当我在没有“训练测试划分”的情况下使用线性回归时,我得到一个 MAE 值“0.3”。而在使用“训练测试划分”时,我得到一个 MAE 值“4.9”。
那么我应该划分数据集吗?MAE 值“0.3”是否被认为是错误的(过拟合)?
不,这可能是因为划分导致两个集合太小而无法使用。
也许可以改用 k 折交叉验证。
那么,即使我不使用训练数据,这个结果也被认为是正确的吗?
抱歉,我不明白你的意思。也许你可以详细说明一下?
我的意思是 MAE 值“0.3”不被视为过拟合?而且我不应该使用训练测试划分(训练数据集)。
通常,如果模型在训练集上的表现优于测试集,并且测试集的表现不佳,那么模型可能存在过拟合。
也许这会有帮助。
https://machinelearning.org.cn/overfitting-machine-learning-models/
划分完数据集后,如何下载训练集和测试集??
你的意思是保存吗?如果是,请看这里。
https://machinelearning.org.cn/how-to-save-a-numpy-array-to-file-for-machine-learning/
你好 Jason,
很棒的文章!我有一个小问题。在数据挖掘过程中,我们应该在哪个阶段进行划分?是在预处理之后还是在进行转换之后?这对数据泄露有影响吗?
在数据准备之前。
这将有助于您避免数据泄露。
https://machinelearning.org.cn/data-preparation-without-data-leakage/
非常感谢 Jason
如果我想知道原始文件中 x_test 和 x_train 的索引,代码是什么?
(x_test 包含元素 6、7、9、1) 我想知道数据文件中的这些索引。
谢谢
训练/测试划分将直接返回行索引的数组。
嗨 Jason,我最近应用了一种非标准的模型评估方法。该方法存在计算成本高的问题,但我很难说服自己标准的评估方法是否足够。我希望你能提供一些输入。
我的目标是证明添加新特征可以提高性能。由于数据划分会影响结果,因此我生成了 k 次训练/测试划分。“训练”划分将由算法分成训练集和验证集,它将使用我文章中描述的方法之一。测试集是一个保留集。关键区别在于,我对多个测试集评估我的模型。
对原始数据集和包含新特征的数据集执行等效的划分。训练 k 个具有相同参数的模型,以产生基线和具有新特征的模型。这些模型在其相应的测试集上进行评估。然后,我对评估指标的分布运行 t 检验,以证明是否存在改进。
我不相信像 k 折交叉验证这样的方法可以保证测试集划分会偶然有利于一种场景。因此,我采用了上述方法。我希望你能解释一下为什么会这样,或者验证我的方法。
谢谢!
如果该方法能让您放心,那就继续吧。
我担心与该领域 40 多年的经验背道而驰,例如,重复的 k 折交叉验证 + 修正的学生 t 检验是黄金标准。
https://machinelearning.org.cn/statistical-significance-tests-for-comparing-machine-learning-algorithms/
又一篇有用的文章,谢谢。
在无监督方法中,`stratify y` 是否可以用于平衡训练集和测试集?或者是否有替代方法?
是的,它有效。事实上,分层也是处理不平衡数据集的一种方法。
精彩教程。
但是,在执行
X = preprocessing.StandardScalar().fit(X).transform(X) #.astype(float))
X[0:5]
时,出现错误
AttributeError: module ‘sklearn.preprocessing’ has no attribute ‘StandardScalar’
另一个错误是无法将字符串转换为浮点数。
你拼写错了。StandardScaler,最后是“e”。
嗨,Jason,
感谢这个教程,
1. 我们是否应该在进行归一化之前进行划分,还是之后?这是否意味着只对训练数据进行归一化,然后使用标量对测试数据进行归一化?
我认为只对训练数据进行是正确的。
2. 如果只对训练数据进行,如何进行分层划分,以使所有字符串列的值在训练和测试数据框中均匀分布?
我在 stackoverflow 上找到了这个 https://stackoverflow.com/a/51525992/11053801,这样做是否合适?
谢谢
归一化意味着您应用了标量。对于您将输入模型的所有数据,都应该进行此操作。您可以只用训练数据拟合标量,但这个拟合好的标量应该被复用于所有输入。
感谢您的回答。
如何确保测试集和训练集的划分包含字符串列的所有可能唯一值?
我不确定。您问的是哪些字符串列?
分类列。如果某个列有 10 个唯一值,我们必须确保训练集和测试集都包含这 10 个值。
在 train_test_split 中,根据目标列进行分层划分,而不是根据整个数据集,我能知道如何做到吗?
嗨,我构建了许多深度学习分类模型,但我不知道在使用 train_test_spilt() 划分数据集后如何确定模型的输入形状。另外,我想问输入形状是否因模型而异?我尝试了 (x_train.shape[1])、(x_train.shape[1:])、(x_train.shape[0],x_train.shape[1])、(x_train.shape[1],x_train.shape[2]),以及一些数字,但当我尝试拟合模型时,它们都出现了问题。
确保您能识别 train_test_split() 的输出,其中哪个维度是特征,哪个是样本。您不应该在输入形状中包含样本,所以通常 x_train.shape[0] 不应该包含在内。更多详情,请参阅这里详细的回答:https://stackoverflow.com/questions/44747343/keras-input-explanation-input-shape-units-batch-size-dim-etc
嗨 Adrian,谢谢这篇教程。我想问一下。
分层训练-测试划分要求我们随机化数据顺序。如果我不想打乱它怎么办?
换句话说,继续按照我们想要的百分比划分数据,但保持数据的顺序。
谢谢你。
查看文档,有一个“shuffle”参数,您可以将其设置为“False”:https://scikit-learn.cn/stable/modules/generated/sklearn.model_selection.train_test_split.html
在这种情况下,我们如何知道应该为模型训练多少个 epoch?
嗨 Alina……您应该为 epoch 设置一个上限,以避免过拟合。绘制损失曲线与 epoch 的关系图将很有帮助。以下内容可能有所帮助
https://www.pluralsight.com/guides/data-visualization-deep-learning-model-using-matplotlib
https://machinelearning.org.cn/early-stopping-to-avoid-overtraining-neural-network-models/
非常感谢这篇有用的文章。
我有一个数据集,包含 2 个信号的不同测量值,所有测量值都具有相同的长度,因此每个输入样本都是一个 nx2 的矩阵。每个输入矩阵应该对应一个标量输出。
请问如何创建将每个输入矩阵与相应的实数输出配对的数据集?以及哪种机器学习方法最适合此类问题?
再次感谢
嗨 Marco……请说明您机器学习模型的具体目标,以便我能更好地为您提供帮助。
嗨 James,
感谢您的回复。我正在尝试预测两个信号之间的相位差。
嗨 James,感谢您的回复。我正在尝试预测两个信号之间的相位差。
我真的很喜欢阅读您的文章。您的博客为我们提供了有用的信息。您做得非常出色。
这是我读过的最清晰的 ML 文章。感谢您花时间写作。
感谢您的反馈 Macduff!
出色的教程!但是,在回归场景中划分训练和测试数据时,对连续的 y(目标)变量进行分层是否明智?在回归场景中,我们甚至无法在 sklearn `train_test_split` 函数中使用 `stratify=y` 参数。感谢您的时间。谢谢!
嗨 James,
在决策树支持 1 次划分(即预测变量和目标来评估数据准确性)时,我有一个疑问,而随机森林不支持,因为我们需要将其分成 x_test、x_train 和 y_test、y_train。我能否知道这两种划分方法的原因,以及是否需要遵循任何基于模型的划分技术?
嗨 Kondal……我知道在使用小数据集时可能会出现问题。在您的应用中是否是这种情况?
以下内容也可能增加清晰度:
https://realpython.com/train-test-split-python-data/
https://www.kaggle.com/code/rafjaa/dealing-with-very-small-datasets/notebook
嗨。感谢这篇精彩的教程。
请问,如果我们想在训练之前对数据集进行标准化和重采样,步骤顺序是怎样的?
1) 划分 > 标准化 > 重采样
2) 划分 > 重采样 > 标准化
3) 标准化 > 划分 > 重采样
嗨 Ben……以下资源可能有所帮助。
https://machinelearning.org.cn/training-validation-test-split-and-cross-validation-done-right/
TypeError: Indexing elements must be in increasing order
当我使用该函数时,我收到此错误,您能帮我解决吗?
with h5py.File(path,”r”) as hdf
X_train, X_test = train_test_split( hdf[‘X’], test_size=0.20, random_state=33)
嗨 Vedant……您可能会发现以下讨论很有帮助。
https://github.com/madebyollin/acapellabot/issues/1
如果我们有两个用于训练和测试的数据框,我们想如何划分它们。
注意:我们想单独使用这些文件,所以我们不会合并两个文件并使用 train_test split。
在这种情况下,我们想进行划分。
读完这篇文章,我觉得我可以开始机器学习了。我一开始有点害怕。现在一切都清楚了。谢谢哥们。
感谢您的反馈 Sibutha!我们很感激!
嗨!
所以,我明白 train-test-split 应该在模型选择/超参数调整期间使用,但当我们在训练最佳模型以部署到真实、未见过的数据时该怎么办?模型仍然应该只在训练数据上拟合,还是可以使用我们拥有的所有可用标记数据?
我被告知,由于我们拥有的数据只是世界上所有现有数据的一个(非随机)切片,因此使用所有数据可能会导致过拟合。另一方面,我现在处理的数据集非常不平衡(约 48 个正例和约 5000 个负例),因此我想在尽可能多的正面观测值上拟合模型。
谢谢!
(另外,我从这个博客中学到了很多。我很欣赏这份奉献精神和友好的教程!)
嗨 Allen……在训练用于部署的最终模型时,一般原则是使用尽可能多的相关数据来最大化模型在新数据上的性能。以下是一些关键考虑因素:
### 用于部署的模型训练
1. **使用所有可用数据**
– **最终模型训练**:一旦您通过交叉验证或训练-测试划分等技术选择了最佳模型并调整了其超参数,您就应该在所有可用的标记数据上训练最终模型。这包括模型选择过程中使用的训练集和验证集。
– **原因**:更多数据通常能让模型学习到更好的表示,并更好地泛化到新的、未见过的数据。这对于正面样本稀少的类别不平衡数据集尤其重要。
2. **过拟合的考虑**
– **过拟合风险**:过拟合的风险主要出现在模型选择和超参数调整阶段。当模型不仅学习到潜在的模式,还学习到训练数据中的噪声时,就会发生过拟合。
– **缓解**: 使用交叉验证等技术有助于在模型选择过程中缓解过拟合。当在所有数据上训练最终模型时,过拟合的风险通常较低,因为模型在选择过程中已经在单独的数据上进行了验证。
### 数据不平衡
1. **不平衡数据集**
– **问题**: 不平衡数据集,例如您示例中约 48 个正样本和约 5000 个负样本,会带来挑战,因为模型可能会偏向多数类。
– **解决方案**: 有几种技术可以帮助解决数据不平衡问题
– **重采样**: 使用过采样(例如 SMOTE)来增加正样本的数量,或使用欠采样来减少负样本的数量。
– **类别权重调整**: 调整模型中的类别权重,以给予少数类更多的重视。
– **算法选择**: 一些算法在处理不平衡数据集方面具有内在优势,例如基于树的方法和集成技术。
### 最终模型训练的实际步骤
1. **超参数调优和模型选择**
– 使用训练-测试集划分或交叉验证来选择最佳模型并调优超参数。
– 在保留的验证集上评估模型性能,以确保其泛化能力良好。
2. **训练最终模型**
– 确定了最佳模型和超参数后,在整个数据集(包括先前的训练集和验证集)上重新训练模型。
– 这可以最大化模型从中学习的数据量,从而提高其鲁棒性和泛化能力。
### 示例工作流程
1. **数据准备**
python
from sklearn.model_selection import train_test_split
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
2. **模型选择和超参数调优**
python
from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifier
param_grid = {
'n_estimators': [100, 200],
'max_depth': [10, 20]
}
model = RandomForestClassifier(class_weight='balanced')
grid_search = GridSearchCV(model, param_grid, cv=5, scoring='roc_auc')
grid_search.fit(X_train, y_train)
best_model = grid_search.best_estimator_
3. **最终模型训练**
python
# 合并训练集和验证集数据
X_final = np.concatenate((X_train, X_val))
y_final = np.concatenate((y_train, y_val))
# 在所有可用数据上训练最佳模型
best_model.fit(X_final, y_final)
4. **模型评估**
– 在单独的测试数据或通过交叉验证来评估模型,以确保其性能良好。
– 监控性能指标,如 ROC AUC、准确率、召回率和 F1 分数,尤其是在数据不平衡的情况下。
通过遵循这些步骤,您可以确保您的模型经过良好调优,并在最大量的相关数据上进行训练,这对于在真实世界、未见过的数据上实现最佳性能至关重要。