最后,赫兹量化交易软件使用to_datalader()函数将训练和验证数据集转换为PyTorch DataLoader对象。此函数需要以下参数:
-
“train”参数,指示数据是否应该被打乱
-
“batch_size”参数,用于指定每个批次的样本数
-
“num_workers”参数,用于指定数据加载的工作进程数
train_dataloader = training.to_dataloader(train=True, shuffle=t_shuffle, drop_last=t_drop_last, batch_size=batch_size, num_workers=0,) val_dataloader = validation.to_dataloader(train=False, shuffle=v_shuffle, drop_last=v_drop_last, batch_size=batch_size, num_workers=0)
最后,我们将这部分代码封装到函数spilt_data(data:pd.DataFrame,t_drop_last:bool,t_shuffle:bool,v_drop_last:bol,v_shuffle:bol)中,并指定以下参数:
-
“data”参数,用于接收需要处理的数据集
-
“t_drop_last”参数,指示是否应丢弃训练数据集的最后一组
-
“t_shuffle”参数,指示是否应对训练数据进行混洗
-
“v_drop_last”参数,指示是否应删除验证数据集的最后一组
-
“v_shuffle”参数,指示是否应对验证数据进行混洗
赫兹量化交易软件将train_dataloader(用于训练数据集的dataloader的实例)、val_dataloadr(用于验证数据集的dataloader的实例)和training(用于数据集的TimeSeriesDataSet的实例)作为该函数的返回值,因为它们将在以后使用。
def spilt_data(data:pd.DataFrame, t_drop_last:bool, t_shuffle:bool, v_drop_last:bool, v_shuffle:bool): training_cutoff = data["time_idx"].max() - max_prediction_length #max:95 context_length = max_encoder_length prediction_length = max_prediction_length training = New_TmSrDt( data[lambda x: x.time_idx <= training_cutoff], time_idx="time_idx", target="close", categorical_encoders={"series":NaNLabelEncoder().fit(data.series)}, group_ids=["series"], time_varying_unknown_reals=["close"], max_encoder_length=context_length, # min_encoder_length=max_encoder_length//2, max_prediction_length=prediction_length, # min_prediction_length=1, ) validation = New_TmSrDt.from_dataset(training, data, min_prediction_idx=training_cutoff + 1) train_dataloader = training.to_dataloader(train=True, shuffle=t_shuffle, drop_last=t_drop_last, batch_size=batch_size, num_workers=0,) val_dataloader = validation.to_dataloader(train=False, shuffle=v_shuffle, drop_last=v_drop_last, batch_size=batch_size, num_workers=0) return train_dataloader,val_dataloader,training
模型创建和训练
现在我们开始创建NHiTS模型。这一部分将展示如何设置其参数以及如何对其进行训练。
1.找到最佳学习率
在开始创建模型之前,我们使用PyTorch Lightning的Tuner对象来找到最佳学习率。
首先,我们需要创建PyTorch Lightning的Trainer对象,其中“accelerator”参数用于指定设备类型,“gradient_clip_val”用于防止梯度爆炸。
pl.seed_everything(42) trainer = pl.Trainer(accelerator="cpu", gradient_clip_val=0.1)
接下来,赫兹量化交易软件使用NHiTS.from_dataset()函数来创建一个NHiTS模型网。此函数需要以下参数:
-
训练数据集
-
学习率
-
权重衰减
-
损失函数
-
隐藏层的大小
-
优化器
net = NHiTS.from_dataset( training, learning_rate=3e-2, weight_decay=1e-2, loss=MQF2DistributionLoss(prediction_length=max_prediction_length), backcast_loss_ratio=0.0, hidden_size=64, optimizer="AdamW", )
然后我们实例化Tuner类并调用lr_find()函数。该函数将基于我们的数据集在一系列学习率上训练模型,并比较每个学习率的损失,以获得最佳学习率。
res = Tuner(trainer).lr_find( net, train_dataloaders=train_dataloader, val_dataloaders=val_dataloader, min_lr=1e-5, max_lr=1e-1 ) lr_=res.suggestion()
同样,我们将获得最佳学习率的这部分代码封装到函数get_learning_rate()中,并将获得的最佳学习率作为其返回值:
def get_learning_rate(): pl.seed_everything(42) trainer = pl.Trainer(accelerator="cpu", gradient_clip_val=0.1,logger=False) net = NHiTS.from_dataset( training, learning_rate=3e-2, weight_decay=1e-2, loss=MQF2DistributionLoss(prediction_length=max_prediction_length), backcast_loss_ratio=0.0, hidden_size=64, optimizer="AdamW", ) res = Tuner(trainer).lr_find( net, train_dataloaders=t_loader, val_dataloaders=v_loader, min_lr=1e-5, max_lr=1e-1 ) lr_=res.suggestion() return lr_
如果您想可视化学习率,可以添加以下代码:
添加图片注释,不超过 140 字(可选)
print(f"suggested learning rate: {res.suggestion()}") fig = res.plot(show=True, suggest=True) fig.show()
此示例中的结果如下:
添加图片注释,不超过 140 字(可选)
建议学习率:0.003981071705534973。
2. 定义EarlyStoping回调
此回调主要用于监测验证损失,并在损失连续几个时期没有改善时停止训练。这样可以防止模型过拟合。
early_stop_callback = EarlyStopping(monitor="val_loss", min_delta=1e-4, patience=10, verbose=True, mode="min")
这里需要注意的参数是“patience”,它主要控制在训练过程中,如果损失连续几个时期没有改善,何时停止。我们把它设置为10。
3. 定义ModelCheckpoint回调
此回调主要用于控制模型归档和归档的名称。我们主要设置这两个变量。
ck_callback=ModelCheckpoint(monitor='val_loss', mode="min", save_top_k=1, filename='{epoch}-{val_loss:.2f}')
“save_top_k”用于控制保存前几个最好的模型。我们将其设置为1,只保存最好的模型。
4. 定义训练模型
我们首先需要在lightning.pytarch中实例化一个Trainer类,并添加我们之前定义的两个回调。
trainer = pl.Trainer( max_epochs=ep, accelerator="cpu", enable_model_summary=True, gradient_clip_val=1.0, callbacks=[early_stop_callback,ck_callback], limit_train_batches=30, enable_checkpointing=True, )
这里我们需要注意的参数是“max_epochs”(最大训练时期数)、“gradient_clip_val”(用于防止梯度爆炸)和“回调”。这里“max_epochs”使用ep,这是我们稍后将定义的全局变量,而“callbacks”是我们的回调集合。
接下来,我们还需要定义NHiTS模型并实例化它:
net = NHiTS.from_dataset( training, learning_rate=lr, log_interval=10, log_val_interval=1, weight_decay=1e-2, backcast_loss_ratio=0.0, hidden_size=64, optimizer="AdamW", loss=MQF2DistributionLoss(prediction_length=max_prediction_length), )
这里,参数通常不需要修改,只需使用默认的参数即可。这里我们只将“loss”修改为MQF2DistributionLoss 损失函数。
5. 训练模块
我们使用Trainer对象的fit()函数来训练模型:
trainer.fit( net, train_dataloaders=train_dataloader, val_dataloaders=val_dataloader, )
类似地,我们将这部分代码封装到一个函数train()中:
def train(): early_stop_callback = EarlyStopping(monitor="val_loss", min_delta=1e-4, patience=10, # The number of times without improvement will stop verbose=True, mode="min") ck_callback=ModelCheckpoint(monitor='val_loss', mode="min", save_top_k=1, # Save the top few best ones filename='{epoch}-{val_loss:.2f}') trainer = pl.Trainer( max_epochs=ep, accelerator="cpu", enable_model_summary=True, gradient_clip_val=1.0, callbacks=[early_stop_callback,ck_callback], limit_train_batches=30, enable_checkpointing=True, ) net = NHiTS.from_dataset( training, learning_rate=lr, log_interval=10, log_val_interval=1, weight_decay=1e-2, backcast_loss_ratio=0.0, hidden_size=64, optimizer="AdamW", loss=MQF2DistributionLoss(prediction_length=max_prediction_length), ) trainer.fit( net, train_dataloaders=t_loader, val_dataloaders=v_loader, # ckpt_path='best' ) return trainer
此函数将返回一个经过训练的模型,可用于预测任务。