pytorch K折交叉验证过程说明及实现方式

目录
  • K折交叉交叉验证的过程如下
  • 交叉验证区分k折代码分析
  • 总结

K折交叉交叉验证的过程如下

以200条数据,十折交叉验证为例子,十折也就是将数据分成10组,进行10组训练,每组用于测试的数据为:数据总条数/组数,即每组20条用于valid,180条用于train,每次valid的都是不同的。

(1)将200条数据,分成按照 数据总条数/组数(折数),进行切分。然后取出第i份作为第i次的valid,剩下的作为train

(2)将每组中的train数据利用DataLoader和Dataset,进行封装。

(3)将train数据用于训练,epoch可以自己定义,然后利用valid做验证。得到一次的train_loss和 valid_loss。

(4)重复(2)(3)步骤,得到最终的 averge_train_loss和averge_valid_loss

上述过程如下图所示:

上述的代码如下:

import torch
import torch.nn as nn
from torch.utils.data import DataLoader,Dataset
import torch.nn.functional as F
from torch.autograd import Variable

#####构造的训练集####
x = torch.rand(100,28,28)
y = torch.randn(100,28,28)
x = torch.cat((x,y),dim=0)
label =[1] *100 + [0]*100
label = torch.tensor(label,dtype=torch.long)

######网络结构##########
class Net(nn.Module):
    #定义Net
    def __init__(self):
        super(Net, self).__init__() 

        self.fc1   = nn.Linear(28*28, 120)
        self.fc2   = nn.Linear(120, 84)
        self.fc3   = nn.Linear(84, 2)

    def forward(self, x):

        x = x.view(-1, self.num_flat_features(x)) 

        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x
    def num_flat_features(self, x):
        size = x.size()[1:]
        num_features = 1
        for s in size:
            num_features *= s
        return num_features

##########定义dataset##########
class TraindataSet(Dataset):
    def __init__(self,train_features,train_labels):
        self.x_data = train_features
        self.y_data = train_labels
        self.len = len(train_labels)

    def __getitem__(self,index):
        return self.x_data[index],self.y_data[index]
    def __len__(self):
        return self.len

########k折划分############
def get_k_fold_data(k, i, X, y):  ###此过程主要是步骤(1)
    # 返回第i折交叉验证时所需要的训练和验证数据,分开放,X_train为训练数据,X_valid为验证数据
    assert k > 1
    fold_size = X.shape[0] // k  # 每份的个数:数据总条数/折数(组数)

    X_train, y_train = None, None
    for j in range(k):
        idx = slice(j * fold_size, (j + 1) * fold_size)  #slice(start,end,step)切片函数
        ##idx 为每组 valid
        X_part, y_part = X[idx, :], y[idx]
        if j == i: ###第i折作valid
            X_valid, y_valid = X_part, y_part
        elif X_train is None:
            X_train, y_train = X_part, y_part
        else:
            X_train = torch.cat((X_train, X_part), dim=0) #dim=0增加行数,竖着连接
            y_train = torch.cat((y_train, y_part), dim=0)
    #print(X_train.size(),X_valid.size())
    return X_train, y_train, X_valid,y_valid

def k_fold(k, X_train, y_train, num_epochs=3,learning_rate=0.001, weight_decay=0.1, batch_size=5):
    train_loss_sum, valid_loss_sum = 0, 0
    train_acc_sum ,valid_acc_sum = 0,0

    for i in range(k):
        data = get_k_fold_data(k, i, X_train, y_train) # 获取k折交叉验证的训练和验证数据
        net =  Net()  ### 实例化模型
        ### 每份数据进行训练,体现步骤三####
        train_ls, valid_ls = train(net, *data, num_epochs, learning_rate,\
                                   weight_decay, batch_size) 

        print('*'*25,'第',i+1,'折','*'*25)
        print('train_loss:%.6f'%train_ls[-1][0],'train_acc:%.4f\n'%valid_ls[-1][1],\
              'valid loss:%.6f'%valid_ls[-1][0],'valid_acc:%.4f'%valid_ls[-1][1])
        train_loss_sum += train_ls[-1][0]
        valid_loss_sum += valid_ls[-1][0]
        train_acc_sum += train_ls[-1][1]
        valid_acc_sum += valid_ls[-1][1]
    print('#'*10,'最终k折交叉验证结果','#'*10)
    ####体现步骤四#####
    print('train_loss_sum:%.4f'%(train_loss_sum/k),'train_acc_sum:%.4f\n'%(train_acc_sum/k),\
          'valid_loss_sum:%.4f'%(valid_loss_sum/k),'valid_acc_sum:%.4f'%(valid_acc_sum/k))

