时间序列的蒙特卡罗交叉验证

news2024/11/25 16:36:01

交叉验证应用于时间序列需要注意是要防止泄漏和获得可靠的性能估计本文将介绍蒙特卡洛交叉验证。这是一种流行的TimeSeriesSplits方法的替代方法。

时间序列交叉验证

TimeSeriesSplit通常是时间序列数据进行交叉验证的首选方法。下图1说明了该方法的操作方式。可用的时间序列被分成几个大小相等的折叠。然后每一次折首先被用来测试一个模型,然后重新训练它。除了第一折只用于训练。

使用TimeSeriesSplit进行交叉验证的主要好处如下:

  • 它保持了观察的顺序。这个问题在有序数据集(如时间序列)中非常重要。
  • 它生成了很多拆分 。几次拆分后可以获得更稳健的评估。如果数据集不大,这一点尤其重要。

TimeSeriesSplit的主要缺点是跨折叠的训练样本量是不一致的。这是什么意思?

假设将该方法应用于图1所示的5次分折。在第一次迭代中,所有可用观测值的20%用于训练。但是,这个数字在上次迭代中是80%。因此,初始迭代可能不能代表完整的时间序列。这个问题会影响性能估计。

那么如何解决这个问题?

蒙特卡罗交叉验证

蒙特卡罗交叉验证(MonteCarloCV)是一种可以用于时间序列的方法。这个想法是在不同的随机起点来获取一个时间周期的数据,下面是这种方法的可视化描述:

像TimeSeriesSplit一样,MonteCarloCV也保留了观测的时间顺序。它还会保留多次重复估计过程。

MonteCarloCV与TimeSeriesSplit的区别主要有两个方面:

  • 对于训练和验证样本量,使用TimeSeriesSplit时训练集的大小会增加。在MonteCarloCV中,训练集的大小在每次迭代过程中都是固定的,这样可以防止训练规模不能代表整个数据;
  • 随机的分折,在MonteCarloCV中,验证原点是随机选择的。这个原点标志着训练集的结束和验证的开始。在TimeSeriesSplit的情况下,这个点是确定的。它是根据迭代次数预先定义的。

MonteCarloCV最初由Picard和Cook使用。详细信息可以查看参考文献[1]。

经过详细研究MonteCarloCV。这包括与TimeSeriesSplit等其他方法的比较。MonteCarloCV可以获得更好的估计,所以我一直在使用它。你可以在参考文献[2]中查看完整的研究。

