如何使用 SVM 和 Iris 数据检查过度拟合?

数据挖掘 机器学习 scikit-学习 过拟合
2021-09-17 10:14:59

我正在对示例 iris 数据集使用机器学习预测。例如,我使用scikit-learn的支持向量机 (SVM)来预测准确性。但是,它返回的准确度为 1.0。这是我正在使用的代码:

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=51)
svm_model = svm.SVC(kernel='linear', C=1, gamma='auto')
svm_model.fit(X_train,y_train)
predictions = svm_model.predict(X_test)
accuracy_score(predictions, y_test)

如何找出或衡量这种过度拟合或模型是否如此好?我认为它没有过度拟合,但验证这一点的最佳方法是什么?

3个回答

您可以使用训练集测试集(或训练、验证和测试集)来检查过度拟合的迹象。正如其他人所提到的,您可以将数据拆分为训练集和测试集,或者使用交叉验证来更准确地评估分类器的性能。

由于您的数据集很小,因此不建议将您的数据分成训练集和测试集。使用交叉验证。

这可以使用cross_validatecross_val_score函数来完成;后者提供多种评估指标。除了测试分数,后者还提供适合时间得分时间

用你的例子;

from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
from sklearn import svm
from sklearn.metrics import accuracy_score

iris = load_iris()
X = iris.data[:, :5]  # we only take the first two features.
y = iris.target

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=51)
svm_model = svm.SVC(kernel='linear', C=1, gamma='auto')
svm_model.fit(X_train,y_train)
predictions = svm_model.predict(X_test)
accuracy_score(predictions, y_test)

原始精度:0.96666666666666667

使用cross_val_score函数,并打印分数估计的平均分数95% 置信区间:

from sklearn.model_selection import cross_val_score

scores = cross_val_score(svm_model, iris.data, iris.target, cv=5)
print("Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))

准确度:0.98 (+/- 0.03)

当然,虹膜数据集只是一个玩具示例在更大的真实数据集上,您可能会看到测试误差高于训练误差,而交叉验证提供的准确度低于原始数据。

所以我不会使用 iris 数据集来展示过度拟合。选择一个更大、更混乱的数据集,然后你就可以开始努力减少模型的偏差方差(过度拟合的“原因”)。

然后,您可以开始探索是偏差问题还是方差问题的迹象看这里:

https://www.quora.com/How-many-training-samples-are-needed-to-get-a-reliable-model-in-ML/answer/Sean-McClure-3?srid=zGgv

在此处输入图像描述

这可能是过度拟合的问题,或者仅仅进行一次训练/测试拆分并不能可靠地估计 SVM 的可推广误差。

我建议使用KFold验证来检查。

from sklearn.model_selection import KFold
import numpy as np
acc_score = []

kf = KFold(n_splits=5)

for train_index, test_index in kf.split(X):

    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]

    svm_model.fit(X_train,y_train)
    predictions = svm_model.predict(X_test)
    acc_score.append(accuracy_score(predictions, y_test))

np.mean(acc_score)

如果平均值仍然是 1.0,那么你做得很好,但我的直觉是,你的高分取决于你正在查看的数据的削减。

基于此处,用于sklearn.model_selection.train_test_split(*arrays, **options)将您的数据拆分为训练和测试。在 train-split 上训练您的模型并使用该predict方法查看测试数据的性能。作为一个例子,看看下面的代码,它将数据分成两个单独的组。

import numpy as np
from sklearn.model_selection import train_test_split
X, y = np.arange(10).reshape((5, 2)), range(5)
X

array([[0, 1],
       [2, 3],
       [4, 5],
       [6, 7],
       [8, 9]])

list(y)
[0, 1, 2, 3, 4]


X_train, X_test, y_train, y_test = train_test_split(
...     X, y, test_size=0.33, random_state=42)
...
X_train
array([[4, 5],
   [0, 1],
   [6, 7]])
y_train
[2, 0, 3]
X_test
array([[2, 3],
   [8, 9]])
y_test
[1, 4]

train_test_split(y, shuffle=False)
[[0, 1, 2], [3, 4]]