范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

使用TemporalFusionTransformer进行时间序列预测

  目前来看表格类的数据的处理还是树型的结构占据了主导地位。但是在时间序列预测中,深度学习神经网络是有可能超越传统技术的。为什么需要现代时间序列模型?
  专为单个时间序列(无论是多变量还是单变量)创建模型的情况现在已经很少见了。现在的时间序列研究方向都是多元的,并且具有各种分布,其中包含更多探索性因素包括:缺失数据、趋势、季节性、波动性、漂移和罕见事件等等。
  通过直接预测目标变量往往是不够的,我们优势还希望系统能够产生预测区间,显示预测的不确定性程度。
  并且除了历史数据外,所有的变量都应该考虑在内,这样可以建立一个在预测能力方面具有竞争力的模型。
  所以现代时间序列模型应该考虑到以下几点:模型应该考虑多个时间序列,理想情况下应该考虑数千个时间序列。模型中应该使用单维或多维序列。除了时态数据之外,模型还应该能够使用过去数据。这个限制影响了所有的自回归技术(ARIMA模型),包括亚马逊的DeepAR。非时间的外部静态因素也应加以考虑。模型需要具有高度的适应性。即使时间序列比较复杂或包含一些噪声,模型也可以使用季节性"朴素"预测器预测。并且应该能够区分这些实例。如果可以的话模型可以进行多步预测功能。也就是不止预测下一个值们需要预测下几个值。直接对目标变量预测是不够的。模型能够产生预测区间,这样显示预测的不确定性程度。生产环境应该能够顺利地集成最优模型,该模型也应该易于使用和理解。什么是Temporal Fusion Transformer?
  Temporal Fusion Transformer(TFT)是一个基于注意力的深度神经网络,它优化了性能和可解释性,顶层架构如图2所示。
  TFT架构的优点如下:
  能够使用丰富的特征:TFT支持三种不同类型的特征:外生类别/静态变量,也称为时不变特征;具有已知输入到未来的时态数据,仅到目前已知的时态数据;具有未知输入的未来时态数据。
  区间预测:TFT使用分位数损失函数来产生除实际预测之外的预测区间。
  异构时间序列:允许训练具有不同分布的多个时间序列。TFT设计将处理分为两个部分:局部处理,集中于特定事件的特征和全局处理,记录所有时间序列的一般特征。
  可解释性:TFT的核心是基于transformer的体系结构。该模型引入的多头注意力机制,在需要对模型进行解释时提供了关于特征重要性的额外知识。另外一个性能良好的DNN实现是Multi-Horizon Quantile Recurrent Forecaster(MQRNN)。但是它没有提供如何解释这些特征重要程度的指导。
  性能:在基准测试中,TFT 优于基于 DNN 的模型,如 DeepAR、MQRNN 和深度状态空间模型(Deep Space-State Models)以及传统统计模型 (ARIMA,DSSM等)。
  与传统方法不同,TFT的多头注意力提供了特征可解释性。通过TFT的多头注意力添加一个新的矩阵或分组,允许不同的头共享一些权重,然后可以根据季节性分析来解释这些全红的含义。如何使用 Temporal Fusion Transformer 进行预测?
  本文将在一个非常小的数据集上训练 TemporalFusionTransformer,以证明它甚至在仅 20k 样本上也能很好地工作。
  1、加载数据
  本文中将使用 Kaggle Stallion 数据集,该数据集跟踪几种饮料的销售情况。我们的目标是预测在接下来的六个月中,库存单位 (SKU) 销售的商品数量或由零售商代理机构销售的产品数量。
  每月约有 21,000 条历史销售记录。除了过去的销售量,我们还有销售价格、代理商位置、节假日等特殊日子以及该行业销售总量的数据。
  数据集已经是正确的格式。但是,它还缺少一些我们关注的信息,我们需要添加是一个时间索引,它随着每个时间步长增加一个。from pytorch_forecasting.data.examples import get_stallion_data data = get_stallion_data() # add time index data["time_idx"] = data["date"].dt.year * 12 + data["date"].dt.month data["time_idx"] -= data["time_idx"].min() # add additional features data["month"] = data.date.dt.month.astype(str).astype("category") # categories have be strings data["log_volume"] = np.log(data.volume + 1e-8) data["avg_volume_by_sku"] = data.groupby(["time_idx", "sku"], observed=True).volume.transform("mean") data["avg_volume_by_agency"] = data.groupby(["time_idx", "agency"], observed=True).volume.transform("mean") # we want to encode special days as one variable and thus need to first reverse one-hot encoding special_days = [ "easter_day", "good_friday", "new_year", "christmas", "labor_day", "independence_day", "revolution_day_memorial", "regional_games", "fifa_u_17_world_cup", "football_gold_cup", "beer_capital", "music_fest", ] data[special_days] = data[special_days].apply(lambda x: x.map({0: "-", 1: x.name})).astype("category") data.sample(10, random_state=521)
  2、创建数据集和基线模型
  现在需要将我们的df转换为 Forecasting的 TimeSeriesDataSet。 这里需要设置参数确定哪些特征是分类的还是连续的,哪些是静态的还是时变的,还有选择如何规范化数据。 我们分别对每个时间序列进行标准化,并确认其始终都是正值。
  为了防止归一化带来的前瞻性偏差,通常会使用 EncoderNormalizer,它会在训练时在每个编码器序列上动态缩放。
  最后我选择使用六个月的数据作为验证集。max_prediction_length = 6 max_encoder_length = 24 training_cutoff = data["time_idx"].max() - max_prediction_length training = TimeSeriesDataSet( data[lambda x: x.time_idx <= training_cutoff], time_idx="time_idx", target="volume", group_ids=["agency", "sku"], min_encoder_length=max_encoder_length // 2, # keep encoder length long (as it is in the validation set) max_encoder_length=max_encoder_length, min_prediction_length=1, max_prediction_length=max_prediction_length, static_categoricals=["agency", "sku"], static_reals=["avg_population_2017", "avg_yearly_household_income_2017"], time_varying_known_categoricals=["special_days", "month"], variable_groups={"special_days": special_days}, # group of categorical variables can be treated as one variable time_varying_known_reals=["time_idx", "price_regular", "discount_in_percent"], time_varying_unknown_categoricals=[], time_varying_unknown_reals=[ "volume", "log_volume", "industry_volume", "soda_volume", "avg_max_temp", "avg_volume_by_agency", "avg_volume_by_sku", ], target_normalizer=GroupNormalizer( groups=["agency", "sku"], transformation="softplus" ), # use softplus and normalize by group add_relative_time_idx=True, add_target_scales=True, add_encoder_length=True, ) validation = TimeSeriesDataSet.from_dataset(training, data, predict=True, stop_randomization=True) batch_size = 128 # set this between 32 to 128 train_dataloader = training.to_dataloader(train=True, batch_size=batch_size, num_workers=0) train_dataloader = training.to_dataloader(train=True, batch_size=batch_size, num_workers=0)
  这里我们通过复制最有一个值来预测下6个月的数据,这个简单的操作我们将它作为基线模型。actuals = torch.cat([y for x, (y, weight) in iter(val_dataloader)]) baseline_predictions = Baseline().predict(val_dataloader) (actuals - baseline_predictions).abs().mean().item() ##结果 293.0088195800781
  3、训练TFT
  现在我们将创建 TemporalFusionTransformer 模型了。 这里使用 PyTorch Lightning 训练模型。pl.seed_everything(42) trainer = pl.Trainer( gpus=0, # clipping gradients is a hyperparameter and important to prevent pergance # of the gradient for recurrent neural networks gradient_clip_val=0.1, ) tft = TemporalFusionTransformer.from_dataset( training, # not meaningful for finding the learning rate but otherwise very important learning_rate=0.03, hidden_size=16, # most important hyperparameter apart from learning rate # number of attention heads. Set to up to 4 for large datasets attention_head_size=1, dropout=0.1, # between 0.1 and 0.3 are good values hidden_continuous_size=8, # set to <= hidden_size output_size=7, # 7 quantiles by default loss=QuantileLoss(), # reduce learning rate if no improvement in validation loss after x epochs reduce_on_plateau_patience=4, ) print(f"Number of parameters in network: {tft.size()/1e3:.1f}k")
  模型的参数大小:Number of parameters in network: 29.7kres = trainer.tuner.lr_find( tft, train_dataloaders=train_dataloader, val_dataloaders=val_dataloader, max_lr=10.0, min_lr=1e-6, ) print(f"suggested learning rate: {res.suggestion()}") fig = res.plot(show=True, suggest=True) fig.show() #suggested learning rate: 0.01862087136662867
  对于 TemporalFusionTransformer,最佳学习率似乎略低于默认的学习率。我们也可以不直接使用建议的学习率,因为 PyTorch Lightning 有时会被较低学习率的噪音混淆,所以我们使用一个根据经验确定的学习率。early_stop_callback = EarlyStopping(monitor="val_loss", min_delta=1e-4, patience=10, verbose=False, mode="min") lr_logger = LearningRateMonitor() # log the learning rate logger = TensorBoardLogger("lightning_logs") # logging results to a tensorboard trainer = pl.Trainer( max_epochs=30, gpus=0, enable_model_summary=True, gradient_clip_val=0.1, limit_train_batches=30, # coment in for training, running valiation every 30 batches # fast_dev_run=True, # comment in to check that networkor dataset has no serious bugs callbacks=[lr_logger, early_stop_callback], logger=logger, ) tft = TemporalFusionTransformer.from_dataset( training, learning_rate=0.03, hidden_size=16, attention_head_size=1, dropout=0.1, hidden_continuous_size=8, output_size=7, # 7 quantiles by default loss=QuantileLoss(), log_interval=10, # uncomment for learning rate finder and otherwise, e.g. to 10 for logging every 10 batches reduce_on_plateau_patience=4, ) trainer.fit( tft, train_dataloaders=train_dataloader, val_dataloaders=val_dataloader, )
  4、验证
  PyTorch Lightning 会自动保存训练的检查点,我们加载最佳模型。best_model_path = trainer.checkpoint_callback.best_model_path best_tft = TemporalFusionTransformer.load_from_checkpoint(best_model_path) actuals = torch.cat([y[0] for x, y in iter(val_dataloader)]) predictions = best_tft.predict(val_dataloader) (actuals - predictions).abs().mean() raw_predictions, x = best_tft.predict(val_dataloader, mode="raw", return_x=True) for idx in range(10): # plot 10 examples best_tft.plot_prediction(x, raw_predictions, idx=idx, add_loss_to_title=True);
  计算显示的指标: predictions = best_tft.predict(val_dataloader) mean_losses = SMAPE(reduction="none")(predictions, actuals).mean(1) indices = mean_losses.argsort(descending=True) # sort losses for idx in range(10): # plot 10 examples best_tft.plot_prediction( x, raw_predictions, idx=indices[idx], add_loss_to_title=SMAPE(quantiles=best_tft.loss.quantiles) );
  5、通过变量计算实际值与预测值
  检查模型在不同数据上的表现如何可以让我们看到模型的问题。 predictions, x = best_tft.predict(val_dataloader, return_x=True) predictions_vs_actuals = best_tft.calculate_prediction_actual_by_variable(x, predictions) best_tft.plot_prediction_actual_by_variable(predictions_vs_actuals);
  对选定数据进行预测best_tft.predict( training.filter(lambda x: (x.agency == "Agency_01") & (x.sku == "SKU_01") & (x.time_idx_first_prediction == 15)), mode="quantiles", ) raw_prediction, x = best_tft.predict( training.filter(lambda x: (x.agency == "Agency_01") & (x.sku == "SKU_01") & (x.time_idx_first_prediction == 15)), mode="raw", return_x=True, ) best_tft.plot_prediction(x, raw_prediction, idx=0);
  对新数据进行预测encoder_data = data[lambda x: x.time_idx > x.time_idx.max() - max_encoder_length] last_data = data[lambda x: x.time_idx == x.time_idx.max()] decoder_data = pd.concat( [last_data.assign(date=lambda x: x.date + pd.offsets.MonthBegin(i)) for i in range(1, max_prediction_length + 1)], ignore_index=True, ) decoder_data["time_idx"] = decoder_data["date"].dt.year * 12 + decoder_data["date"].dt.month decoder_data["time_idx"] += encoder_data["time_idx"].max() + 1 - decoder_data["time_idx"].min() decoder_data["month"] = decoder_data.date.dt.month.astype(str).astype("category") # categories have be strings new_prediction_data = pd.concat([encoder_data, decoder_data], ignore_index=True) new_raw_predictions, new_x = best_tft.predict(new_prediction_data, mode="raw", return_x=True) for idx in range(10): # plot 10 examples best_tft.plot_prediction(new_x, new_raw_predictions, idx=idx, show_future_observed=False);
  6、模型解释
  TFT中内置了解释功能,我们可以直接使用interpretation = best_tft.interpret_output(raw_predictions, reduction="sum") best_tft.plot_interpretation(interpretation)
  部分依赖图通常用于更好地解释模型(假设特征独立)。dependency = best_tft.predict_dependency( val_dataloader.dataset, "discount_in_percent", np.linspace(0, 30, 30), show_progress_bar=True, mode="dataframe" ) agg_dependency = dependency.groupby("discount_in_percent").normalized_prediction.agg( median="median", q25=lambda x: x.quantile(0.25), q75=lambda x: x.quantile(0.75) ) ax = agg_dependency.plot(y="median") ax.fill_between(agg_dependency.index, agg_dependency.q25, agg_dependency.q75, alpha=0.3);
  总结
  在本文中,我们解释了TFT的理论知识并且使用它进行了一个完整的训练和预测流程,希望对你有帮助
  TFT论文地址:arxiv 1912.09363
  作者:Aryan Jadon

关于怀孕你知道多少?孕中期第4孕月(1316周)在孕期第4个月(1316周)的时候,你是不是觉得精力充沛饭量在增加腹部也迅速隆起了呢?恭喜你,你的早孕反应已经逐渐减轻甚至可以愉快的告别前三个月的恶心呕吐了。孕期的黄金时间开始了!茶叶塑料包装的优点和缺点现在人们的生活压力普遍都很大说起茶叶我们都很熟悉茶叶有着浓郁的香气保存茶叶的时候需要避免潮湿高温阳光异味氧气因为茶叶具有很强的吸湿还潮性所以茶叶商家会给茶叶选择一家正规的茶叶塑料包本赛季过后本泽马的历史是不是历史前五十乃至前二十随着本赛季欧冠皇马1比0击败利物浦获得欧冠冠军,今年金球奖最大热门本泽马赔率领跑。甚至很多专业名宿直言今年的金球没有悬念了,法国巨星帮助皇马拿下联赛冠军与欧冠冠军并且本泽马是今年西企业的社会责任是什么?王健林带领万达用实际行动完美诠释在这个社会中,小到个人,大到国家,都承担着属于自己的责任,而作为社会重要组成部分的企业更是如此。企业在创造利润对股东和员工承担法律责任的同时,更应该承担消费者和社会环境的责任,不仅蔚来火速公布便携式充放电一体机售价3880元IT之家6月7日消息,蔚来昨天发布了便携式充放电一体机,租用价格为168元周,但该产品一经发布就遭到了用户的吐槽,主要是因为其只租不卖的政策,后来蔚来官方做出了回应,称将快速提高产iOS16首个测试版推送达5GB,升级更新支持机型有这些苹果在今天凌晨举行了WWDC22开发者大会,在WWDC22开发者大会上iOS16iPadOS16watchOS9macOSVentura系统已经正式发布与大家见面。当然对于大家来说冲马桶,盖?还是不盖?别纠结了,央视的一个实验告诉你真相根据世界厕所组织的调查报告,每个人每天进出厕所68次,其中一次大约为5分钟,而余下的每次平均为2分钟。这样算下来,人一生当中大概有2年的时光在厕所里度过。如今不少人家里的厕所都用上一款金融题材的策略管理模拟游戏HELLO大家好,这里是小白的每日一游推荐时间。世上的游戏千千万,有许多好玩的游戏由于缺乏宣传,所以不被广大玩家所熟知。在这里小白每天会为大家推荐一款评价很高但是不太出名的游戏无形拿3000亿扶持,有公司担心风险不敢复工,上海如何重振经济?6月1日起上海开始恢复正常生产生活秩序,但疫情反复的风险并未完全消除,消费生产外贸外资和纾困发展的挑战各不相同文王静仪郭怀毅李皙寅严沁雯郭宇张欣培编辑施智梁袁满陆玲我现在在南京路步山鹰国际最新公告造纸板块5月销量环比上升40。4山鹰国际发布2022年5月经营数据快报,其中,国内造纸销量52。83万吨,同比下降1。07包装销量1。85亿平方米,同比增长5。72。公司造纸板块5月销量环比上升40。40,呈现复苹果用户检查一下,你可能被盯上了论坛里有个帖子蛮火的。有小伙伴反馈,自己的iPhone夜间待机时耗电异常。连着WiFi耗电比开着5G耗电还要大,即使拔掉SIM卡,耗电依旧是10以上。如果开了飞行模式,没有连接Wi
网传阿的江新疆下课,第一时间给纳什打了个电话(虚拟)网传阿的江新疆下课,心情极为不爽,遂拨通了纳什的电话。阿哈喽,纳老弟,听说你下岗了?纳你不也下岗了么?乌鸦笑话母猪黑。阿呵呵呵,我是调整岗位,别听他们瞎说。纳媒体都传遍了,纸里能包故事数学界的花木兰一首木兰辞让替父从军的花木兰名垂青史,万古传诵。但是,你知道吗,在法国,也有一位顶替男士之名痴迷于数学并取得非凡成就的巾帼英豪。一一她就是被誉为数学界的花木兰的索菲热尔曼。被好奇心自西汉末王莽以下,像杨坚这样顺利迅速夺取帝位的,之前不曾有公元581年,北周随王汉人杨坚通过禅让的方式,登上皇位,建立了隋王朝,取代了鲜卑人宇文氏的北周政权。一个汉人,能够将少数民族建立的王朝的皇帝赶下台,可谓不易。但是,如果捋一捋隋文帝120多年前,这棵石榴树从古桥旁石缝中钻出如今年年累累硕果挂满枝头图说石榴树从石桥缝隙钻出蒋一超摄(下同)安亭老街古朴生香,严泗桥横跨安亭泾两岸。在河岸两旁,高耸直立着的香樟树常年青翠。不过,周围最吸睛的景观,却是一棵有着120多年树龄的石榴树。李鸿章为何炮轰赵县城西何庄村我的曾祖母娘家是赵县城西何庄的于氏家族,1966年她老人家享高寿90岁辞世,她在世时候,经常和我的父辈们讲述她本家的一位传奇人物于五辈。就是因为这位于五辈做了白莲教的二当家,何庄村安史之乱后为何唐朝只有河北的官员不敢贪污?贪污会被军人杀全家大家好,我是兰台。今天兰台给大家讲一讲为什么安史之乱后唐朝只有河朔三镇的官员最清廉。当然这里所说的清廉是相对的,并不是说河朔三镇的官员一个个都如同海瑞一样清廉,而是说相比同时期唐朝1950年冬,朝鲜天降大雪,李奇微进入司令部后发怒把床单丢了1950年12月,朝鲜。此时正值隆冬,北风凛冽,大雪纷飞。种种迹象表明,这个冬天,会格外的寒冷。寒冷吗?李奇微心中并不这样认为,由于第八集团军司令沃克意外身亡,他被突击委任为司令员新桥镇石湖荡镇新桥镇新桥集镇位于松江区新桥镇六磊塘中部。明万历十年(1582年),在六磊塘(原集镇中部)建造一座石拱桥,名日新桥。后又在日新桥东洪家河口建造一座石砌夹板桥,名又新桥,意为又造了一清宫回忆录太后与我,揭露慈禧晚年生活,揭露晚清政治风云光绪皇帝(三)做宫廷第一命妇太后刚刚穿戴整齐,光绪皇帝就穿着黄袍进来了,他的这身打扮与其他任何人穿的官服没什么两样,唯一的区别就是他的帽子上没有顶子,头上没戴翎毛,他跪在太后面前说周瑜离世后,小乔过着怎样的生活?和谁在一起?说出来你可能不信三国时期,风气并没有后期那么封建传统,对于女人的要求也没有那么严苛。即便是死了丈夫的寡妇,只要遇到合适的人,也大可另嫁他人。在这种背景下,不少人就在猜测周瑜死后,小乔是否另嫁他人?楚人早期居住在荆山穴穷是今湖北南漳的薛坪吗前文,我们根据有限的文字记载,将像雾像雨又像风的楚国,缥缈且神秘的历史更加清晰一些,固定到公元前1300年前楚祖季连时期,楚人就在汉江南的荆山一带,今湖北襄阳南漳繁衍生息。只是早期