不幸的是,scikit-learn不提供MonteCarloCV的实现。所以,我们决定自己手动实现它:

 from typing import List, Generator
 
 import numpy as np
 
 from sklearn.model_selection._split import _BaseKFold
 from sklearn.utils.validation import indexable, _num_samples
 
 
 class MonteCarloCV(_BaseKFold):
 
     def __init__(self,
                  n_splits: int,
                  train_size: float,
                  test_size: float,
                  gap: int = 0):
         """
         Monte Carlo Cross-Validation
 
         Holdout applied in multiple testing periods
         Testing origin (time-step where testing begins) is randomly chosen according to a monte carlo simulation
 
         :param n_splits: (int) Number of monte carlo repetitions in the procedure
         :param train_size: (float) Train size, in terms of ratio of the total length of the series
         :param test_size: (float) Test size, in terms of ratio of the total length of the series
         :param gap: (int) Number of samples to exclude from the end of each train set before the test set.
         """
 
         self.n_splits = n_splits
         self.n_samples = -1
         self.gap = gap
         self.train_size = train_size
         self.test_size = test_size
         self.train_n_samples = 0
         self.test_n_samples = 0
 
         self.mc_origins = []
 
     def split(self, X, y=None, groups=None) -> Generator:
         """Generate indices to split data into training and test set.
         Parameters
         ----------
         X : array-like of shape (n_samples, n_features)
             Training data, where `n_samples` is the number of samples
             and `n_features` is the number of features.
         y : array-like of shape (n_samples,)
             Always ignored, exists for compatibility.
         groups : array-like of shape (n_samples,)
             Always ignored, exists for compatibility.
         Yields
         ------
         train : ndarray
             The training set indices for that split.
         test : ndarray
             The testing set indices for that split.
         """
 
         X, y, groups = indexable(X, y, groups)
         self.n_samples = _num_samples(X)
 
         self.train_n_samples = int(self.n_samples * self.train_size) - 1
         self.test_n_samples = int(self.n_samples * self.test_size) - 1
 
         # Make sure we have enough samples for the given split parameters
         if self.n_splits > self.n_samples:
             raise ValueError(
                 f'Cannot have number of folds={self.n_splits} greater'
                 f' than the number of samples={self.n_samples}.'
             )
         if self.train_n_samples - self.gap <= 0:
             raise ValueError(
                 f'The gap={self.gap} is too big for number of training samples'
                 f'={self.train_n_samples} with testing samples={self.test_n_samples} and gap={self.gap}.'
             )
 
         indices = np.arange(self.n_samples)
 
         selection_range = np.arange(self.train_n_samples + 1, self.n_samples - self.test_n_samples - 1)
 
         self.mc_origins = \
             np.random.choice(a=selection_range,
                              size=self.n_splits,
                              replace=True)
 
         for origin in self.mc_origins:
             if self.gap > 0:
                 train_end = origin - self.gap + 1
             else:
                 train_end = origin - self.gap
             train_start = origin - self.train_n_samples - 1
 
             test_end = origin + self.test_n_samples
 
             yield (
                 indices[train_start:train_end],
                 indices[origin:test_end],
             )
 
     def get_origins(self) -> List[int]:
         return self.mc_origins

MonteCarloCV接受四个参数:

n_splitting:分折或迭代的次数。这个值趋向于10;

training_size:每次迭代时训练集的大小与时间序列大小的比值;

test_size:类似于training_size,但用于验证集;

gap:分离训练集和验证集的观察数。与TimeSeriesSplits一样,此参数的值默认为0(无间隙)。

每次迭代的训练和验证大小取决于输入数据。我发现一个0.6/0.1的分区工作得很好。也就是说,在每次迭代中,60%的数据被用于训练。10%的观察结果用于验证。

实际使用的例子

下面是配置的一个例子:

 from sklearn.datasets import make_regression
 from src.mccv import MonteCarloCV
 
 X, y = make_regression(n_samples=120)
 
 mccv = MonteCarloCV(n_splits=5, 
                     train_size=0.6, 
                     test_size=0.1, 
                     gap=0)
 
 for train_index, test_index in mccv.split(X):
     print("TRAIN:", train_index, "TEST:", test_index)
     X_train, X_test = X[train_index], X[test_index]
     y_train, y_test = y[train_index], y[test_index]

该实现也与scikit-learn兼容。以下是如何结合GridSearchCV:

 from sklearn.ensemble import RandomForestRegressor
 from sklearn.model_selection import GridSearchCV
 
 model = RandomForestRegressor()
 param_search = {'n_estimators': [10, 100]}
 
 gsearch = GridSearchCV(estimator=model, cv=mccv, param_grid=param_search)
 gsearch.fit(X, y)

我希望你发现MonteCarloCV有用!

引用

[1] Picard, Richard R., and R. Dennis Cook. “Cross-validation of regression models.” Journal of the American Statistical Association 79.387 (1984): 575–583.

[2] Vitor Cerqueira, Luis Torgo, and Igor Mozetič. “Evaluating time series forecasting models: An empirical study on performance estimation methods.” Machine Learning 109.11 (2020): 1997–2028.

https://avoid.overfit.cn/post/d6ab5b4cd0e5476c91cae97c4564deb9

作者:Vitor Cerqueira

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/90531.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

编译原理实验三:算符优先分析算法的设计与实现(python)

