PVNet 3.0.23__tar.gz → 3.0.25__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {PVNet-3.0.23 → pvnet-3.0.25}/PKG-INFO +1 -1
- {PVNet-3.0.23 → pvnet-3.0.25}/PVNet.egg-info/PKG-INFO +1 -1
- pvnet-3.0.25/pvnet/__init__.py +2 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/models/base_model.py +71 -61
- PVNet-3.0.23/pvnet/__init__.py +0 -2
- {PVNet-3.0.23 → pvnet-3.0.25}/LICENSE +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/MANIFEST.in +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/PVNet.egg-info/SOURCES.txt +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/PVNet.egg-info/dependency_links.txt +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/PVNet.egg-info/requires.txt +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/PVNet.egg-info/top_level.txt +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/README.md +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/callbacks.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/data/__init__.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/data/base.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/data/datamodule.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/data/pv_site_datamodule.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/data/utils.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/data/wind_datamodule.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/models/__init__.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/models/baseline/__init__.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/models/baseline/last_value.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/models/baseline/single_value.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/models/ensemble.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/models/multimodal/__init__.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/models/multimodal/basic_blocks.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/models/multimodal/encoders/__init__.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/models/multimodal/encoders/basic_blocks.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/models/multimodal/encoders/encoders2d.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/models/multimodal/encoders/encoders3d.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/models/multimodal/encoders/encodersRNN.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/models/multimodal/linear_networks/__init__.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/models/multimodal/linear_networks/basic_blocks.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/models/multimodal/linear_networks/networks.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/models/multimodal/multimodal.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/models/multimodal/multimodal_base.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/models/multimodal/site_encoders/__init__.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/models/multimodal/site_encoders/basic_blocks.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/models/multimodal/site_encoders/encoders.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/models/multimodal/unimodal_teacher.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/models/utils.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/optimizers.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/training.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pvnet/utils.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/pyproject.toml +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/requirements-dev.txt +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/requirements.txt +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/setup.cfg +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/setup.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/tests/__init__.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/tests/conftest.py +0 -0
- {PVNet-3.0.23 → pvnet-3.0.25}/tests/test_end2end.py +0 -0
|
@@ -302,6 +302,7 @@ class BaseModel(pl.LightningModule, PVNetModelHubMixin):
|
|
|
302
302
|
self._accumulated_metrics = MetricAccumulator()
|
|
303
303
|
self._accumulated_batches = BatchAccumulator(key_to_keep=self._target_key_name)
|
|
304
304
|
self._accumulated_y_hat = PredAccumulator()
|
|
305
|
+
self._horizon_maes = MetricAccumulator()
|
|
305
306
|
|
|
306
307
|
# Store whether the model should use quantile regression or simply predict the mean
|
|
307
308
|
self.use_quantile_regression = self.output_quantiles is not None
|
|
@@ -390,6 +391,18 @@ class BaseModel(pl.LightningModule, PVNetModelHubMixin):
|
|
|
390
391
|
|
|
391
392
|
return losses
|
|
392
393
|
|
|
394
|
+
def _step_mae_and_mse(self, y, y_hat, dict_key_root):
|
|
395
|
+
"""Calculate the MSE and MAE at each forecast step"""
|
|
396
|
+
losses = {}
|
|
397
|
+
|
|
398
|
+
mse_each_step = torch.mean((y_hat - y) ** 2, dim=0)
|
|
399
|
+
mae_each_step = torch.mean(torch.abs(y_hat - y), dim=0)
|
|
400
|
+
|
|
401
|
+
losses.update({f"MSE_{dict_key_root}/step_{i:03}": m for i, m in enumerate(mse_each_step)})
|
|
402
|
+
losses.update({f"MAE_{dict_key_root}/step_{i:03}": m for i, m in enumerate(mae_each_step)})
|
|
403
|
+
|
|
404
|
+
return losses
|
|
405
|
+
|
|
393
406
|
def _calculate_val_losses(self, y, y_hat):
|
|
394
407
|
"""Calculate additional validation losses"""
|
|
395
408
|
|
|
@@ -405,12 +418,17 @@ class BaseModel(pl.LightningModule, PVNetModelHubMixin):
|
|
|
405
418
|
|
|
406
419
|
# Take median value for remaining metric calculations
|
|
407
420
|
y_hat = self._quantiles_to_prediction(y_hat)
|
|
408
|
-
mse_each_step = torch.mean((y_hat - y) ** 2, dim=0)
|
|
409
|
-
mae_each_step = torch.mean(torch.abs(y_hat - y), dim=0)
|
|
410
421
|
|
|
411
|
-
|
|
412
|
-
losses.update(
|
|
422
|
+
# Log the loss at each time horizon
|
|
423
|
+
losses.update(self._step_mae_and_mse(y, y_hat, dict_key_root="horizon"))
|
|
424
|
+
|
|
425
|
+
# Log the persistance losses
|
|
426
|
+
y_persist = y[:, -1].unsqueeze(1).expand(-1, self.forecast_len)
|
|
427
|
+
losses["MAE_persistence/val"] = F.l1_loss(y_persist, y)
|
|
428
|
+
losses["MSE_persistence/val"] = F.mse_loss(y_persist, y)
|
|
413
429
|
|
|
430
|
+
# Log persistance loss at each time horizon
|
|
431
|
+
losses.update(self._step_mae_and_mse(y, y_persist, dict_key_root="persistence"))
|
|
414
432
|
return losses
|
|
415
433
|
|
|
416
434
|
def _calculate_test_losses(self, y, y_hat):
|
|
@@ -477,51 +495,36 @@ class BaseModel(pl.LightningModule, PVNetModelHubMixin):
|
|
|
477
495
|
opt_target = losses["MAE/train"]
|
|
478
496
|
return opt_target
|
|
479
497
|
|
|
498
|
+
def _log_forecast_plot(self, batch, y_hat, accum_batch_num, timesteps_to_plot, plot_suffix):
|
|
499
|
+
"""Log forecast plot to wandb"""
|
|
500
|
+
fig = plot_batch_forecasts(
|
|
501
|
+
batch,
|
|
502
|
+
y_hat,
|
|
503
|
+
quantiles=self.output_quantiles,
|
|
504
|
+
key_to_plot=self._target_key_name,
|
|
505
|
+
)
|
|
506
|
+
|
|
507
|
+
plot_name = f"val_forecast_samples/batch_idx_{accum_batch_num}_{plot_suffix}"
|
|
508
|
+
|
|
509
|
+
self.logger.experiment.log({plot_name: wandb.Image(fig)})
|
|
510
|
+
plt.close(fig)
|
|
511
|
+
|
|
480
512
|
def validation_step(self, batch: dict, batch_idx):
|
|
481
513
|
"""Run validation step"""
|
|
482
514
|
y_hat = self(batch)
|
|
483
515
|
# Sensor seems to be in batch, station, time order
|
|
484
516
|
y = batch[self._target_key][:, -self.forecast_len :, 0]
|
|
485
|
-
|
|
517
|
+
|
|
486
518
|
# Expand persistence to be the same shape as y
|
|
487
|
-
persistence = persistence.unsqueeze(1).expand(-1, self.forecast_len)
|
|
488
519
|
losses = self._calculate_common_losses(y, y_hat)
|
|
489
520
|
losses.update(self._calculate_val_losses(y, y_hat))
|
|
490
521
|
|
|
522
|
+
# Store these to make horizon accuracy plot
|
|
523
|
+
self._horizon_maes.append(
|
|
524
|
+
{i: losses[f"MAE_horizon/step_{i:03}"].cpu().numpy() for i in range(self.forecast_len)}
|
|
525
|
+
)
|
|
526
|
+
|
|
491
527
|
logged_losses = {f"{k}/val": v for k, v in losses.items()}
|
|
492
|
-
logged_losses["MAE_persistence/val"] = F.l1_loss(persistence, y)
|
|
493
|
-
logged_losses["MSE_persistence/val"] = F.mse_loss(persistence, y)
|
|
494
|
-
# Log for each timestep the persistence loss
|
|
495
|
-
for i in range(self.forecast_len):
|
|
496
|
-
logged_losses[f"MAE_persistence/step_{i:03}/val"] = F.l1_loss(
|
|
497
|
-
persistence[:, i], y[:, i]
|
|
498
|
-
)
|
|
499
|
-
logged_losses[f"MSE_persistence/step_{i:03}/val"] = F.mse_loss(
|
|
500
|
-
persistence[:, i], y[:, i]
|
|
501
|
-
)
|
|
502
|
-
# Get the losses in the format of {VAL>_horizon/step_000: 0.1, VAL>_horizon/step_001: 0.2}
|
|
503
|
-
# for each step in the forecast horizon
|
|
504
|
-
# This is needed for the custom plot
|
|
505
|
-
# And needs to be in order of step
|
|
506
|
-
x_values = [
|
|
507
|
-
int(k.split("_")[-1].split("/")[0])
|
|
508
|
-
for k in logged_losses.keys()
|
|
509
|
-
if "MAE_horizon/step" in k
|
|
510
|
-
]
|
|
511
|
-
y_values = []
|
|
512
|
-
for x in x_values:
|
|
513
|
-
y_values.append(logged_losses[f"MAE_horizon/step_{x:03}/val"])
|
|
514
|
-
per_step_losses = [[x, y] for (x, y) in zip(x_values, y_values)]
|
|
515
|
-
# Check if WandBLogger is being used
|
|
516
|
-
if isinstance(self.logger, pl.loggers.WandbLogger):
|
|
517
|
-
table = wandb.Table(data=per_step_losses, columns=["timestep", "MAE"])
|
|
518
|
-
wandb.log(
|
|
519
|
-
{
|
|
520
|
-
"mae_vs_timestep": wandb.plot.line(
|
|
521
|
-
table, "timestep", "MAE", title="MAE vs Timestep"
|
|
522
|
-
)
|
|
523
|
-
}
|
|
524
|
-
)
|
|
525
528
|
|
|
526
529
|
self.log_dict(
|
|
527
530
|
logged_losses,
|
|
@@ -531,7 +534,8 @@ class BaseModel(pl.LightningModule, PVNetModelHubMixin):
|
|
|
531
534
|
|
|
532
535
|
accum_batch_num = batch_idx // self.trainer.accumulate_grad_batches
|
|
533
536
|
|
|
534
|
-
if
|
|
537
|
+
# Make plots only if using wandb logger
|
|
538
|
+
if isinstance(self.logger, pl.loggers.WandbLogger) and accum_batch_num in [0, 1]:
|
|
535
539
|
# Store these temporarily under self
|
|
536
540
|
if not hasattr(self, "_val_y_hats"):
|
|
537
541
|
self._val_y_hats = PredAccumulator()
|
|
@@ -539,47 +543,53 @@ class BaseModel(pl.LightningModule, PVNetModelHubMixin):
|
|
|
539
543
|
|
|
540
544
|
self._val_y_hats.append(y_hat)
|
|
541
545
|
self._val_batches.append(batch)
|
|
542
|
-
|
|
546
|
+
|
|
547
|
+
# if batch has accumulated
|
|
543
548
|
if (batch_idx + 1) % self.trainer.accumulate_grad_batches == 0:
|
|
544
549
|
y_hat = self._val_y_hats.flush()
|
|
545
550
|
batch = self._val_batches.flush()
|
|
546
551
|
|
|
547
|
-
|
|
552
|
+
self._log_forecast_plot(
|
|
548
553
|
batch,
|
|
549
554
|
y_hat,
|
|
550
|
-
|
|
551
|
-
|
|
555
|
+
accum_batch_num,
|
|
556
|
+
timesteps_to_plot=None,
|
|
557
|
+
plot_suffix="all",
|
|
552
558
|
)
|
|
553
559
|
|
|
554
|
-
self.logger.experiment.log(
|
|
555
|
-
{
|
|
556
|
-
f"val_forecast_samples/batch_idx_{accum_batch_num}_all": wandb.Image(fig),
|
|
557
|
-
}
|
|
558
|
-
)
|
|
559
|
-
plt.close(fig)
|
|
560
|
-
|
|
561
560
|
if self.time_step_intervals_to_plot is not None:
|
|
562
561
|
for interval in self.time_step_intervals_to_plot:
|
|
563
|
-
|
|
562
|
+
self._log_forecast_plot(
|
|
564
563
|
batch,
|
|
565
564
|
y_hat,
|
|
566
|
-
|
|
567
|
-
key_to_plot=self._target_key_name,
|
|
565
|
+
accum_batch_num,
|
|
568
566
|
timesteps_to_plot=interval,
|
|
567
|
+
plot_suffix=f"timestep_{interval}",
|
|
569
568
|
)
|
|
570
|
-
self.logger.experiment.log(
|
|
571
|
-
{
|
|
572
|
-
f"val_forecast_samples/batch_idx_{accum_batch_num}_"
|
|
573
|
-
f"timestep_{interval}": wandb.Image(fig),
|
|
574
|
-
}
|
|
575
|
-
)
|
|
576
|
-
plt.close(fig)
|
|
577
569
|
|
|
578
570
|
del self._val_y_hats
|
|
579
571
|
del self._val_batches
|
|
580
572
|
|
|
581
573
|
return logged_losses
|
|
582
574
|
|
|
575
|
+
def on_validation_epoch_end(self):
|
|
576
|
+
"""Run on epoch end"""
|
|
577
|
+
|
|
578
|
+
horizon_maes_dict = self._horizon_maes.flush()
|
|
579
|
+
|
|
580
|
+
# Create the horizon accuracy curve
|
|
581
|
+
if isinstance(self.logger, pl.loggers.WandbLogger):
|
|
582
|
+
per_step_losses = [[i, horizon_maes_dict[i]] for i in range(self.forecast_len)]
|
|
583
|
+
|
|
584
|
+
table = wandb.Table(data=per_step_losses, columns=["horizon_step", "MAE"])
|
|
585
|
+
wandb.log(
|
|
586
|
+
{
|
|
587
|
+
"horizon_loss_curve": wandb.plot.line(
|
|
588
|
+
table, "horizon_step", "MAE", title="Horizon loss curve"
|
|
589
|
+
)
|
|
590
|
+
},
|
|
591
|
+
)
|
|
592
|
+
|
|
583
593
|
def test_step(self, batch, batch_idx):
|
|
584
594
|
"""Run test step"""
|
|
585
595
|
y_hat = self(batch)
|
PVNet-3.0.23/pvnet/__init__.py
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|