Kaggle比赛冠军经验分享:如何用 RNN 预测维基百科网络流量
Kaggle比赛冠军经验分享:如何用 RNN 预测维基百科网络流量
雷锋网 AI 科技评论按:最近在 Kaggle 上有一场关于网络流量预测的比赛落下帷幕,作为领域里最具挑战性的问题之一,这场比赛得到了广泛关注。比赛的目标是预测 14 万多篇维基百科的未来网络流量,分两个阶段进行,首先是训练阶段,此阶段的结果是基于历史数据的验证集结果,接下来的阶段则是真正的预测阶段,对未来网络流量的预测。
来自莫斯科的 Arthur Suilin 在这场比赛中夺冠,他在 github 上分享了自己的模型,雷锋网 AI 科技评论把 Arthur Suilin 的经验分享编译如下。
核心思路
简单来说,Arthur Suilin 采用了 seq2seq 模型,使用一些调优方法在数据体现年份和四季带来的波动。模型的主要依靠的信息源有两类:局部特征和全局特征。
1. 局部特征
自回归模型 —— 当发现一种趋势出现时,期望它能持续出现
滑动平均模型 —— 当发现流量高峰出现时,随后会出现持续性地衰退
季节性模型 —— 当发现某些假日的流量高时,期望以后的假日的流量都会高
2. 全局特征
注意看下面的自相关图,会发现按年、按月都有很强的自相关性。
一个好的模型应该完美结合全局特征和局部特征。
Arthur 解释了他为什么采用 RNN seq2seq 模型来预测网络流量:
ARIMA 模型已经发展成熟,而 RNN 是在 ARIMA 模型基础上延深的算法,更为灵活、可表达性强。
RNN 属于非参数算法,简化了模型的学习过程。
RNN 模型能轻易识别一些异常特征(数字类的或分类的,时间相关的或序列相关的)。
Seq2seq 算法擅长处理时序问题:基于过去值和过去值的预测值来预测未来值。使用过去值的预测值能使模型更加稳定,这也是 Seq2seq 模型较为谨慎的地方。训练过程中每一步的错误都会累积,当某一步出现了极端错误,可能就会毁坏其后面所有时步的预测质量。
深度学习算法已经被过度使用。
特征工程
在这一步,Arthur 选择了简化处理,因为 RNN 本身在特征提取上已足够强大,以下为模型提取的特征:
pageviews,由于这次比赛是基于网页的流量预测,在此使用了页面点击率(hits),原值通过lop1p() 转换。
agent,county,site – 这些特征都是从页面 url 和 one-hot 编码中提取的。
day of week – 用于学习按周的季节性
year-to-year autocorrelation, quarter-to-quarter autocorrelation,用于学习按年和按季的季节性长度
page popularity,高流量和低流量页面有不同的流量变化模式,这一特征用于学习流量规模,流量规模信息在 pageviews 特征中丢失了,因为 pageviews 序列正则化成均值为零、单位方差。
lagged pageviews,随后会解释这一特征
特征预处理
所有特征(包括 one-hot 编码的特征) 都正则化成均值为零、单位方差的数据,每一个 pageviews 序列都是单独正则化的。
与时间无关的特征(autocorrelations,country 等)都被“拉伸”到与时间序列相同的长度,也就是说每天都会同样地重复。
模型从原始时间序列上随机抽取固定长度的样本进行训练。例如,如果原始时间序列的长度为 600 天,那么把训练样本的长度设为200天,就可以有400种不同的起始点。
这种采样方法相当于一种有效的数据增强机制,在每一步训练中,训练程序都会随机选择时序的开始点,相当于生成了无限长的、几乎不重复的训练数据。
模型的核心
模型有两个主要部分:encoder 和decoder
在这里,encoder 是一个 cuDNN GRU。 cuDNN 比传统的 Tensorflow RNNCell 要快 5 到 10 倍,但 cuDNN 不容易上手,而且相关文档也不全面。
decoder 是 一个 TF GRUBlockCell,包含在 tf.while_loop() 函数里。循环函数里的代码获取过去步的预测值,并将其作为当前步的输入。
处理长时序
LSTM/GRU 擅长处理最多 100-300 个项目的短序列。虽然它也能在更长的序列上工作,但它会逐渐忘记以前的信息。本次比赛中的时间序列长达 700 天,所以 Arthur 使用了一些其他的方法来增强 GRU 的记忆力。
作者选择的第一种方法是注意力机制 ( attention )。 Attention 可以记住“久远”的信息,针对这次比赛的任务,最简单有效的 attention 方法是固定权重的滑动窗口 attention(fixed-weight sliding-window attention)。对于季节性长的时间序列, 有两个数据点是非常重要的:year ago、 quarter ago。
作者从 current_day - 365 和 current_day - 90 时间点取 encoder 的输出, 经过一层 FC 层来降维,然后将结果传送到 decoder 作为输入。这种简单的方法能极大地降低预测错误。
接下来为了减少噪音数据和不均匀间隔(闰年、月份长度不同等)的影响,模型使用这些重要数据点和其邻近几个数据点的平均值作为这些数据点的值。
attn_365 = 0.25 * day_364 + 0.5 * day_365 + 0.25 * day_366
0.25, 0.5, 0.25 都是在一维的卷积内核上(长度为3),想要读出过去的重要数据点,则需要应用更大的内核。
最终形成的 attention 机制有些奇怪,如同提取了每一个时间序列的“指纹”(由小型卷积层形成),这些“指纹”决定了哪一个数据点会被选入更大的卷积内核并生成权重。这个大的卷积内核会应用到 decoder 的输出,为每一个待预测的天生成 attention 特征。这个模型可以在源码中找到。
注:模型没有使用传统的 attention 机制(Bahdanau or Luong attention),因为传统 attention 在每一步都需要从头计算,并且用上所有历史数据点。这对于这次比赛的数据 —— 长达 2 年的时间序列来说不太适用,会耗费很长时间。所以模型采用了另一种 attention 方法,对所有的数据点应用同一层卷积层,在预测时使用相同的 attention 权重,这样的模型计算起来更快。
attention 机制太过复杂,Arthur 表示也尝试过完全移除 attention,只留下过去的重要数据点,如年,半年,季前等数据点,把这些数据点作为新增的特征输入到 encoder 和 decoder 里。这种方法效果显著,甚至略为超过了目前使用 attention 的预测质量。Arthur 公布的最好成绩模型,只使用了滞后数据点作为特征,而没有使用 attention 。
滞后的数据点还有一些好处: 模型可以使用更短的 encoder,不用担心在训练过程会丢失过去的信息。因为这些信息已经完全包含在特征里了。即使是需要 60 - 90 天时间序列的 encoder 还是表现的不错 , 而之前的模型需要 300 - 400 天的时间序列。encoder 更短意味着训练更快,更少的信息丢失。
损失和正则化
本次比赛用 SMAPE 来评估结果,在模型中,由于零值点的邻近数据点不稳定,SMAPE 无法直接使用。
Arthur 使用了平滑过的可微 SMAPE 变量,在真实的数据上表现良好:
其他可选的方案: MAE ,使用 MAE 得到的结果每一处都很平滑,非常接近 SMAPE 的训练目标。
最后的预测结果四舍五入为最接近的整数值,所有负值记为 0。
训练和验证
模型使用了 COCOB 优化器结合梯度裁剪,这个优化器方法可参见论文《Training Deep Networks without Learning Rates Through Coin Betting》。COCOB 尝试在每一步预测最优学习率,所以在训练过程中不需要调节学习率。它比传统基于动量的优化器要收敛的快很多,尤其在第一个 epoch,这节省了很多时间。
划分训练集和验证集的方法有两种:
1. Walk-forward split
这种方法事实上不是真的在划分数据,数据集的全集同时作为训练集和验证集,但验证集用了不同的时间表。相比训练集的时间表,验证集的时间表被调前了一个预测间隔期。
2. Side-by-side split
这是一种主流的划分方式,将数据集切分为独立的不同子集,一部分完全用于训练,另一部分完全用于验证。
这两种方法在模型中都有尝试过。
Walk-forward 的结果更可观,毕竟它比较符合比赛目标:用历史值预测未来值。但这种切分方法有其弊端,因为它需要在时间序列末端使用完全只用作预测的数据点,这样在时间序列上训练的数据点和预测的数据点间隔较长,想要准确预测未来的数据就会变得困难。
举个例子,假如我们有 300 天的历史数据,想要预测接下来的 100 天。如果我们选择 Walk-forward 划分方法,我们会使用第前 100 天作为训练数据,接下来 100 天作为训练过程中的预测数据(运行 decoder,计算损失),接下来 100 天的数据用作验证集,最后 100 天用作预测未来的值。所以我们实际上用了 1/3 的数据点在训练,在最后一次训练数据点和第一次预测数据点之间有 200 天的间隔。这个间隔太大了,所以一旦我们离开训练的场景,预测质量会成指数型下降。 如果只有 100 天的间隔,预测质量会有显著提升。
Side-by-side split 在末端序列上不会单独耗用数据点作为预测的数据集,这一点很好,但模型在验证集上的性能就会和训练集的性能有很强的关联性,却与未来要预测的真实数据没有任何相关性,换一句话说,这样划分数据没有实质性作用,只是重复了在训练集上观察到的模型损失。
简而言之,使用 walk-forward split 划分的验证集只是用来调优参数,最后的预测模型必然是在与训练集和验证集完全无相关的数据下运行的。
减少模型方差
由于噪音数据的存在,模型不可避免有很大的方差。事实上RNN能在这些噪音数据中完成学习过程已经很不错了。
不同 seed 下训练的模型性能也会不一样,某些 seed 下的模型性能误差很大。在训练过程中,这种性能的波动是一直存在的,完全凭运气赢得比赛是不行的,所以必须有一些措施来减少方差。
1. 我们不清楚模型训练到哪一步是最适合用于预测未来值的(毕竟基于当前数据的验证集和未来数据的关联性很弱),所以不能过早停止训练。但是防止模型过拟合的一个大概范围可以推测,Arthur 把这个范围边界设为 10500..11500, 这样节省了 10 个 checkpoints。
2. Arthur 在不同的 seed 上训练 了3 种模型,每一个模型都减少了 checkpoint ,最后总共有 30 个 checkpoints 。
3. 提供模型性能、减少方差的典型方法是 SGD averaging(ASGD),这种方法非常简单,在 Tensorlow 上用起来也很顺手。ASGD 要求在训练过程中网络权重使用滑动平均值。
以上三种方法结合起来效果很好,模型的 SMAPE 误差几乎快赶上排行榜上基于历史数据的验证集下的 SMAPE 误差值了。
理论上,使用前两种方法作为集合的学习过程就可以了,第三种方法的使用主要是为了减少误差。
超参数调优
很多超参数的值会影响模型性能,例如网络层的个数和深度,激励函数,dropout 系数,因此超参数需要调优。手动调参既无趣又耗时,我们当然希望模型能自动调优,所以模型中使用了 SMAC3 来自动调优,SMAC3 是一种参数调优的搜索算法,它有以下几点优点:
支持条件参数 (举一个例子,同时调节网络层个数和每层的 dropout 个数,当只有 n_layers >1 时,第二层的 drupout 才能被调节,我们说这里存在条件参数)
显示处理误差 。SMAC 在不同 seed 上为每个模型都训练了几个实例,只有这些实例在同一个 seed 上训练时才会相互对比。一个模型如果比其他所有同等 seed 上的模型性能都好的话,证明这个模型是成功的。
另外,Arthur 表示有一点没有达到他的期待,超参数的搜索方法并没有找出全局最优值,因为目前最好的几个模型虽然参数不同,性能都相差无几。有可能 RNN 模型的可表达性太强,所以模型的表现更加依赖于数据的质量、噪音数据所占的比例,而不是依赖于模型本身的架构了。
如果感兴趣的话,在 hparams.py 中可以找到最优的参数设置。
Via: https://github.com/Arturus/ ,雷锋网(公众号:雷锋网) AI 科技评论编译
Kaggle比赛冠军经验分享:如何用 RNN 预测维基百科网络流量的更多相关文章
- 【干货】Kaggle 数据挖掘比赛经验分享(mark 专业的数据建模过程)
简介 Kaggle 于 2010 年创立,专注数据科学,机器学习竞赛的举办,是全球最大的数据科学社区和数据竞赛平台.笔者从 2013 年开始,陆续参加了多场 Kaggle上面举办的比赛,相继获得了 C ...
- Kaggle 数据挖掘比赛经验分享(转)
原作者:陈成龙 简介 Kaggle 于 2010 年创立,专注数据科学,机器学习竞赛的举办,是全球最大的数据科学社区和数据竞赛平台.笔者从 2013 年开始,陆续参加了多场 Kaggle上面举办的比 ...
- Kaggle 数据挖掘比赛经验分享
文章发布于公号[数智物语] (ID:decision_engine),关注公号不错过每一篇干货. 来源 | 腾讯广告算法大赛 作者 | 陈成龙 Kaggle 于 2010 年创立,专注数据科学,机器学 ...
- 好文推荐:转载一篇别人kaggle的经验分享
转载:https://www.toutiao.com/i6435866304363627010/ 笔者参加了由Quora举办的Quora Question Pairs比赛,并且获得了前1%的成绩.这是 ...
- 经验分享:如何用grep对PHP进行代码审计
这是一个常见的误解- 企业需要购买复杂和昂贵的软件来发现应用程序中安全漏洞:而这些专门的软件应用程序,无论是黑盒或白盒,开源或商业,都能很快的发现安全漏洞. 事实是:所有这些专业的漏洞扫描工具都有其特 ...
- 【原创经验分享】WCF之消息队列
最近都在鼓捣这个WCF,因为看到说WCF比WebService功能要强大许多,另外也看了一些公司的招聘信息,貌似一些中.高级的程序员招聘,都有提及到WCF这一块,所以,自己也关心关心一下,虽然目前工作 ...
- 【原创经验分享】JQuery(Ajax)调用WCF服务
最近在学习这个WCF,由于刚开始学 不久,发现网上的一些WCF教程都比较简单,感觉功能跟WebService没什么特别大的区别,但是看网上的介绍,就说WCF比WebService牛逼多少多少,反正我刚 ...
- (转)CMOS Sensor的调试经验分享
CMOS Sensor的调试经验分享 我这里要介绍的就是CMOS摄像头的一些调试经验. 首先,要认识CMOS摄像头的结构.我们通常拿到的是集成封装好的模组,一般由三个部分组成:镜头.感应器和图像信号处 ...
- 关于启用 HTTPS 的一些经验分享(二)
转载: 关于启用 HTTPS 的一些经验分享(二) 几天前,一位朋友问我:都说推荐用 Qualys SSL Labs 这个工具测试 SSL 安全性,为什么有些安全实力很强的大厂家评分也很低?我认为这个 ...
随机推荐
- a Javascript library for training Deep Learning models
w强化算法和数学,来迎接机器学习.神经网络. http://cs.stanford.edu/people/karpathy/convnetjs/ ConvNetJS is a Javascript l ...
- 双态运维分享之二: 服务型CMDB的消费场景
近年来,CMDB在IT运维管理中的价值逐步得到认可,使用CMDB的期望值也日益增长.然而,CMDB实施和维护的高成本却一直是建设者们的痛点.那么今天,我们来探讨一下如何通过消费来持续驱动CMDB的逐步 ...
- Mirror--镜像使用的工作线程数
/*在SQL SERVER 2005 及以后版本中, 使用'MAXworker thread' 来配置可用的线程数,默认设置为0 ,即自动控制线程数 计算最大工作线程数: 对于32 位系统:逻辑CPU ...
- php源码编译常见错误解决方案大全
php源码编译常见错误解决方案大全http://www.cnlvzi.com/index.php/Index/article/id/143 在CentOS编译PHP5的时候有时会遇到以下的一些错误信息 ...
- [RGEOS]数学基础
1.向量Vector3d using System; namespace RGeos.Geometry { /// <summary> /// 3D向量类 /// </summary ...
- sql用法
1: SELECT `SCHEMA_NAME` FROM `information_schema`.`SCHEMATA`; 查询sql中的数据库名 2: select * from for ...
- 运行.xcworkspace项目后报错:'React/RCTBundleURLProvider.h’ file not found
情况:根据https://github.com/rebeccahughes/react-native-device-info添加依赖库,运行.xcworkspacea项目后报错 解决:Delete n ...
- rails性能优化
1,使用Unicorn或者Thin服务器替代默认的webrick.2,静态资源压缩合并,放到云存储上.3,同时可以使用rails的Turbolinks,使用js替换title和body,但也带来了js ...
- VS2010/MFC编程入门之十九(对话框:颜色对话框)
鸡啄米在上一节中为大家讲解了字体对话框的使用方法,熟悉了字体对话框,本节继续讲另一种通用对话框--颜色对话框. 颜色对话框大家肯定也不陌生,我们可以打开它选择需要的颜色,简单说,它的作用就是用来选择颜 ...
- Linux 基础 —— Linux 进程的管理与监控
这篇文章主要讲 Linux 中进程的概念和进程的管理工具.原文:http://liaoph.com/inux-process-management/ 进程的概念 什么是进程 进程(Process)是计 ...