前言

最近学到了K折交叉验证,已经迫不及待去实验一下他的效果是不是如老师讲的一样好,特此写下本文。

本文运行环境为:sklearn、pytorch 、jupyter notebook


k折交叉验证介绍

五折交叉验证: 把数据平均分成5等份,每次实验拿一份做测试,其余用做训练。实验5次求平均值。如上图,第一次实验拿第一份做测试集,其余作为训练集。第二次实验拿第二份做测试集,其余做训练集。依此类推~


baseline基础模型演示

先看一个最简单的,朴实无华,什么tricks都没加的基础模型。

(1)导入包


#---------------------------------Torch Modules --------------------------------------------------------
from __future__ import print_function
import numpy as np
import pandas as pd
import torch.nn as nn
import math
import torch.nn.functional as F
import torch
import torchvision
from torch.nn import init
import torch.optim as optim
from torchvision import datasets, transforms
from torchvision import models
import torch.nn.functional as F
from torch.utils import data
import matplotlib.pyplot as plt
import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"

(2) 设定一些初始值


###-----------------------------------variables-----------------------------------------------
# for Normalization
mean = [0.5]
std = [0.5]
# batch size
BATCH_SIZE =128
Iterations = 1        # epoch
learning_rate = 0.01

(3)加载数据集


##-----------------------------------Commands to download and perpare the MNIST dataset ------------------------------------
train_transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize(mean, std)])test_transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize(mean, std)])train_loader = torch.utils.data.DataLoader(datasets.MNIST('./mnist', train=True, download=True,transform=train_transform),batch_size=BATCH_SIZE, shuffle=True) # train datasettest_loader = torch.utils.data.DataLoader(datasets.MNIST('./mnist', train=False, transform=test_transform),batch_size=BATCH_SIZE, shuffle=False) # test dataset

transforms是用来增强数据集的,例如:旋转,裁剪....等等

(4)可视化数据集


#visualization
def show_images(imgs, num_rows, num_cols, titles=None, scale=1.5): """Plot a list of images."""figsize = (num_cols * scale, num_rows * scale)_, axes = plt.subplots(num_rows, num_cols, figsize=figsize)axes = axes.flatten()for i, (ax, img) in enumerate(zip(axes, imgs)):if torch.is_tensor(img):# Tensor Imageax.imshow(img.numpy())else:# PIL Imageax.imshow(img)ax.axes.get_xaxis().set_visible(False)ax.axes.get_yaxis().set_visible(False)if titles:ax.set_title(titles[i])return axes
mnist_train = torchvision.datasets.MNIST(root="../data", train=True,
transform=train_transform,
download=True)
X, y = next(iter(data.DataLoader(mnist_train, batch_size=18)))
show_images(X.reshape(18, 28, 28), 2, 9)

【output】输出 

(5)加载模型、优化器与损失函数


model = nn.Sequential(nn.Flatten(), nn.Linear(784, 256), nn.ReLU(),nn.Linear(256, 10))
def init_weights(m):if type(m) == nn.Linear:nn.init.normal_(m.weight, std=0.01)
model.apply(init_weights);## Loss function
criterion = torch.nn.CrossEntropyLoss() # pytorch's cross entropy loss function# definin which paramters to train only the CNN model parameters
optimizer = torch.optim.SGD(model.parameters(),learning_rate)

(6)训练函数


# defining the training function
# Train baseline classifier on clean data
def train(model, optimizer,criterion,epoch): model.train() # setting up for trainingfor batch_idx, (data, target) in enumerate(train_loader): # data contains the image and target contains the label = 0/1/2/3/4/5/6/7/8/9data = data.view(-1, 28*28).requires_grad_()optimizer.zero_grad() # setting gradient to zerooutput = model(data) # forwardloss = criterion(output, target) # loss computationloss.backward() # back propagation here pytorch will take care of itoptimizer.step() # updating the weight valuesif batch_idx % 100 == 0:print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(epoch, batch_idx * len(data), len(train_loader.dataset),100. * batch_idx / len(train_loader), loss.item()))

(7)测试函数


