天天看点

翻译:提高既定数据集下的模型效果——交叉验证(CrossValidaton)

官方文档链接

数据给定&模型给定的前提下,怎么提高训练模型的效果?

数据和模型给定之后,我们只有一条路:提高数据的利用效率。方法有两个:

1)使用train_test_split函数分成训练集和测试集;

2)通过CrossValidaton (cross_val_score函数) 进一步压榨训练集的价值;

1) 一般我们用的方法是:将原始数据集分为 训练数据集 & 测试数据集。

优点:思路正确,但仅仅是思路正确。

缺点:思路正确,但是方法不够高明。

import numpy as np
from sklearn.model_selection import train_test_split
from sklearn import datasets                  # sklearn 自带的给学习人员用的数据集
from sklearn import svm

# 首先,引入原始数据集
x, y = datasets.load_iris(return_X_y=True)    # iris: 鸢尾花数据集
print(x.shape)
print(y.shape)
"""
结果如下:
(150, 4)
(150,)
"""
           
# 其次,把数据集按6:4的比例划分为训练数据集和测试数据集
x_train, x_test, y_train, y_test = train_test_split(x, y, train_size=0.6, random_state=0) # random_state的用处见下边注释。

print(x_train.shape)
print(x_test.shape)
print(y_train.shape)
print(y_test.shape)
"""
结果如下:
(90, 4)
(60, 4)
(90,)
(60,)
"""
           
# 最后,用SVC模型测试一下:
clf = svm.SVC(kernel='linear', C=1)  # C的作用见下便注释
clf.fit(x_train, y_train)
score = clf.score(x_test, y_test)

print(score)
"""
0.9666666666666667
"""
           
注释:
  1. train_test_split(random_state=0):一方面,random_state不设定的话,每次函数train_test_split得到的训练集和测试集都不一样;另一方面,random_state设定为INT的话每次得到的训练集和测试集保持一致(INT可以是0也可以是42,效果一样)
  2. svm.SVC(C=1):kernel='linear'时
    翻译:提高既定数据集下的模型效果——交叉验证(CrossValidaton)
    ,C用来告诉SVM你有多想把训练数据正确分好类。对于一个大的C值,分类器选用margin小的超平面,代价是分类器的泛化性会降低;反之亦然,

评价:

一方面,看它的优点:如果原始数据集没有被划分为 训练数据集&测试数据集两部分,而是直接给训练模型的话,结果会是过拟合、泛化能力极低(即模型完美于预测样本数据,完败于预测原始样本之外的任何数据);

另一方面看它的不足:

  1. 训练结果更大地依赖于训练数据集和测试数据集占原始数据集的比重。
  2. 用训练数据集得到算法参数/模型参数的方法不够好,因为最终的一组参数其实是从N组参数中对比得来的,这意味着测试数据集的信息会被间接地泄露出来,参数调整得越多、泄露越多,使得测试数据集的意义越低;

2)一个压榨数据价值更好的方法就是 cross-validation / CV / 交叉检验:

以k-fold CV为例:仍然是把原始数据集分成训练集和测试集,但是训练模型的时候不使用测试集。最常见的一个叫做k_fold CV。

  • 具体来说就是把训练集平分为k个fold,其中每个fold依次作为测试集、余下的作为训练集,进行k次训练,得到共计k组参数。取k组参数的均值作为模型的最终参数。
  1. 优点:充分压榨了数据集的价值。在样本集不够大的情况下尤其珍贵。
  2. 缺点:运算起来花时间。
翻译:提高既定数据集下的模型效果——交叉验证(CrossValidaton)

我们用SVM()/support vector machines(支持向量机)中的SVC分类算法为例:

from sklearn.model_selection import cross_val_score

clf = svm.SVC(kernal='linear', C=1)
scores = cross_val_score(clf, x, y, cv=5)

print(scores)
print(f"Accuracy: {scores.mean():.3f},{scores.std()**2:.3f}")
"""
[0.96666667     1.     0.96666667    0.96666667     1.        ]
Accuracy: 0.980,0.000
"""
           

继续阅读