mirror of
https://github.com/KimMeen/Time-LLM.git
synced 2024-11-27 07:49:53 +08:00
90 lines
3.4 KiB
Python
90 lines
3.4 KiB
Python
# This source code is provided for the purposes of scientific reproducibility
|
|
# under the following limited license from Element AI Inc. The code is an
|
|
# implementation of the N-BEATS model (Oreshkin et al., N-BEATS: Neural basis
|
|
# expansion analysis for interpretable time series forecasting,
|
|
# https://arxiv.org/abs/1905.10437). The copyright to the source code is
|
|
# licensed under the Creative Commons - Attribution-NonCommercial 4.0
|
|
# International license (CC BY-NC 4.0):
|
|
# https://creativecommons.org/licenses/by-nc/4.0/. Any commercial use (whether
|
|
# for the benefit of third parties or internally in production) requires an
|
|
# explicit license. The subject-matter of the N-BEATS model and associated
|
|
# materials are the property of Element AI Inc. and may be subject to patent
|
|
# protection. No license to patents is granted hereunder (whether express or
|
|
# implied). Copyright © 2020 Element AI Inc. All rights reserved.
|
|
|
|
"""
|
|
Loss functions for PyTorch.
|
|
"""
|
|
|
|
import torch as t
|
|
import torch.nn as nn
|
|
import numpy as np
|
|
import pdb
|
|
|
|
|
|
def divide_no_nan(a, b):
|
|
"""
|
|
a/b where the resulted NaN or Inf are replaced by 0.
|
|
"""
|
|
result = a / b
|
|
result[result != result] = .0
|
|
result[result == np.inf] = .0
|
|
return result
|
|
|
|
|
|
class mape_loss(nn.Module):
|
|
def __init__(self):
|
|
super(mape_loss, self).__init__()
|
|
|
|
def forward(self, insample: t.Tensor, freq: int,
|
|
forecast: t.Tensor, target: t.Tensor, mask: t.Tensor) -> t.float:
|
|
"""
|
|
MAPE loss as defined in: https://en.wikipedia.org/wiki/Mean_absolute_percentage_error
|
|
|
|
:param forecast: Forecast values. Shape: batch, time
|
|
:param target: Target values. Shape: batch, time
|
|
:param mask: 0/1 mask. Shape: batch, time
|
|
:return: Loss value
|
|
"""
|
|
weights = divide_no_nan(mask, target)
|
|
return t.mean(t.abs((forecast - target) * weights))
|
|
|
|
|
|
class smape_loss(nn.Module):
|
|
def __init__(self):
|
|
super(smape_loss, self).__init__()
|
|
|
|
def forward(self, insample: t.Tensor, freq: int,
|
|
forecast: t.Tensor, target: t.Tensor, mask: t.Tensor) -> t.float:
|
|
"""
|
|
sMAPE loss as defined in https://robjhyndman.com/hyndsight/smape/ (Makridakis 1993)
|
|
|
|
:param forecast: Forecast values. Shape: batch, time
|
|
:param target: Target values. Shape: batch, time
|
|
:param mask: 0/1 mask. Shape: batch, time
|
|
:return: Loss value
|
|
"""
|
|
return 200 * t.mean(divide_no_nan(t.abs(forecast - target),
|
|
t.abs(forecast.data) + t.abs(target.data)) * mask)
|
|
|
|
|
|
class mase_loss(nn.Module):
|
|
def __init__(self):
|
|
super(mase_loss, self).__init__()
|
|
|
|
def forward(self, insample: t.Tensor, freq: int,
|
|
forecast: t.Tensor, target: t.Tensor, mask: t.Tensor) -> t.float:
|
|
"""
|
|
MASE loss as defined in "Scaled Errors" https://robjhyndman.com/papers/mase.pdf
|
|
|
|
:param insample: Insample values. Shape: batch, time_i
|
|
:param freq: Frequency value
|
|
:param forecast: Forecast values. Shape: batch, time_o
|
|
:param target: Target values. Shape: batch, time_o
|
|
:param mask: 0/1 mask. Shape: batch, time_o
|
|
:return: Loss value
|
|
"""
|
|
masep = t.mean(t.abs(insample[:, freq:] - insample[:, :-freq]), dim=1)
|
|
masked_masep_inv = divide_no_nan(mask, masep[:, None])
|
|
return t.mean(t.abs(target - forecast) * masked_masep_inv)
|