实验目的 根据算符优先分析法&#xff0c;对表达式进行语法分析&#xff0c;使其能够判断一个表达式是否正确。通过算符优先分析方法的实现&#xff0c;加深对自下而上语法分析方法的理解。 实验内容 1、输入文法。可以是如下算术表达式的文法&#xff08;你可以根据需要适当…

赋能组织执行力学习-R4管理-结果体系、责任体系、检查与改进体系、及时激励体系

本文向大家介绍R4管理&#xff0c;是由结果体系&#xff08;Result&#xff09;、责任体系&#xff08;Responsibility&#xff09;、检查与改进体系&#xff08;Review&#xff09;、及时激励体系&#xff08;Reward&#xff09;组成&#xff0c;帮助我们如何更好的运用。 马云…

TikTok选品技巧 | 爆品一般是怎么选出来的,快看这些技巧

TikTok电商商家看过来&#xff01;随着短视频时代的兴起与发展&#xff0c;TikTok在全球受到越来越多的用户所追捧。同时&#xff0c;吸引了更多TikTok商家前来发展电商。但是&#xff0c;想要在这里快速实现TikTok变现目标&#xff0c;并非容易。TikTok选品和TikTok营销是最不…

数据库原理及MySQL应用 | 多表查询

在实际应用中&#xff0c;多表查询应用相对较多&#xff0c;根据多表之间的相关列&#xff0c;可以从多个表中检索出所需数据。 在实际应用中&#xff0c;单表查询应用范围相对较少&#xff0c;因为用户需要的数据往往存储在多个不同的表中&#xff0c;这时需要进行多表查询。…

oracle的pkg改为hivesql

1. oracle的() 改为hive左右连接 oracle ()学习_cclovezbf的博客-CSDN博客最近工作需要将oracle的存储过程转化为hive的sql脚本。遇到很多不一样的地方&#xff0c;例如oracle连接中有()号的用法。借鉴这篇文章&#xff0c;但是这个排版比较烂。。。先建表和插入数据首先说明…

笔试强训(四十六)

目录一、选择题二、编程题2.1 简单错误记录2.1.1 题目2.1.2 题解一、选择题 &#xff08;1&#xff09;一台刚接入互联网的WEB服务器第一次被访问到时&#xff0c;不同协议的发生顺序是下面中的&#xff08;A&#xff09; A.ARP->DNS->HTTP B.ARP->HTTP->DNS C.DN…

怎么提取伴奏?有什么实用的提取软件?

由于我喜欢唱歌&#xff0c;所以在读书时期偶尔会参加学校的一些歌唱比赛或是文艺汇演。而一开始的我没什么经验&#xff0c;练习时都是放着原声带跟唱&#xff0c;但是到了舞台上发现只有伴奏&#xff0c;一时间卡不到开唱的点&#xff0c;甚是尴尬。所以后来我吸取了教训&…

蓝桥杯嵌入式 cubeMX生成代码解读

文章目录前言一、代码风格二、为什么要这些注释&#xff1f;三、生成的独立模块的代码总结前言 本篇文章讲介绍一下cubeMX生成代码的风格。 一、代码风格 在main.c中可以看到非常多的注释代码&#xff0c;很多人都不知道这些是用来干嘛的&#xff0c;现在就给大家介绍一下这…

你了解Java中的ForkJoin吗?

什么是ForkJoin? ForkJoin 从字面上看Fork是分岔的意思&#xff0c;Join是结合的意思&#xff0c;我们可以理解为将大任务拆分成小任务进行计算求解&#xff0c;最后将小任务的结果进行结合求出大任务的解&#xff0c;这些裂变出来的小任务&#xff0c;我们就可以交给不同的线…

新智慧杂志新智慧杂志社新智慧编辑部2022年第30期目录

杏坛潮_热点关注 特色劳动教育模式探究——基于“劳动周”项目的设计与实践 王胜; 1-3《新智慧》投稿&#xff1a;cn7kantougao163.com “双减”背景下小学数学大单元深度学习的实践与探索——以小学高年级为例 王晓雪; 4-6 杏坛潮_创新教育 问题教学法在高中物理教…