# to evaluate the model
## validation of test accuracy
def test(model, criterion, val_loader, epoch,train= False):    model.eval()test_loss = 0correct = 0  with torch.no_grad():for batch_idx, (data, target) in enumerate(val_loader):data = data.view(-1, 28*28).requires_grad_()output = model(data)test_loss += criterion(output, target).item() # sum up batch losspred = output.max(1, keepdim=True)[1] # get the index of the max log-probabilitycorrect += pred.eq(target.view_as(pred)).sum().item() # if pred == target then correct +=1test_loss /= len(val_loader.dataset) # average test lossif train == False:print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.4f}%)\n'.format(test_loss, correct, val_loader.sampler.__len__(),100. * correct / val_loader.sampler.__len__() ))if train == True:print('\nTrain set: Average loss: {:.4f}, Accuracy: {}/{} ({:.4f}%)\n'.format(test_loss, correct, val_loader.sampler.__len__(),100. * correct / val_loader.sampler.__len__() ))return 100. * correct / val_loader.sampler.__len__() 

(8)训练、测试并且评估baseline模型


test_acc = torch.zeros([Iterations])
train_acc = torch.zeros([Iterations])
## training the logistic model
for i in range(Iterations):train(model, optimizer,criterion,i)train_acc[i] = test(model, criterion, train_loader, i,train=True) #Testing the the current CNNtest_acc[i] = test(model, criterion, test_loader, i)torch.save(model,'perceptron.pt')

【output】

我们可以看到准确率不是很高,甚至可以说模型鲁棒性表现的不好,才83%。那么接下来就是我们的重头戏了,我们现在打算使用k折交叉验证,需要修改什么地方呢?

  • Step1、修改数据集
  • Step2、设定k值
  • Step3、重新训练

【重点】实现K折交叉验证

NOTE:只需要在最下方插入这一行代码即可,会覆盖掉之前的变量,而且因为是在函数内部运行,与之前的代码没有冲突。

(1)【难点:Fold的数据集处理】


#!pip install sklearn -i https://pypi.mirrors.ustc.edu.cn/simple
from sklearn.model_selection import KFold
train_init = datasets.MNIST('./mnist', train=True,transform=train_transform)test_init =  datasets.MNIST('./mnist', train=False, transform=test_transform)# the dataset for k fold cross validation
dataFold = torch.utils.data.ConcatDataset([train_init, test_init])def train_flod_Mnist(k_split_value):different_k_mse = []kf = KFold(n_splits=k_split_value,shuffle=True, random_state=0)  # init KFoldfor train_index , test_index in kf.split(dataFold):  # split  # get train, val train_fold = torch.utils.data.dataset.Subset(dataFold, train_index)test_fold = torch.utils.data.dataset.Subset(dataFold, test_index) # package type of DataLoadertrain_loader = torch.utils.data.DataLoader(dataset=train_fold, batch_size=BATCH_SIZE, shuffle=True)test_loader = torch.utils.data.DataLoader(dataset=test_fold, batch_size=BATCH_SIZE, shuffle=True)# train modeltest_acc = torch.zeros([Iterations])train_acc = torch.zeros([Iterations])## training the logistic modelfor i in range(Iterations):train(model, optimizer,criterion,i)train_acc[i] = test(model, criterion, train_loader, i,train=True) #Testing the the current CNNtest_acc[i] = test(model, criterion, test_loader, i)#torch.save(model,'perceptron.pt')# one epoch, all accdifferent_k_mse.append(np.array(test_acc))return different_k_mse

上面这个代码,解决的重点有哪些呢?

一是将这个Mnist数据集的训练集和测试集合并,这一块的坑不少。

train_init = datasets.MNIST('./mnist', train=True,transform=train_transform)test_init =  datasets.MNIST('./mnist', train=False, transform=test_transform)# the dataset for k fold cross validation
dataFold = torch.utils.data.ConcatDataset([train_init, test_init])

二是使用Sklearn中的KFold进行数据集划分,并且转换回pytorch类型的Dataloader。

 kf = KFold(n_splits=k_split_value,shuffle=True, random_state=0)  # init KFoldfor train_index , test_index in kf.split(dataFold):  # split  # get train, val 根据索引划分train_fold = torch.utils.data.dataset.Subset(dataFold, train_index)test_fold = torch.utils.data.dataset.Subset(dataFold, test_index) # package type of DataLoadertrain_loader = torch.utils.data.DataLoader(dataset=train_fold, batch_size=BATCH_SIZE, shuffle=True)test_loader = torch.utils.data.DataLoader(dataset=test_fold, batch_size=BATCH_SIZE, shuffle=True)

