分层k折交叉验证_python 分层抽样,按照某一列分层交叉验证 - CSDN
精华内容
参与话题
  • 交叉验证是什么? 在模型建立中,通常有两个数据集:训练集(train)和测试集(test)。训练集用来训练模型;测试集是完全不参与训练的数据,仅仅用来观测测试效果的数据。 一般情况下,训练的结果对于训练集的拟合...

    交叉验证是什么?

    在模型建立中,通常有两个数据集:训练集(train)和测试集(test)。训练集用来训练模型;测试集是完全不参与训练的数据,仅仅用来观测测试效果的数据。

    一般情况下,训练的结果对于训练集的拟合程度通常还是挺好的,但是在测试集总的表现却可能不行。比如下面的例子:
    在这里插入图片描述

    • 图一的模型是一条线型方程。 可以看到,所有的红点都不在蓝线上,所以导致了错误率很高,这是典型的不拟合的情况
    • 图二 的蓝线则更加贴近实际的红点,虽然没有完全重合,但是可以看出模型表示的关系是正确的。
    • 图三,所有点都在蓝线上,这时候模型计算出的错误率很低,(甚至将噪音都考虑进去了)。这个模型只在训练集中表现很好,在测试集中的表现就不行。 这是典型的‘过拟合’情况。

    所以,训练的模型需要找出数据之间‘真正’的关系,避免‘过拟合’的情况发生。

    交叉验证:就是在训练集中选一部分样本用于测试模型。
    保留一部分的训练集数据作为验证集/评估集,对训练集生成的参数进行测试,相对客观的判断这些参数对训练集之外的数据的符合程度。

    留一验证(LOOCV,Leave one out cross validation )

    只从可用的数据集中保留一个数据点,并根据其余数据训练模型。此过程对每个数据点进行迭代,比如有n个数据点,就要重复交叉验证n次。例如下图,一共10个数据,就交叉验证十次
    在这里插入图片描述

    优点:

    • 适合小样本数据集
    • 利用所有的数据点,因此偏差将很低

    缺点:

    • 重复交叉验证过程n次导致更高的执行时间
    • 测试模型有效性的变化大。因为针对一个数据点进行测试,模型的估计值受到数据点的很大影响。如果数据点被证明是一个离群值,它可能导致更大的变化

    LOOCC是保留一个数据点,同样的你也可以保留P个数据点作为验证集,这种方法叫LPOCV(Leave P Out Cross Validation)

    LOOCC代码

    R

    score = list()
    
    LOOCV_function = function(x,label){
     for(i in 1:nrow(x)){
     training = x[-i,]
     model = #... train model on training
     validation = x[i,]
     pred = predict(model, validation[,setdiff(names(validation),label)])
     score[[i]] = rmse(pred, validation[[label]]) # score/error of ith fold
     }
     return(unlist(score)) # returns a vector
     }
    

    验证集方法

    交叉验证的步骤如下:

    1. 保留一个样本数据集, (取出训练集中20%的样本不用)
    2. 使用数据集的剩余部分训练模型 (使用另外的80%样本训练模型)
    3. 使用验证集的保留样本。(完成模型后,在20%的样本中测试)
    4. 如果模型在验证数据上提供了一个肯定的结果,那么继续使用当前的模型。

    优点: 简单方便。直接将训练集按比例拆分成训练集和验证集,比如50:50。

    缺点: 没有充分利用数据, 结果具有偶然性。如果按50:50分,会损失掉另外50%的数据信息,因为我们没有利用着50%的数据来训练模型。

    验证集方法代码

    Python 使用train_test_split

    from sklearn.model_selection import train_test_split
    train, validation = train_test_split(data, test_size=0.50, random_state = 5)
    
    

    train_test_split,划分成train 和test 两部分,其中train用来训练模型,test用来评估模型,模型通过fit方法从train数据集中学习,调用score方法在test集上进行评估。

    from sklearn.model_selection import train_test_split
    from sklearn.linear_model import LogisticRegression
    
    #已经导入数据
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=20, shuffle=True)
    
    # Logistic Regression
    model = LogisticRegression()
    model.fit(X_train, y_train)
    prediction = model.predict(X_test)
    print('The accuracy of the Logistic Regression is: {0}'.format(metrics.accuracy_score(prediction,y_test)))
    

    R

    set.seed(101) # Set Seed so that same sample can be reproduced in future also
    
    # Now Selecting 50% of data as sample from total 'n' rows of the data
    sample <- sample.int(n = nrow(data), size = floor(.50*nrow(data)), replace = F)
    train <- data[sample, ]
    test  <- data[-sample, ]
    

    K折交叉验证(k-fold cross validation)

    针对上面通过train_test_split划分,从而进行模型评估方式存在的弊端,提出Cross Validation 交叉验证。

    Cross Validation:简言之,就是进行多次train_test_split划分;每次划分时,在不同的数据集上进行训练、测试评估,从而得出一个评价结果;如果是5折交叉验证,意思就是在原始数据集上,进行5次划分,每次划分进行一次训练、评估,最后得到5次划分后的评估结果,一般在这几次评估结果上取平均得到最后的 评分。k-fold cross-validation ,其中,k一般取5或10。
    在这里插入图片描述

    1. 训练模型需要在大量的数据集基础上,否则就不能够识别数据中的趋势,导致错误产生
    2. 同样需要适量的验证数据点。 验证集太小容易导致误差
    3. 多次训练和验证模型。需要改变训练集和验证集的划分,有助于验证模型。
      步骤:
    4. 随机将整个数据集分成k折;
    5. 如图中所示,依次取每一折的数据集作验证集,剩余部分作为训练集
    6. 算出每一折测试的错误率
    7. 取这里K次的记录平均值 作为最终结果

    优点:

    • 适合大样本的数据集
    • 经过多次划分,大大降低了结果的偶然性,从而提高了模型的准确性。
    • 对数据的使用效率更高。train_test_split,默认训练集、测试集比例为3:1。如果是5折交叉验证,训练集比测试集为4:1;10折交叉验证训练集比测试集为9:1。数据量越大,模型准确率越高。

    缺点:

    • 对数据随机均等划分,不适合包含不同类别的数据集。比如:数据集有5类数据(ABCDE各占20%),抽取出来的也正好是按照类别划分的5类,第一折全是A,第二折全是B……这样就会导致,模型学习到测试集中数据的特点,用BCDE训练的模型去测试A类数据、ACDE的模型测试B类数据,这样准确率就会很低。

    如何确定K值?

    • 一般情况下3、5是默认选项,常建议用K=10。
    • k值越低,就越有偏差;K值越高偏差就越小,但是会受到很大的变化。
    • k值越小,就越类似于验证集方法;而k值越大,则越接近LOOCV方法。

    k-fold代码

    Python 使用cross_val_score或者KFold

    cross_val_score直接将整个交叉验证过程连接起来。

    from sklearn.model_selection import cross_val_score
    model  = LogisticRegression()
    scores = cross_val_score(model,X, y,cv=3) #cv:默认是3折交叉验证,可以修改cv=5,变成5折交叉验证。
    print("Cross validation scores:{}".format(scores))
    print("Mean cross validation score:{:2f}".format(scores.mean()))
    

    KFold 可以显示具体的划分情况。

    from sklearn.model_selection import KFold 
    
    kf = KFold(n_splits=5, random_state=None) # 5折
    
    #显示具体划分情况
    for train_index, test_index in kf.split(X):
          print("Train:", train_index, "Validation:",test_index)
          X_train, X_test = X[train_index], X[test_index] 
          y_train, y_test = y[train_index], y[test_index] 
    
    i = 1
    for train_index, test_index in kf.split(X, y):
        print('\n{} of kfold {}'.format(i,kf.n_splits))
        X_train, X_test = X[train_index], X[test_index] 
        y_train, y_test = y[train_index], y[test_index]
        model = LogisticRegression(random_state=1)
        model.fit(X_train, y_train)
        pred_test = model.predict(X_test)
        score = metrics.accuracy_score(y_test, pred_test)
        print('accuracy_score', score)
        i += 1
        #pred_test = model.predict(X_test)
        pred = model.predict_proba(X_test)[:, 1]
    

    R code

    library(caret)
    data(iris)
    
    # Define train control for k fold cross validation
    train_control <- trainControl(method="cv", number=10)
    # Fit Naive Bayes Model
    model <- train(Species~., data=iris, trControl=train_control, method="nb")
    # Summarise Results
    print(model)
    

    分层交叉验证 (Stratified k-fold cross validation)

    分层是重新将数据排列组合,使得每一折都能比较好地代表整体。

    比如下面这个例子:在一个二分类问题上,原始数据一共有两类(F和M),F:M的数据量比例大概是 1:3;划分了5折,每一折中F和M的比例都保持和原数据一致(1:3)。

    这样就避免了随机划分可能产生的的情况,像是一折全是F,其他3折都是M。

    在这里插入图片描述

    下图是标准交叉验证和分层交叉验证的区别:
    标准交叉验证(即K折交叉验证):直接将数据分成几折;
    分层交叉验证:先将数据分类(class1,2,3),然后在每个类别中划分三折。
    在这里插入图片描述

    分层验证代码

    Python 使用cross_val_scoreStratifiedKFold

    from sklearn.model_selection import StratifiedKFold
    skf = StratifiedKFold(n_splits=5,shuffle=False,random_state=0)
    
    # X is the feature set and y is the target
    for train_index, test_index in skf.split(X,y): 
        print("Train:", train_index, "Validation:", test_index) 
        X_train, X_test = X[train_index], X[test_index] 
        y_train, y_test = y[train_index], y[test_index]
        
    model = LogisticRegression()
    scores = cross_val_score(model,X,y,cv=skf)
    print("straitified cross validation scores:{}".format(scores))
    print("Mean score of straitified cross validation:{:.2f}".format(scores.mean()))
    

    ** R code**

    library(caret)
    # Folds are created on the basis of target variable
    folds <- createFolds(factor(data$target), k = 10, list = FALSE)
    

    重复交叉验证( k-fold cross validation with repetition)

    如果训练集不能很好地代表整个样本总体,分层交叉验证就没有意义了。这时候,可以使用重复交叉验证。

    重复验证代码

    Python:RepeatedKFold重复K折交叉验证

    kf = RepeatedKFold(n_splits=5, n_repeats=2, random_state=None)  #默认是5折
    
    for train_index, test_index in kf.split(X):
          print("Train:", train_index, "Validation:",test_index)
          X_train, X_test = X[train_index], X[test_index] 
          y_train, y_test = y[train_index], y[test_index]
            
    i = 1
    for train_index, test_index in kf.split(X, y):
        print('\n{} of kfold {}'.format(i,i))
        X_train, X_test = X[train_index], X[test_index] 
        y_train, y_test = y[train_index], y[test_index]
        model = LogisticRegression(random_state=1)
        model.fit(X_train, y_train)
        pred_test = model.predict(X_test)
        score = metrics.accuracy_score(y_test, pred_test)
        print('accuracy_score', score)
        i += 1
        #pred_test = model.predict(X_test)
        pred = model.predict_proba(X_test)[:, 1]
    

    对抗验证(Adversarial Validation)

    在处理实际数据集时,经常会出现测试集和训练集截然不同的情况。因此,可能导致交叉验证结果不一致

    在这种情况下,可以使用对抗验证法:总体思路是根据特征分布创建一个分类模型,以检查训练集和测试集之间的相似程度。

    步骤:

    1. 组合训练集和测试集;
    2. 分配0/1标签(0-训练、1-测试);
    3. 建立模型,(如果模型AUC在0.7以上,表示分类器表现较好,也间接说明train 和test 差异度较大
    4. 评估二进制分类任务来量化两个数据集的分布是否一致;
    5. 找出和测试集最相似的数据样本
    6. 构成与测试集最相似的验证集;

    优点: 使验证策略在训练集和测试集高度不同的情况下更加可靠。

    缺点: 一旦测试集的分布发生变化,验证集可能不再适合评估模型。

    对抗验证代码

    #1. 将目标变量删除
    train.drop(['target'], axis = 1, inplace = True)
    
    #2. 创建新的目标变量:训练集为1;测试集为0
    train['is_train'] = 1
    test['is_train'] = 0
    
    #3. 合并训练集和测试集
    df = pd.concat([train, test], axis = 0)
    
    #4. 使用新变量训练分类模型,并预测概率
    y = df['is_train']; df.drop('is_train', axis = 1, inplace = True) 
    # Xgboost parameters
    xgb_params = {'learning_rate': 0.05, 
                  'max_depth': 4,
                  'subsample': 0.9,        
                  'colsample_bytree': 0.9,
                  'objective': 'binary:logistic',
                  'silent': 1, 
                  'n_estimators':100, 
                  'gamma':1,         
                  'min_child_weight':4}   
    clf = xgb.XGBClassifier(**xgb_params, seed = 10)
    probs = clf.predict_proba(x1)[:,1]
    
    #5. 使用步骤4中计算的概率对序列集进行排序,并将前n%个样本/行作为验证集(n%是您希望保留在验证集中的序列集的分数)
    new_df = pd.DataFrame({'id':train.id, 'probs':probs})
    new_df = new_df.sort_values(by = 'probs', ascending=False) # 30% validation set
    val_set_ids = new_df.iloc[1:np.int(new_df.shape[0]*0.3),1]
    #val_set_ids将为提供列训练集的ID,这些ID将构成与测试集最相似的验证集。
    

    时间序列的交叉验证(Cross Validation for time series)

    对于时间序列的数据集,不能像上述方法一样随机地划分验证集。为了解决时间序列的预测问题,可以尝试时间序列交叉验证:采用正向链接的策略,即按照时间顺序划分每一折的数据集。

    假设我们有一个时间序列,表示在n年内消费者对某一产品的年需求量。
    在这里插入图片描述
    我们逐步选择新的训练集和测试集。我们从一个最小的训练集开始(这个训练集具有拟合模型所需的最少观测数)逐步地,每次都会更换训练集和测试集。在大多数情况下,不必一个个点向前移动,可以设置一次跨5个点/10个点。在回归问题中,可以使用以下代码执行交叉验证。

    时间序列代码

    pythonTimeSeriesSplit

    from sklearn.model_selection import TimeSeriesSplit
    X = np.array([[1, 2], [3, 4], [1, 2], [3, 4]])
    y = np.array([1, 2, 3, 4])
    tscv = TimeSeriesSplit(n_splits=3)
    
    for train_index, test_index in tscv.split(X):
         print("Train:", train_index, "Validation:", val_index)
         X_train, X_test = X[train_index], X[val_index]
         y_train, y_test = y[train_index], y[val_index]
    
    TRAIN: [0] TEST: [1]
    TRAIN: [0 1] TEST: [2]
    TRAIN: [0 1 2] TEST: [3]
    

    R code

    library(fpp)
    library(forecast)
    e <- tsCV(ts, Arima(x, order=c(2,0,0), h=1) #CV for arima model
    sqrt(mean(e^2, na.rm=TRUE)) # RMSE
    #h =1意味着我们只接受1步超前预报的误差。
    #(h=4)4步前进误差如下图所示。如果想评估多步预测的模型,可以使用此选项。
    

    在这里插入图片描述

    参考链接:https://www.analyticsvidhya.com/blog/2018/05/improve-model-performance-cross-validation-in-python-r/
    其他网上找到的有关文章:
    关于时间序列的:https://zhuanlan.zhihu.com/p/99674163
    关于对抗验证的:https://zhuanlan.zhihu.com/p/137580733

    展开全文
  • 3.4 选择两个UCI数据集,比较10折交叉验证法和留一法所估计出的对率回归的错误率 (这里只选择了UCI的iris数据集:https://archive.ics.uci.edu/ml/index.php) 理论知识:笔记(二)机器学习(周志华)第2章 模型...

    同时也是 第3章 线性模型 3.4答案 

    3.4 选择两个UCI数据集,比较10折交叉验证法和留一法所估计出的对率回归的错误率

    (这里只选择了UCI的iris数据集:https://archive.ics.uci.edu/ml/index.php

    理论知识:笔记(二)机器学习(周志华)第2章 模型选择和评估——交叉验证

                      笔记(三)机器学习(周志华)第3章 线性模型——对率回归

    import pandas as pd
    from sklearn import datasets
    from sklearn.linear_model import LogisticRegression
    from sklearn.model_selection import cross_val_predict, cross_val_score, LeaveOneOut, KFold, StratifiedKFold
    from sklearn.metrics import accuracy_score
    from numpy import *
    
    # 加载数据
    def loadDataSet():
        # iris = datasets.load_iris()
        # xArr = iris.data   # (150, 4) <class 'numpy.ndarray'>
        # labels = iris.target  # (150,) 数字。从UCI下载的数据lable是字符需要转换
    
        raw_data = pd.read_csv('iris.data', header=None)
        xArr = raw_data.values[:, 0:4]  # <class 'numpy.ndarray'>
        labels = raw_data.values[:, -1]
        labels[labels == 'Iris-setosa'] = 0
        labels[labels == 'Iris-versicolor'] = 1
        labels[labels == 'Iris-virginica'] = 2
        # for i in range(len(labels)):
        #     if labels[i] == 'Iris-setosa':
        #         labels[i] = 0
        #     elif labels[i] == 'Iris-versicolor':
        #         labels[i] = 1
        #     else:
        #         labels[i] = 2
        return xArr, labels
    
    # 训练模型
    logistModel = LogisticRegression()
    
    def crossValidation(xArr, labels):
        score = (cross_val_score(logistModel, xArr, labels, cv=10)).mean()  # 每次的得分组成的数组(10,)。 没有shuffle功能
        # 等价于下面两句:
        # y_pred = cross_val_predict(logistModel, xArr, labels, cv=10)
        # score = accuracy_score(y_pred, labels)  # 十次交叉验证平均值
        return score
    
    # KFold+cross_val_score 具有shuffle功能
    def kFold(x, y):
        kf = KFold(n_splits=10, shuffle=True, random_state=None)  # random_state=None 结果不唯一
        score = (cross_val_score(logistModel, x, y, cv=kf, scoring='precision_macro')).mean()
        return score   #
    
    # 分层采样k折交叉切分
    def stratifiedKFold(x, y):
        skf = StratifiedKFold(n_splits=10, shuffle=True, random_state=1)
        score = (cross_val_score(logistModel, x, y, cv=skf)).mean()
        return score
    
    # 留一法
    def LOO(x, y):
        loo = LeaveOneOut()
        # loo划分数据方法: loo.split(x)
        accCount = 0
        for train, test in loo.split(x):
            # print(train, '==', test)  # [1..149]==[0]  [0 2 ...149]==[1] ....
            logistModel.fit(x[train], y[train])
            y_pred = logistModel.predict(x[test])
            if y_pred == y[test]:
                accCount += 1
        aveScore = accCount / x.shape[0]
        return aveScore
    
    if __name__ == '__main__':
        xArr, labels = loadDataSet()
        # logistModel.fit(xArr, labels)  # ValueError: Unknown label type: 'unknown' sklearn无法识别它的类型,y=y.astype('int')
        labels = labels.astype('int')
    
        cv_score = crossValidation(xArr, labels)
        print(cv_score)  # accuracy
    
        loo_score = LOO(xArr, labels)
        print(loo_score)  # accuracy
    
        kf_score = kFold(xArr, labels)
        print(kf_score)  # precision_macro
    
        skf_score = stratifiedKFold(xArr, labels)
        print(skf_score)

     

    展开全文
  • 全栈工程师开发手册 (作者:栾鹏) python数据挖掘系列教程 学习预测函数的参数,并在相同数据集上进行测试是一种错误的做法: 一个仅给出测试用例标签的模型将会获得极高的分数,但对于尚未出现过的数据它则...

    分享一个朋友的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!大家可以看看是否对自己有帮助:点击打开

    docker/kubernetes入门视频教程


    全栈工程师开发手册 (作者:栾鹏)
    python数据挖掘系列教程

    学习预测函数的参数,并在相同数据集上进行测试是一种错误的做法: 一个仅给出测试用例标签的模型将会获得极高的分数,但对于尚未出现过的数据它则无法预测出任何有用的信息。 这种情况称为 overfitting(过拟合). 为了避免这种情况,在进行(监督)机器学习实验时,通常取出部分可利用数据作为 test set(测试数据集) X_test, y_test。

    利用 scikit-learn 包中的 train_test_split 辅助函数可以很快地将实验数据集划分为任何训练集(training sets)和测试集(test sets)。

    计算交叉验证的指标

    使用交叉验证最简单的方法是在估计器和数据集上调用 cross_val_score 辅助函数。

    保留数据的数据转换

    正如在训练集中保留的数据上测试一个 predictor (预测器)是很重要的一样,预处理(如标准化,特征选择等)和类似的 data transformations 也应该从训练集中学习,并应用于预测数据以进行预测

    cross_validate 函数和多度量评估

    cross_validate 函数与 cross_val_score 在下面的两个方面有些不同 -

    • 它允许指定多个指标进行评估.
    • 除了测试得分之外,它还会返回一个包含训练得分,拟合次数, score-times (得分次数)的一个字典。

    交叉验证迭代器

    K折交叉验证KFold 将所有的样例划分为 k 个组,称为折叠 (fold) (如果 k = n, 这等价于 Leave One Out(留一) 策略),都具有相同的大小(如果可能)。预测函数学习时使用 k - 1 个折叠中的数据,最后一个剩下的折叠会用于测试。

    K折重复多次RepeatedKFold 重复 K-Fold n 次。当需要运行时可以使用它 KFold n 次,在每次重复中产生不同的分割。

    留一交叉验证LeaveOneOut (或 LOO) 是一个简单的交叉验证。每个学习集都是通过除了一个样本以外的所有样本创建的,测试集是被留下的样本。 因此,对于 n 个样本,我们有 n 个不同的训练集和 n 个不同的测试集。这种交叉验证程序不会浪费太多数据,因为只有一个样本是从训练集中删除掉的:

    留P交叉验证LeavePOut 与 LeaveOneOut 非常相似,因为它通过从整个集合中删除 p 个样本来创建所有可能的 训练/测试集。对于 n 个样本,这产生了 {n \choose p} 个 训练-测试 对。与 LeaveOneOut 和 KFold 不同,当 p > 1 时,测试集会重叠。

    用户自定义数据集划分ShuffleSplit 迭代器将会生成一个用户给定数量的独立的训练/测试数据划分。样例首先被打散然后划分为一对训练测试集合。

    设置每次生成的随机数相同: 可以通过设定明确的 random_state ,使得伪随机生成器的结果可以重复。

    基于类标签、具有分层的交叉验证迭代器

    如何解决样本不平衡问题? 使用StratifiedKFold和StratifiedShuffleSplit 分层抽样。 一些分类问题在目标类别的分布上可能表现出很大的不平衡性:例如,可能会出现比正样本多数倍的负样本。在这种情况下,建议采用如 StratifiedKFold 和 StratifiedShuffleSplit 中实现的分层抽样方法,确保相对的类别频率在每个训练和验证 折叠 中大致保留。

    StratifiedKFold 是 k-fold 的变种,会返回 stratified(分层) 的折叠:每个小集合中, 各个类别的样例比例大致和完整数据集中相同。

    StratifiedShuffleSplit 是 ShuffleSplit 的一个变种,会返回直接的划分,比如: 创建一个划分,但是划分中每个类的比例和完整数据集中的相同。

    用于分组数据的交叉验证迭代器

    如何进一步测试模型的泛化能力? **留出一组特定的不属于测试集和训练集的数据。**有时我们想知道在一组特定的 groups 上训练的模型是否能很好地适用于看不见的 group 。为了衡量这一点,我们需要确保验证对象中的所有样本来自配对训练折叠中完全没有表示的组。

    GroupKFold 是 k-fold 的变体,它确保同一个 group 在测试和训练集中都不被表示。 例如,如果数据是从不同的 subjects 获得的,每个 subject 有多个样本,并且如果模型足够灵活以高度人物指定的特征中学习,则可能无法推广到新的 subject 。 GroupKFold 可以检测到这种过拟合的情况。

    LeaveOneGroupOut 是一个交叉验证方案,它根据第三方提供的 array of integer groups (整数组的数组)来提供样本。这个组信息可以用来编码任意域特定的预定义交叉验证折叠。

    每个训练集都是由除特定组别以外的所有样本构成的。

    LeavePGroupsOut 类似于 LeaveOneGroupOut ,但为每个训练/测试集删除与 P 组有关的样本。

    GroupShuffleSplit 迭代器是 ShuffleSplit 和 LeavePGroupsOut 的组合,它生成一个随机划分分区的序列,其中为每个分组提供了一个组子集。

    时间序列分割

    TimeSeriesSplit 是 k-fold 的一个变体,它首先返回 k 折作为训练数据集,并且 (k+1) 折作为测试数据集。 请注意,与标准的交叉验证方法不同,连续的训练集是超越前者的超集。 另外,它将所有的剩余数据添加到第一个训练分区,它总是用来训练模型。

    这个类可以用来交叉验证以固定时间间隔观察到的时间序列数据样本。

    代码实现

    from sklearn.model_selection import train_test_split,cross_val_score,cross_validate # 交叉验证所需的函数
    from sklearn.model_selection import KFold,LeaveOneOut,LeavePOut,ShuffleSplit # 交叉验证所需的子集划分方法
    from sklearn.model_selection import StratifiedKFold,StratifiedShuffleSplit # 分层分割
    from sklearn.model_selection import GroupKFold,LeaveOneGroupOut,LeavePGroupsOut,GroupShuffleSplit # 分组分割
    from sklearn.model_selection import TimeSeriesSplit # 时间序列分割
    from sklearn import datasets  # 自带数据集
    from sklearn import svm  # SVM算法
    from sklearn import preprocessing  # 预处理模块
    from sklearn.metrics import recall_score  # 模型度量
    
    iris = datasets.load_iris()  # 加载数据集
    print('样本集大小:',iris.data.shape,iris.target.shape)
    
    # ===================================数据集划分,训练模型==========================
    X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.4, random_state=0)  # 交叉验证划分训练集和测试集.test_size为测试集所占的比例
    print('训练集大小:',X_train.shape,y_train.shape)  # 训练集样本大小
    print('测试集大小:',X_test.shape,y_test.shape)  # 测试集样本大小
    clf = svm.SVC(kernel='linear', C=1).fit(X_train, y_train) # 使用训练集训练模型
    print('准确率:',clf.score(X_test, y_test))  # 计算测试集的度量值(准确率)
    
    
    #  如果涉及到归一化,则在测试集上也要使用训练集模型提取的归一化函数。
    scaler = preprocessing.StandardScaler().fit(X_train)  # 通过训练集获得归一化函数模型。(也就是先减几,再除以几的函数)。在训练集和测试集上都使用这个归一化函数
    X_train_transformed = scaler.transform(X_train)
    clf = svm.SVC(kernel='linear', C=1).fit(X_train_transformed, y_train) # 使用训练集训练模型
    X_test_transformed = scaler.transform(X_test)
    print(clf.score(X_test_transformed, y_test))  # 计算测试集的度量值(准确度)
    
    # ===================================直接调用交叉验证评估模型==========================
    clf = svm.SVC(kernel='linear', C=1)
    scores = cross_val_score(clf, iris.data, iris.target, cv=5)  #cv为迭代次数。
    print(scores)  # 打印输出每次迭代的度量值(准确度)
    print("Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))  # 获取置信区间。(也就是均值和方差)
    
    # ===================================多种度量结果======================================
    scoring = ['precision_macro', 'recall_macro'] # precision_macro为精度,recall_macro为召回率
    scores = cross_validate(clf, iris.data, iris.target, scoring=scoring,cv=5, return_train_score=True)
    sorted(scores.keys())
    print('测试结果:',scores)  # scores类型为字典。包含训练得分,拟合次数, score-times (得分次数)
    
    
    # ==================================K折交叉验证、留一交叉验证、留p交叉验证、随机排列交叉验证==========================================
    # k折划分子集
    kf = KFold(n_splits=2)
    for train, test in kf.split(iris.data):
        print("k折划分:%s %s" % (train.shape, test.shape))
        break
    
    # 留一划分子集
    loo = LeaveOneOut()
    for train, test in loo.split(iris.data):
        print("留一划分:%s %s" % (train.shape, test.shape))
        break
    
    # 留p划分子集
    lpo = LeavePOut(p=2)
    for train, test in loo.split(iris.data):
        print("留p划分:%s %s" % (train.shape, test.shape))
        break
    
    # 随机排列划分子集
    ss = ShuffleSplit(n_splits=3, test_size=0.25,random_state=0)
    for train_index, test_index in ss.split(iris.data):
        print("随机排列划分:%s %s" % (train.shape, test.shape))
        break
    
    # ==================================分层K折交叉验证、分层随机交叉验证==========================================
    skf = StratifiedKFold(n_splits=3)  #各个类别的比例大致和完整数据集中相同
    for train, test in skf.split(iris.data, iris.target):
        print("分层K折划分:%s %s" % (train.shape, test.shape))
        break
    
    skf = StratifiedShuffleSplit(n_splits=3)  # 划分中每个类的比例和完整数据集中的相同
    for train, test in skf.split(iris.data, iris.target):
        print("分层随机划分:%s %s" % (train.shape, test.shape))
        break
    
    
    # ==================================组 k-fold交叉验证、留一组交叉验证、留 P 组交叉验证、Group Shuffle Split==========================================
    X = [0.1, 0.2, 2.2, 2.4, 2.3, 4.55, 5.8, 8.8, 9, 10]
    y = ["a", "b", "b", "b", "c", "c", "c", "d", "d", "d"]
    groups = [1, 1, 1, 2, 2, 2, 3, 3, 3, 3]
    
    # k折分组
    gkf = GroupKFold(n_splits=3)  # 训练集和测试集属于不同的组
    for train, test in gkf.split(X, y, groups=groups):
        print("组 k-fold分割:%s %s" % (train, test))
    
    # 留一分组
    logo = LeaveOneGroupOut()
    for train, test in logo.split(X, y, groups=groups):
        print("留一组分割:%s %s" % (train, test))
    
    # 留p分组
    lpgo = LeavePGroupsOut(n_groups=2)
    for train, test in lpgo.split(X, y, groups=groups):
        print("留 P 组分割:%s %s" % (train, test))
    
    # 随机分组
    gss = GroupShuffleSplit(n_splits=4, test_size=0.5, random_state=0)
    for train, test in gss.split(X, y, groups=groups):
        print("随机分割:%s %s" % (train, test))
    
    
    # ==================================时间序列分割==========================================
    tscv = TimeSeriesSplit(n_splits=3)
    TimeSeriesSplit(max_train_size=None, n_splits=3)
    for train, test in tscv.split(iris.data):
        print("时间序列分割:%s %s" % (train, test))
    
    展开全文
  • keras实现交叉验证以及K折交叉验证

    千次阅读 2019-09-18 20:25:36
    三.K折交叉验证k-fold cross validation) 在训练深度学习模型的时候,通常将数据集切分为训练集和验证集.Keras提供了两种评估模型性能的方法: 使用自动切分的验证集 使用手动切分的验证集 ...

    原文来自https://www.cnblogs.com/bymo/p/9026198.html

    记下来,以便以后忘记了可以找到

    目录

     


    在训练深度学习模型的时候,通常将数据集切分为训练集和验证集.Keras提供了两种评估模型性能的方法:

    • 使用自动切分的验证集
    • 使用手动切分的验证集

     

    回到顶部

    一.自动切分

    在Keras中,可以从数据集中切分出一部分作为验证集,并且在每次迭代(epoch)时在验证集中评估模型的性能.

    具体地,调用model.fit()训练模型时,可通过validation_split参数来指定从数据集中切分出验证集的比例.

    # MLP with automatic validation set
    from keras.models import Sequential
    from keras.layers import Dense
    import numpy
    # fix random seed for reproducibility
    numpy.random.seed(7)
    # load pima indians dataset
    dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",")
    # split into input (X) and output (Y) variables
    X = dataset[:,0:8]
    Y = dataset[:,8]
    # create model
    model = Sequential()
    model.add(Dense(12, input_dim=8, activation='relu'))
    model.add(Dense(8, activation='relu'))
    model.add(Dense(1, activation='sigmoid'))
    # Compile model
    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    # Fit the model
    model.fit(X, Y, validation_split=0.33, epochs=150, batch_size=10)

    validation_split:0~1之间的浮点数,用来指定训练集的一定比例数据作为验证集。验证集将不参与训练,并在每个epoch结束后测试的模型的指标,如损失函数、精确度等。

    注意,validation_split的划分在shuffle之前,因此如果你的数据本身是有序的,需要先手工打乱再指定validation_split,否则可能会出现验证集样本不均匀。 

     

    回到顶部

    二.手动切分

    Keras允许在训练模型的时候手动指定验证集.

    例如,用sklearn库中的train_test_split()函数将数据集进行切分,然后在kerasmodel.fit()的时候通过validation_data参数指定前面切分出来的验证集.

     

    # MLP with manual validation set
    from keras.models import Sequential
    from keras.layers import Dense
    from sklearn.model_selection import train_test_split
    import numpy
    # fix random seed for reproducibility
    seed = 7
    numpy.random.seed(seed)
    # load pima indians dataset
    dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",")
    # split into input (X) and output (Y) variables
    X = dataset[:,0:8]
    Y = dataset[:,8]
    # split into 67% for train and 33% for test
    X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.33, random_state=seed)
    # create model
    model = Sequential()
    model.add(Dense(12, input_dim=8, activation='relu'))
    model.add(Dense(8, activation='relu'))
    model.add(Dense(1, activation='sigmoid'))
    # Compile model
    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    # Fit the model
    model.fit(X_train, y_train, validation_data=(X_test,y_test), epochs=150, batch_size=10)

    回到顶部

    三.K折交叉验证(k-fold cross validation)

    将数据集分成k份,每一轮用其中(k-1)份做训练而剩余1份做验证,以这种方式执行k轮,得到k个模型.将k次的性能取平均,作为该算法的整体性能.k一般取值为5或者10.

    • 优点:能比较鲁棒性地评估模型在未知数据上的性能.
    • 缺点:计算复杂度较大.因此,在数据集较大,模型复杂度较高,或者计算资源不是很充沛的情况下,可能不适用,尤其是在训练深度学习模型的时候.

    sklearn.model_selection提供了KFold以及RepeatedKFold, LeaveOneOut, LeavePOut, ShuffleSplit, StratifiedKFold, GroupKFold, TimeSeriesSplit等变体.

    下面的例子中用的StratifiedKFold采用的是分层抽样,它保证各类别的样本在切割后每一份小数据集中的比例都与原数据集中的比例相同.

    # MLP for Pima Indians Dataset with 10-fold cross validation
    from keras.models import Sequential
    from keras.layers import Dense
    from sklearn.model_selection import StratifiedKFold
    import numpy
    # fix random seed for reproducibility
    seed = 7
    numpy.random.seed(seed)
    # load pima indians dataset
    dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",")
    # split into input (X) and output (Y) variables
    X = dataset[:,0:8]
    Y = dataset[:,8]
    # define 10-fold cross validation test harness
    kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=seed)
    cvscores = []
    for train, test in kfold.split(X, Y):
      # create model
        model = Sequential()
        model.add(Dense(12, input_dim=8, activation='relu'))
        model.add(Dense(8, activation='relu'))
        model.add(Dense(1, activation='sigmoid'))
        # Compile model
        model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
        # Fit the model
        model.fit(X[train], Y[train], epochs=150, batch_size=10, verbose=0)
        # evaluate the model
        scores = model.evaluate(X[test], Y[test], verbose=0)
        print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))
        cvscores.append(scores[1] * 100)
    print("%.2f%% (+/- %.2f%%)" % (numpy.mean(cvscores), numpy.std(cvscores)))

     

    展开全文
  • k折交叉验证sklearn中的StratifiedKFold

    千次阅读 2019-07-09 21:31:05
    交叉验证交叉验证k折交叉验证StratifiedKFold实例code 交叉验证 交叉验证的基本思想是把在某种意义下将原始数据(dataset)进行分组,一部分做为训练集(train set),另一部分做为验证集(validation set or test set),...
  • k折交叉验证

    万次阅读 2018-06-14 19:21:04
    一般情况将K折交叉验证用于模型调优,找到使得模型泛化性能最优的超参值。,找到后,在全部训练集上重新训练模型,并使用独立测试集对模型性能做出最终评价。 K折交叉验证使用了无重复抽样技术的好处:每次迭代过程...
  • 如何实现分层k折交叉验证如何实现分层k折交叉验证(文字版)如何实现分层k折交叉验证(图片版)如何实现分层K折交叉验证(matlab版) 很多论文都会用到K折交叉验证,但是以前一直没有做这个操作,所以最近整理了一下关于...
  • 之前使用train_test_split函数将数据集随机划分为训练集和测试集,然后使用score方法评估...标准k折交叉检验:回归问题默认使用。根据用户指定的k划分数据,经历k次训练测试,每次一折当测试集其它的是训练集。 分层
  • 1. 什么是交叉验证 交叉验证(Cross-validation)主要用于...而我们常用的就是K折交叉验证K折就是讲数据集切分成K小块,验证集和测试集相互形成补集,循环交替,它有效的避免过学习以及欠学习状态的发生,最后得到的...
  •   模型在统计中是极其重要的,可以通过模型来描述数据集的内在关系,了解数据的内在关系有助于对未来进行预测。一个模型可以通过设置不同的参数来描述不同的数据集,有的参数需要根据数据集估计,有的参数需要人为...
  • 来源: ...   对于解决同一个问题,如怎么选择模型去拟合线性回归中只有一个特征时房价预测问题,如可能有不同的模型去解决,如: 1、d = 1,h(θ) = θ0+θ1x 2、d = 2,h(θ) = θ0+θ1x+θ2x^2 ...
  • 在机器学习中,将数据集A分为训练集B(training set)和测试集C(test set),在样本量不充足的情况下,为了充分利用数据集对算法效果进行测试,将数据集A随机分为k个包,每次将其中一个包作为测试集,剩下k-1个包...
  • holdout交叉验证K折交叉验证可以得到模型的泛化误差的可靠估计(模型在新数据集是的性能表现)。 holdout交叉验证 holdout交叉验证是机器学习模型泛化性能的一个经典且常用的方法。 holdout交叉验证能...
  • K折交叉验证代码示例

    千次阅读 2018-11-20 17:26:59
    Stratified k-fold 按照百分比划分数据。 import pandas as pd import numpy as np import jieba from util import * from sklearn.feature_extraction.text import CountVectorizer, HashingVectorizer, ...
  • k折交叉验证概述-附R语言实现

    千次阅读 2019-03-02 23:09:55
    k折交叉验证交叉验证方法中的一种(是进行模型比较的有效方法),将整体数据集分为k份(每份近似相等),其中k-1份作为训练数据,另外一份作为验证数据集,并计算预测误差平方和。用验证集来验证所得分类器或模型的...
  • K折交叉验证

    千次阅读 2018-11-29 10:57:25
    写在开头:最近参加了DF的数据竞赛,发现了交叉验证的强大之处。计算时间会长很多但是真的可以把准确率提高很多!这里有对交叉验证很好的解释:知乎专栏:Cross-Validation详解 总结 :为什么要使用交叉验证? ...
1 2 3 4 5 ... 20
收藏数 3,657
精华内容 1,462
关键字:

分层k折交叉验证