20221215英语学习

今日新词&#xff1a; rich adj.富有的, 富裕的, 油腻的 luck n.运气, 幸运, 好运, 侥幸 live adj.活的, 现场直播的, 实况转播的, 现场演出的 tutor n.家庭教师&#xff1b;私人教师&#xff1b;导师&#xff1b;助教 swipe v.挥拳打, 扬起巴掌打, 挥起&#xff08;物体&…

刷屏的AI 绘画,你成功驯服了吗?其背后的AIGC模型你可能还不知道

文章目录前言基于 CLIP Latents 的条件文本图像生成BLIPHugging Face奇点智源中文-CLIP百度昆仑万维之AI绘画前言 随着人工智能技术的发展与完善&#xff0c;AIGC&#xff08;AI generated content&#xff09;在内容的创作上为人们的工作和生活带来前所未有的帮助&#xff0c…

SpringCloud(7)— ElasticSearch基础

SpringCloud&#xff08;7&#xff09;— Elasticsearch基础 一 初识Elasticsearch elasticserach是一个强大的开源搜索引擎&#xff0c;可以从海量数据中迅速找到想要的内容。 elasticsearch结合了 Kibana, Logstach, Beats,也就是 elastic stack。主要应用于日志数据分析&…

【信管4.1】范围与需求

范围与需求范围其实说白了就是我们要做的东西都包括哪些内容&#xff0c;这些内容的边界在哪里&#xff0c;范围其实从另一个角度来说的话&#xff0c;也可以看成是一个产品的约束。为什么要有一个约束呢&#xff1f;你见过一个即是电商&#xff0c;又是社交&#xff0c;还能兼…

Python还好就业吗?30多岁转行晚吗?

最近不少人在微信问我现在Python还好就业不好就业&#xff1f;发展前景怎么样&#xff1f;我30多岁了&#xff0c;还能不能转行编程&#xff1f;Python该怎么学&#xff1f;如果做Python到底该做爬虫还是数据分析还是web&#xff1f;…等等这样的问题&#xff0c;现在逐一谈下我…

将市场部与整个组织联系起来,协调每个人的利益,来达成业务目标

让我们来谈谈业务目标&#xff0c;以及这些目标如何将营销部门与整个组织联系起来&#xff0c;并帮助协调每个人的利益。什么是有效的目标&#xff0c;什么是无效的目标?举一两个例子就好了。 当然。我们目前在高管层看到的情况是——甚至在新冠疫情之前我们就已经看到了——首…

【软件测试】你遇到的随机的bug?出现的原因......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 随机性bug? 为什么…

学习过程中遇到的问题总结(持续更新~~~)

问题总结问题1&#xff1a;Access denied for user 1234localhost (using password: YES)问题2&#xff1a;启动tomcat问题&#xff0c;报错Failed to execute goal org.apache.tomcat.maven:tomcat7-maven-plugin:2.2:run (default-cli) on project springMvc_03_request_mapp…

Linux 6.2:华为代码加速核心功能 715 倍!

整理 | 王启隆出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;作为送给全球开发者的圣诞礼物&#xff0c;Linux 在前日发布了 Linux 6.1 内核的稳定版&#xff0c;并开启了 Linux 6.2 的合并窗口。这次更新不仅为广大用户带来了不少新功能与改进&#xff0c;还让许…

竣达技术 | 智能机房动力环境监控主机、多功能监控服务器

专为现代各类计算机及网络通信机房、通信行业基站而设计的远程多功能监控服务器&#xff0c;系统具备3个RS485通讯接口可监控机房环境温湿度、门禁、烟雾、漏水、市电断电等各类传感器检测对应的告警状态&#xff0c;同时支持15个开关量检测。6路继电器输出控制&#xff0c;支持…