对于KFold:

提供训练集/测试集索引以分割数据。将数据集拆分为k折(默认情况下不打乱数据。

参数介绍:

n_splits:int, 默认为5。表示拆分成5折
shuffle: bool, 默认为False。切分数据集之前是否对数据进行洗牌。True洗牌,False不洗牌。
random_state:int, 默认为None 当shuffle为True时,如果random_state为None,则每次运行代码,获得的数据切分都不一样,random_state指定的时候,则每次运行代码,都能获得同样的切分数据,保证实验可重复。random_state可按自己喜好设定成整数,如random_state=42较为常用。当设定好后,就不能再更改。

例子: 

from sklearn.model_selection import KFold
import numpy as np
X = np.arange(24).reshape(12,2)
y = np.random.choice([1,2],12,p=[0.4,0.6])
kf = KFold(n_splits=5,shuffle=False)  # 初始化KFold
for train_index , test_index in kf.split(X):  # 调用split方法切分数据print('train_index:%s , test_index: %s ' %(train_index,test_index))

【output】 

train_index:[ 3 4 5 6 7 8 9 10 11] , test_index: [0 1 2]
train_index:[ 0 1 2 6 7 8 9 10 11] , test_index: [3 4 5]
train_index:[ 0 1 2 3 4 5 8 9 10 11] , test_index: [6 7]
train_index:[ 0 1 2 3 4 5 6 7 10 11] , test_index: [8 9]
train_index:[0 1 2 3 4 5 6 7 8 9] , test_index: [10 11]

注意:

设置shuffle=False,每次运行结果都相同

设置shuffle=True,每次运行结果都不相同

设置shuffle=True和random_state=整数,每次运行结果相同

(2)设定K值为[2,10]进行训练


testAcc_compare_map = {}
for k_split_value in range(2, 10+1):print('now k_split_value is:', k_split_value)testAcc_compare_map[k_split_value] = train_flod_Mnist(k_split_value)

testAcc_compare_map是将不同k值下训练的结果保存起来,之后我们可以通过这个字典变量,计算出rmse ,比较不同k值下,实验结果的鲁棒性。


【番外】小实验


我想发布一下小作业,试图帮助大家体悟k折交叉验证:

1.执行k倍交叉验证,选择k=1-10,绘制(a)平均列车对数rmse vs k(b)平均
对数rmse vs k〔20分〕

1. Perform a k fold cross validation select k = 1-10, plot (a) avg train log rmse vs k. (b) avg
log rmse vs k. [20 points]

2.当你增加k的值时会发生什么?解释两次损失的行为
随着k的增加[20点]

2. What happens when you increase the value of k? Explain the behavior of the two losses
with increasing k. [20 points]

【补充材料】

对于RMSE:

实验结果中ACC随着K值增大的变化如下【k=1就是baseline的结果,此处是k=[2,10]】:


【参考文献】

【1】五折交叉验证/K折交叉验证, python代码到底怎么写_Tina姐的博客-CSDN博客_五折交叉验证

在Mnist数据上使用k折交叉验证训练,pytorch代码到底怎么写相关推荐

  1. 五折交叉验证/K折交叉验证, python代码到底怎么写

    五折交叉验证: 把数据平均分成5等份,每次实验拿一份做测试,其余用做训练.实验5次求平均值.如上图,第一次实验拿第一份做测试集,其余作为训练集.第二次实验拿第二份做测试集,其余做训练集.依此类推~ 但 ...

  2. Kaggle上分技巧——单模K折交叉验证训练+多模型融合

    一.K折交叉验证训练单个模型 1.1 k 折交叉验证(K-Fold Cross Validation)原理 通过对 k 个不同分组训练的结果进行平均来减少方差,因此模型的性能对数据的划分就不那么敏感, ...

  3. ML:模型训练/模型评估中常用的两种方法代码实现(留一法一次性切分训练和K折交叉验证训练)

    ML:模型训练/模型评估中常用的两种方法代码实现(留一法一次性切分训练和K折交叉验证训练) 目录 模型训练评估中常用的两种方法代码实现 T1.留一法一次性切分训练 T2.K折交叉验证训 模型训练评估中 ...

  4. matlab-K折交叉验证与分层K折交叉验证

    文章目录 K折交叉验证有什么用? 如何实现K折交叉验证? K折交叉验证的要点:(文字版) 如何实现K折交叉验证(图片版) 如何实现K折交叉验证(matlab版) 为啥我们需要分层K折交叉验证? 如何实 ...

  5. 5折交叉验证_[Machine Learning] 模型评估——交叉验证/K折交叉验证

    首先区分两个概念:'模型评估' 与 '模型性能度量' 模型评估:这里强调的是如何划分和利用数据,对模型学习能力的评估,重点在数据的划分方法. Keywords: 划分.利用数据 模型性能度量:是在研究 ...

  6. 交叉验证(cross validation)是什么?K折交叉验证(k-fold crossValidation)是什么?

    交叉验证(cross validation)是什么?K折交叉验证(k-fold crossValidation)是什么? 交叉验证(cross validation)是什么?  交叉验证是一种模型的验 ...

  7. 机器学习(MACHINE LEARNING)交叉验证(简单交叉验证、k折交叉验证、留一法)

    文章目录 1 简单的交叉验证 2 k折交叉验证 k-fold cross validation 3 留一法 leave-one-out cross validation 针对经验风险最小化算法的过拟合 ...

  8. 【Python-ML】SKlearn库Pipeline工作流和K折交叉验证

    # -*- coding: utf-8 -*- ''' Created on 2018年1月18日 @author: Jason.F @summary: Pipeline,流水线工作流,串联模型拟合. ...

  9. k折交叉验证法python实现_Jason Brownlee专栏| 如何解决不平衡分类的k折交叉验证-不平衡分类系列教程(十)...

    作者:Jason Brownlee 编译:Florence Wong – AICUG 本文系AICUG翻译原创,如需转载请联系(微信号:834436689)以获得授权 在对不可见示例进行预测时,模型评 ...

最新文章

  1. CentOS启动不显示图形界面直接进入命令行模式
  2. 一致代码段与非一致代码段
  3. cenotos 卸载mysql_CentOS 6.2编译安装Nginx1.0.12+MySQL5.5.21+PHP5.3.10 | 系统运维
  4. tp框架存在的问题 不可多图同时上传
  5. Maven 项目创建 找不到web.xml
  6. 全国计算机等级考试题库二级C操作题100套(第83套)
  7. LeetCode MySQL 1076. 项目员工II
  8. 鸿蒙行车记录仪,百度导航新增行车记录仪功能 可消除碰瓷风险
  9. javascript中实例对象和构造函数关系、原型语法、原型链、call实现继承、apply调用函数、bind拷贝函数、拷贝继承、class类、super、严格模式、高阶函数、闭包、递归、es6简介
  10. CCCC-GPLT L3-014. 周游世界 团体程序设计天梯赛
  11. mac Lion 10.7系统使用笔记
  12. ubuntu安装matlab2016b
  13. 直播如何解决延时问题?谈如何解决延时和连麦的老难题
  14. 职业生涯必备——程序员“黑话”指南
  15. 筛选后系列填充_案例分享10——如何在筛选后的表格中粘贴数据(二)
  16. Qt 并行运算高级API QtConcurrent
  17. 增值电信业务经营许可证怎么续期,需要什么材料
  18. 发那科pmc编程手册_干货|发那科FANUC PMC编程步骤精编版(图文并茂)
  19. 实用的语音转文字转换器,告别文件转换难题
  20. ASP.NET教育管理系统源码【源码分享】

热门文章

  1. 1、[python]经典详细入门
  2. 各国黑客暗中较量网络战场 美国网络部队成型
  3. 在中国,是OA平台胜,还是协同平台胜?
  4. 搬运机械手及其控制系统设计(论文+CAD装配图+零件图+梯形图+接线图)
  5. Golang黑科技之——string与[]byte转换
  6. Win10历史记录怎么查
  7. C++统计程序运行时间
  8. Android手机系统软件apk开发制作
  9. dz论坛附件在服务器中的位置,dz论坛如何启用远程附件功能(详细图解)
  10. Leaflet与OpenLayer