同样,我们将获得最佳学习率的这部分代码封装到函数get_learning_rate()中,并将获得的最佳学习率作为其返回值:
" t; A; h0 v U3 j4 w3 tdef 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_
8 v( a/ {+ X$ S$ H; g如果您想可视化学习率,可以添加以下代码:
7 U5 r% n8 |& x; K' A1 ?! I2 Y
添加图片注释,不超过 140 字(可选)print(f"suggested learning rate: {res.suggestion()}")fig = res.plot(show=True, suggest=True)fig.show()
p* _6 r, `7 f此示例中的结果如下:/ y4 R+ S& K9 ?* K2 w+ C
$ f: ~( u, v6 A; T- P& {$ R
添加图片注释,不超过 140 字(可选)! r) W3 B* }+ b2 c$ {0 m+ t
建议学习率:0.003981071705534973。2. 定义EarlyStoping回调此回调主要用于监测验证损失,并在损失连续几个时期没有改善时停止训练。这样可以防止模型过拟合。# [/ i& Z( Z- C* i# Q/ t; U! E
early_stop_callback = EarlyStopping(monitor="val_loss", min_delta=1e-4, patience=10, verbose=True, mode="min"), |3 d, |- m0 u$ }$ ?
这里需要注意的参数是“patience”,它主要控制在训练过程中,如果损失连续几个时期没有改善,何时停止。我们把它设置为10。3. 定义ModelCheckpoint回调此回调主要用于控制模型归档和归档的名称。我们主要设置这两个变量。ck_callback=ModelCheckpoint(monitor='val_loss', mode="min", save_top_k=1, filename='{epoch}-{val_loss:.2f}')5 ^! z, C4 m& x" C( d
“save_top_k”用于控制保存前几个最好的模型。我们将其设置为1,只保存最好的模型。4. 定义训练模型我们首先需要在lightning.pytarch中实例化一个Trainer类,并添加我们之前定义的两个回调。
5 C# j- K) o' j* g2 btrainer = 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,)
& h6 T, m$ z' b: ~& n这里我们需要注意的参数是“max_epochs”(最大训练时期数)、“gradient_clip_val”(用于防止梯度爆炸)和“回调”。这里“max_epochs”使用ep,这是我们稍后将定义的全局变量,而“callbacks”是我们的回调集合。接下来,我们还需要定义NHiTS模型并实例化它:9 m" O0 \ r* g
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),)+ h9 O2 F* ~* L. ^; A( {
这里,参数通常不需要修改,只需使用默认的参数即可。这里我们只将“loss”修改为MQF2DistributionLoss 损失函数。5. 训练模块 我们使用Trainer对象的fit()函数来训练模型:
1 t4 ~9 @4 v2 k1 Q! `$ ctrainer.fit( net, train_dataloaders=train_dataloader, val_dataloaders=val_dataloader,)
9 N; v2 G2 L! A3 A# z4 q5 P类似地,我们将这部分代码封装到一个函数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
2 U* v \% T, ^7 e4 C) [此函数将返回一个经过训练的模型,可用于预测任务。& }0 R* r1 R2 E) @
定义执行逻辑1. 定义全局变量:0 J5 P; b* _- ^; }% \2 E1 }
ep=200__train=Falsemt_data_len=200000max_encoder_length = 2*96max_prediction_length = 30batch_size = 1280 D8 l% [/ Y( A% k) E) k' l3 i' C
__train用于控制我们当前是在训练还是测试模型。值得注意的是,ep用于控制最大训练时期。由于我们已经设置了EarlyStoping,因此可以将该值设置得更大一点,因为当模型不再收敛时,它将自动停止。mt_data_len是从客户端获得的最近时间序列数据的数量。max_encoder_length 和 max_prediction_length 分别是最大编码长度和最大预测长度。2.训练当训练完成时,我们还需要将当前的最佳训练结果保存到本地文件中,因此我们定义了一个json文件来保存这些信息:info_file='results.json'为了使我们的训练过程更加清晰,我们需要避免在训练过程中输出一些不必要的警告信息,因此我们将添加以下代码:1 X; {. f" J8 d& ], M8 q) W0 y
warnings.filterwarnings("ignore")7 T0 Y: B, A4 P; A" \
接下来是我们的训练逻辑:
5 g& H( F% z% ?0 J0 ?3 pdt=get_data(mt_data_len=mt_data_len)if __train: # print(dt) # dt=get_data(mt_data_len=mt_data_len) t_loader,v_loader,training=spilt_data(dt, t_shuffle=False,t_drop_last=True, v_shuffle=False,v_drop_last=True) lr=get_learning_rate() trainer__=train() m_c_back=trainer__.checkpoint_callback m_l_back=trainer__.early_stopping_callback best_m_p=m_c_back.best_model_path best_m_l=m_l_back.best_score.item() # print(best_m_p) if os.path.exists(info_file): with open(info_file,'r+') as f1: last=json.load(fp=f1) last_best_model=last['last_best_model'] last_best_score=last['last_best_score'] if last_best_score > best_m_l: last['last_best_model']=best_m_p last['last_best_score']=best_m_l json.dump(last,fp=f1) else: with open(info_file,'w') as f2: json.dump(dict(last_best_model=best_m_p,last_best_score=best_m_l),fp=f2)) q* d# X* }, I) |' H
训练完成后,您可以在根目录的results.json文件中找到我们最佳模型的存储位置和最佳分数。在训练过程中,您将看到一个进度条,显示每个 epoch 的进度。 |