📜  分层 K 折交叉验证

📅  最后修改于: 2022-05-13 01:55:08.965000             🧑  作者: Mango

分层 K 折交叉验证

在机器学习中,当我们想要训练我们的 ML 模型时,我们使用 sklearn 中的 train_test_split() 类将整个数据集拆分为 training_set 和 test_set。然后我们在 training_set 上训练我们的模型并在 test_set 上测试我们的模型。我们将在这种方法中面临的问题是:

每当我们更改 train_test_split() 中存在的 random_state 参数时,我们会针对不同的 random_state 获得不同的准确度,因此我们无法准确指出我们模型的准确度。
train_test_split() 通过随机抽样将数据集拆分为 training_test 和 test_set。但是会进行分层抽样。

什么是随机抽样和分层抽样?
假设您要进行一项调查并决定从特定州致电 1000 人,如果您选择 1000 名男性或 1000 名女性或 900 名女性和 100 名男性(随机)询问他们对特定产品的意见。然后根据这 1000 条意见,您无法决定整个状态对您的产品的意见。这是随机抽样。
但是在分层抽样中,假设该州的人口为 51.3% 男性和 48.7% 女性,然后从该州选择 1000 人,如果您选择 513 名男性(1000 人的 51.3%)和 487 名女性(1000 人的 48.7%)即 513男性 + 487 位女性(总计=1000 人)征求意见。那么这些人代表了整个国家。这称为分层抽样。

为什么机器学习中不首选随机抽样?
让我们考虑一个二元分类问题。让我们的数据集由 100 个样本组成,其中 80 个是负类 {0},20 个是正类 {1}。

随机抽样:
如果我们进行随机抽样以将数据集分别以 8:2 的比例拆分为 training_set 和 test_set。那么我们可能会在 training_set 中获得所有负类 {0},即 training_test 中的 80 个样本和 test_set 中的所有 20 个正类 {1}。现在如果我们在 training_set 上训练我们的模型并在 test_set 上测试我们的模型,那么显然我们会得到一个很差的准确度分数。

分层抽样:
在分层抽样中,training_set 由 64 个负类{0}(80% 0f 80)和 16 个正类 {1}(80% of 20)组成,即 training_set 中有 64{0}+16{1}=80 个样本,代表原始数据集等比例和类似的 test_set 由 16 个负类 {0}(80 的 20%)和 4 个正类{1}(20 的 20%)组成,即 16{0}+4{1}=20 个样本test_set 也以相等的比例表示整个数据集。这种类型的训练-测试-分割结果很好。

上述问题的解决方案是什么?
对于第一个问题,我们能够为不同的 random_state 参数值获得不同的准确度分数的解决方案是使用 K-Fold 交叉验证。但是 K 折交叉验证也存在第二个问题,即随机抽样。
第一个和第二个问题的解决方案是使用分层 K 折交叉验证。

什么是分层 K 折交叉验证?
Stratified k-fold cross-validation 和 just k-fold cross-validation 一样,但是 Stratified k-fold cross-validation,它做的是分层抽样而不是随机抽样。

代码:Stratified K-Fold Cross-Validation 的Python代码实现

Python3
# This code may not be run on GFG IDE 
# as required packages are not found. 
    
# STRATIFIES K-FOLD CROSS VALIDATION { 10-fold }
  
# Import Required Modules.
from statistics import mean, stdev
from sklearn import preprocessing
from sklearn.model_selection import StratifiedKFold
from sklearn import linear_model
from sklearn import datasets
  
# FEATCHING FEATURES AND TARGET VARIABLES IN ARRAY FORMAT.
cancer = datasets.load_breast_cancer()
# Input_x_Features.
x = cancer.data                        
 
# Input_ y_Target_Variable.
y = cancer.target                      
   
  
# Feature Scaling for input features.
scaler = preprocessing.MinMaxScaler()
x_scaled = scaler.fit_transform(x)
  
# Create  classifier object.
lr = linear_model.LogisticRegression()
  
# Create StratifiedKFold object.
skf = StratifiedKFold(n_splits=10, shuffle=True, random_state=1)
lst_accu_stratified = []
  
for train_index, test_index in skf.split(x, y):
    x_train_fold, x_test_fold = x_scaled[train_index], x_scaled[test_index]
    y_train_fold, y_test_fold = y[train_index], y[test_index]
    lr.fit(x_train_fold, y_train_fold)
    lst_accu_stratified.append(lr.score(x_test_fold, y_test_fold))
  
# Print the output.
print('List of possible accuracy:', lst_accu_stratified)
print('\nMaximum Accuracy That can be obtained from this model is:',
      max(lst_accu_stratified)*100, '%')
print('\nMinimum Accuracy:',
      min(lst_accu_stratified)*100, '%')
print('\nOverall Accuracy:',
      mean(lst_accu_stratified)*100, '%')
print('\nStandard Deviation is:', stdev(lst_accu_stratified))


输出:

List of possible accuracy: [0.9298245614035088, 0.9649122807017544, 0.9824561403508771, 1.0, 0.9649122807017544, 0.9649122807017544, 0.9824561403508771, 0.9473684210526315, 0.9473684210526315, 0.9821428571428571]

Maximum Accuracy That can be obtained from this model is: 100.0 %

Minimum Accuracy That can be obtained from this model is: 92.98245614035088 %

The overall Accuracy of this model is: 96.66353383458647 %

The Standard Deviation is: 0.02097789213195869