#########训练函数##########
def train(net, train_features, train_labels, test_features, test_labels, num_epochs, learning_rate,weight_decay, batch_size):
    train_ls, test_ls = [], [] ##存储train_loss,test_loss
    dataset = TraindataSet(train_features, train_labels)
    train_iter = DataLoader(dataset, batch_size, shuffle=True)
    ### 将数据封装成 Dataloder 对应步骤(2)

    #这里使用了Adam优化算法
    optimizer = torch.optim.Adam(params=net.parameters(), lr= learning_rate, weight_decay=weight_decay)

    for epoch in range(num_epochs):
        for X, y in train_iter:  ###分批训练
            output  = net(X)
            loss = loss_func(output,y)
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
        ### 得到每个epoch的 loss 和 accuracy
        train_ls.append(log_rmse(0,net, train_features, train_labels))
        if test_labels is not None:
            test_ls.append(log_rmse(1,net, test_features, test_labels))
    #print(train_ls,test_ls)
    return train_ls, test_ls

def log_rmse(flag,net,x,y):
    if flag == 1: ### valid 数据集
        net.eval()
    output = net(x)
    result = torch.max(output,1)[1].view(y.size())
    corrects = (result.data == y.data).sum().item()
    accuracy = corrects*100.0/len(y)  #### 5 是 batch_size
    loss = loss_func(output,y)
    net.train()

    return (loss.data.item(),accuracy)

loss_func = nn.CrossEntropyLoss() ###申明loss函
k_fold(10,x,label) ### k=10,十折交叉验证

上述代码中,直接按照顺序从x中每次截取20条作为valid,也可以先打乱然后在截取,这样效果应该会更好。

如下所示:

import random
import torch

x = torch.rand(100,28,28)
y = torch.randn(100,28,28)
x = torch.cat((x,y),dim=0)
label =[1] *100 + [0]*100
label = torch.tensor(label,dtype=torch.long)

index = [i for i in range(len(x))]
random.shuffle(index)
x = x[index]
label = label[index]

交叉验证区分k折代码分析

from  sklearn.model_selection import GroupKFold
x = np.array([1,2,3,4,5,6,7,8,9,10])
y = np.array([1,2,3,4,5,6,7,8,9,10])
z = np.array(['hello1','hello2','hello3','hello4','hello5','hello6','hello7','hello8','hello9','hello10'])
gkf = GroupKFold(n_splits = 5)
for  i,(train_idx,valid_idx) in enumerate(list(gkf.split(x,y,z))):
#groups:object,Always ignored,exists for compatibility.
    print('train_idx = ')
    print(train_idx)
    print('valid_idx = ')
    print(valid_idx)

可以看出来首先train_idx以及valid_idx的相应值都是从中乱序提取的,其次每个相应值只提取一次,不会重复提取。

注意交叉验证的流程:这里首先放一个对应的交叉验证的图片:

注意这里的训练方式是每个初始化的模型分别训练n折的数值,然后算出对应的权重内容

