Machine Learning(14) - K Fold Cross Validation

引言

我们前面学了那么多种 Machine Learning 的模型,那么当我们拿到一个具体问题的时候,难免就会有疑惑,我究竟用哪个模型才是合适的呢?这节要讲的 Cross Validation 就是用来解决这个问题的,它可以用来评估模型的表现。

Machine Learning(14) - K Fold Cross Validation

K Fold Cross Validation 的工作原理就是将一个数据集分成 K 份,遍历 这 K 份数据,每次都是用其中的 1 份做测试,剩下的 K-1 份训练数据,然后将每次求得的 score 取平均值。

正文

下面我们就以 ”手写数字“ 的数据集为例,看下具体用法:

引入数据集

from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier
import numpy as np
from sklearn.datasets import load_digits

digits = load_digits()

分别用 3 中模型处理模型,并测试其准确度

from sklearn.model_selection import train_test_split
// 将数据集分为训练数据和测试数据
X_train, X_test, y_train, y_test = train_test_split(digits.data, digits.target, test_size=0.3)

lr = LogisticRegression()
lr.fit(X_train, y_train)
lr.score(X_test, y_test) // 输出模型准确度 0.9592592592592593

svm = SVC()
svm.fit(X_train, y_train)
svm.score(X_test, y_test) // 输出模型准确度 0.5074074074074074

rf = RandomForestClassifier()
rf.fit(X_train, y_train)
rf.score(X_test, y_test) // 输出模型准确度 0.9481481481481482

这里要说明的是,train_test_split() 函数对测试数据和训练数据的分配是随机的,也就是说没执行一次,得到的分类都会不同。数据的不同,也会直接影响到模型的表现。

这里大家可以尝试多执行几次 train_test_split() 函数,会发现 score 的值都会有所变化。

K fold

下面就引入我们上面所说的 K Fold 的概念:

from sklearn.model_selection import KFold
kf = KFold(n_splits = 3) // 会将处理的数据集分成 3 份
kf

// 输出
KFold(n_splits=3, random_state=None, shuffle=False)

// 先用一个简单的数组做例子,来开下 KFold() 函数的效果
for train_index, test_index in kf.split([1, 2, 3, 4, 5, 6, 7, 8, 9]):
    print(train_index, test_index)

// 输出
[3 4 5 6 7 8] [0 1 2]
[0 1 2 6 7 8] [3 4 5]
[0 1 2 3 4 5] [6 7 8]

以上输出可以清楚地看出 KFold() 函数的作用,因为我们设置了参数 n_splits=3,所以它将数据平均地分成 3 份,每一份的数据组合都是不同的,并且保证每个数字都有出现在前后两个数组(训练数据集和测试数据集)中的机会。

定义模型准确度的函数

下面我们把测试模型,测试模型的过程封装成函数,方便后面使用:

def get_score(model, X_train, X_test, y_train, y_test):
    model.fit(X_train, y_train)
    return model.score(X_test, y_test)

用手写数字集正式操练

这里引用的是 StratifiedKFold,它的本质功能同前面的 KFold,区别是它在将数据分组的时候,会将数据打乱来分,准确性更高。

from sklearn.model_selection import StratifiedKFold
folds = StratifiedKFold(n_splits = 3)

// 为 3 个模型的预测值创建 3 个数组
scores_l = []
scores_svm = []
scores_rf = []

// 把手写数字的数据集分成 3 份,然后遍历 3 次
for train_index, test_index in folds.split(digits.data, digits.target):
    // 取出每一次的训练数据和测试数据
    X_train, X_test, y_train, y_test = digits.data[train_index], digits.data[test_index], digits.target[train_index], digits.target[test_index]
    // 把每一次得出模型准确度的值放进对应的数组
    scores_l.append(get_score(LogisticRegression(), X_train, X_test, y_train, y_test))
    scores_svm.append(get_score(SVC(), X_train, X_test, y_train, y_test))
    scores_rf.append(get_score(RandomForestClassifier(n_estimators = 40), X_train, X_test, y_train, y_test))

// 输出每种模型的准确度值的数组    
scores_l
// 输出
[0.8964941569282137, 0.9515859766277128, 0.9115191986644408]

scores_svm
// 输出
[0.41068447412353926, 0.41569282136894825, 0.4273789649415693]

scores_rf
// 输出
[0.9398998330550918, 0.9449081803005008, 0.9131886477462438]

用 cross_val_score 函数轻松实现

以上复杂的操作过程,其实是在讲 cross_val_score 的实现原理,实际上,我们用 cross_val_score 就可以轻松实现上面的过程:

from sklearn.model_selection import cross_val_score

cross_val_score(LogisticRegression(), digits.data, digists.target)

// 输出
array([0.89534884, 0.94991653, 0.90939597])

cross_val_score(SVC(), digits.data, digists.target)
// 输出
array([0.39368771, 0.41068447, 0.45973154])

cross_val_score(RandomForestClassifier(n_estimators = 40), digits.data, digists.target)

// 输出
array([0.93189369, 0.94156928, 0.92281879])

使用 cross_val_score 不仅可以轻松测试每个模型的准确度,还可以对某个模型进行参数微调,比如上面对 RandomForestClassifier,就可以给它增加参数 n_estimators = 40 来调节它的准确度。

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!