也就是说这里每一次计算对应的权重内容(1~n)的时候,需要将模型的权重初始化,然后再进行训练,训练最终结束之后,模型的权重为训练完成之后的平均值,多模类似于模型融合

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Python实现K折交叉验证法的方法步骤

    学习器在测试集上的误差我们通常称作"泛化误差".要想得到"泛化误差"首先得将数据集划分为训练集和测试集.那么怎么划分呢?常用的方法有两种,k折交叉验证法和自助法.介绍这两种方法的资料有很多.下面是k折交叉验证法的python实现. ##一个简单的2折交叉验证 from sklearn.model_selection import KFold import numpy as np X=np.array([[1,2],[3,4],[1,3],[3,5]]) Y=np.a

  • 人工智能学习pyTorch自建数据集及可视化结果实现过程

    目录 一.自定义数据集 1.文件夹映射 2.图片对应标签 3.训练及测试数据分割 4.数据处理 二.ResNet处理 三.训练及可视化 1.数据集导入 2.测试函数 3.训练过程及可视化 一.自定义数据集 现有数据如下: 5个文件夹,每个文件夹是神奇宝贝的一种. 每个图片形状.大小.格式不一. 我们训练CNN的时候需要的是tensor类型的数据,因此需要将所有的图片进行下列转换: 1.对文件夹编号,进行映射,比如妙蛙种子文件夹编号0,皮卡丘编号1等. 2.对文件夹中所有图片,进行编号的对应,这个

  • python实现K折交叉验证

    本文实例为大家分享了python实现K折交叉验证的具体代码,供大家参考,具体内容如下 用KNN算法训练iris数据,并使用K折交叉验证方法找出最优的K值 import numpy as np from sklearn import datasets from sklearn.neighbors import KNeighborsClassifier from sklearn.model_selection import KFold # 主要用于K折交叉验证 # 导入iris数据集 iris =

  • pytorch K折交叉验证过程说明及实现方式

    目录 K折交叉交叉验证的过程如下 交叉验证区分k折代码分析 总结 K折交叉交叉验证的过程如下 以200条数据,十折交叉验证为例子,十折也就是将数据分成10组,进行10组训练,每组用于测试的数据为:数据总条数/组数,即每组20条用于valid,180条用于train,每次valid的都是不同的. (1)将200条数据,分成按照 数据总条数/组数(折数),进行切分.然后取出第i份作为第i次的valid,剩下的作为train (2)将每组中的train数据利用DataLoader和Dataset,进行

  • R语言逻辑回归、ROC曲线与十折交叉验证详解

    自己整理编写的逻辑回归模板,作为学习笔记记录分享.数据集用的是14个自变量Xi,一个因变量Y的australian数据集. 1. 测试集和训练集3.7分组 australian <- read.csv("australian.csv",as.is = T,sep=",",header=TRUE) #读取行数 N = length(australian$Y) #ind=1的是0.7概率出现的行,ind=2是0.3概率出现的行 ind=sample(2,N,rep

  • sklearn和keras的数据切分与交叉验证的实例详解

    在训练深度学习模型的时候,通常将数据集切分为训练集和验证集.Keras提供了两种评估模型性能的方法: 使用自动切分的验证集 使用手动切分的验证集 一.自动切分 在Keras中,可以从数据集中切分出一部分作为验证集,并且在每次迭代(epoch)时在验证集中评估模型的性能. 具体地,调用model.fit()训练模型时,可通过validation_split参数来指定从数据集中切分出验证集的比例. # MLP with automatic validation set from keras.mode

  • R语言交叉验证的实现代码

    k-折交叉验证 k-折交叉验证(K-fold cross-validation)是交叉验证方法里一种.它是指将样本集分为k份,其中k-1份作为训练数据集,而另外的1份作为验证数据集.用验证集来验证所得分类器或者模型的错误率.一般需要循环k次,直到所有k份数据全部被选择一遍为止. 有关交叉验证的介绍可参考作者另一博文: http://blog.csdn.net/yawei_liu1688/article/details/79138202 R语言实现 K折交叉验证,随机分组 数据打折-数据分组自编译

  • sklearn中的交叉验证的实现(Cross-Validation)

    sklearn是利用python进行机器学习中一个非常全面和好用的第三方库,用过的都说好.今天主要记录一下sklearn中关于交叉验证的各种用法,主要是对sklearn官方文档 Cross-validation: evaluating estimator performance进行讲解,英文水平好的建议读官方文档,里面的知识点很详细. 先导入需要的库及数据集 In [1]: import numpy as np In [2]: from sklearn.model_selection impor

  •  分享Python 中的 7 种交叉验证方法

    目录 一.什么是交叉验证? 二.它是如何解决过拟合问题的? 1.HoldOut交叉验证 2.K折交叉验证 3.分层K折交叉验证 4.LeavePOut交叉验证 5.留一交叉验证 6.蒙特卡罗交叉验证(ShuffleSplit) 7.时间序列交叉验证 在任何有监督机器学习项目的模型构建阶段,我们训练模型的目的是从标记的示例中学习所有权重和偏差的最佳值. 如果我们使用相同的标记示例来测试我们的模型,那么这将是一个方法论错误,因为一个只会重复刚刚看到的样本标签的模型将获得完美的分数,但无法预测任何有用

  • python 留一交叉验证的实例

    目录 python 留一交叉验证 基本原理 代码实现 留一法交叉验证 Leave-One-Out Cross Validation 我们用SKlearn库来实现一下LOO python 留一交叉验证 基本原理 K折交叉验证 简单来说,K折交叉验证就是: 把数据集划分成K份,取出其中一份作为测试集,另外的K - 1份作为训练集. 通过训练集得到回归方程,再把测试集带入该回归方程,得到预测值. 计算预测值与真实值的差值的平方,得到平方损失函数(或其他的损失函数). 重复以上过程,总共得到K个回归方程

  • 详解python实现交叉验证法与留出法

    在机器学习中,我们经常在训练集上训练模型,在测试集上测试模型.最终的目标是希望我们的模型在测试集上有最好的表现. 但是,我们往往只有一个包含m个观测的数据集D,我们既要用它进行训练,又要对它进行测试.此时,我们就需要对数据集D进行划分. 对于数据集D的划分,我们尽量需要满足三个要求: 训练集样本量充足 训练模型时的计算量可以忍受 不同的划分方式会得出不同的训练集和测试集,从而得出不同的结果,我们需要消除这种影响 我们将分别介绍留出法.交叉验证法,以及各自的python实现.自助法(bootstr

随机推荐