| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- import torch
- import torch.nn as nn
- import torch.nn.functional as F
- import numpy as np
- class moving_avg(nn.Module):
- """
- Moving average block to highlight the trend of time series
- """
- def __init__(self, kernel_size, stride):
- super(moving_avg, self).__init__()
- self.kernel_size = kernel_size
- self.avg = nn.AvgPool1d(kernel_size=kernel_size, stride=stride, padding=0)
- def forward(self, x):
- # padding on the both ends of time series
- front = x[:, 0:1, :].repeat(1, (self.kernel_size - 1) // 2, 1)
- end = x[:, -1:, :].repeat(1, (self.kernel_size - 1) // 2, 1)
- x = torch.cat([front, x, end], dim=1)
- x = self.avg(x.permute(0, 2, 1))
- x = x.permute(0, 2, 1)
- return x
- class series_decomp(nn.Module):
- """
- Series decomposition block
- """
- def __init__(self, kernel_size):
- super(series_decomp, self).__init__()
- self.moving_avg = moving_avg(kernel_size, stride=1)
- def forward(self, x):
- moving_mean = self.moving_avg(x)
- res = x - moving_mean
- return res, moving_mean
- class DLinearModel(nn.Module):
- """
- DLinear
- """
- def __init__(self, seq_len, pred_len, individual=True, channels=12,channels_outs=1,kernel_size=25):
- """
- seq_len: 历史输入长度
- pred_len: 预测长度
- individual: 是一个布尔值(True / False),控制 是否为每个通道单独建一个线性层。
- channels: 表示输入序列的 特征数(通道数)
- """
- super(DLinearModel, self).__init__()
- self.seq_len = seq_len
- self.pred_len = pred_len
- # Decompsition Kernel Size
- self.decompsition = series_decomp(kernel_size)
- self.individual = individual
- self.channels = channels
- if self.individual:
- self.Linear_Seasonal = nn.ModuleList()
- self.Linear_Trend = nn.ModuleList()
- self.Linear_Decoder = nn.ModuleList()
- for i in range(self.channels):
- self.Linear_Seasonal.append(nn.Linear(self.seq_len, self.pred_len))
- self.Linear_Seasonal[i].weight = nn.Parameter(
- (1 / self.seq_len) * torch.ones([self.pred_len, self.seq_len])
- )
- self.Linear_Trend.append(nn.Linear(self.seq_len, self.pred_len))
- self.Linear_Trend[i].weight = nn.Parameter(
- (1 / self.seq_len) * torch.ones([self.pred_len, self.seq_len])
- )
- self.Linear_Decoder.append(nn.Linear(self.seq_len, self.pred_len))
- else:
- self.Linear_Seasonal = nn.Linear(self.seq_len, self.pred_len)
- self.Linear_Trend = nn.Linear(self.seq_len, self.pred_len)
- self.Linear_Decoder = nn.Linear(self.seq_len, self.pred_len)
- self.Linear_Seasonal.weight = nn.Parameter(
- (1 / self.seq_len) * torch.ones([self.pred_len, self.seq_len])
- )
- self.Linear_Trend.weight = nn.Parameter(
- (1 / self.seq_len) * torch.ones([self.pred_len, self.seq_len])
- )
- self.line = nn.Linear(self.channels,channels_outs)
- def forward(self, x):
- # x: [Batch, Input length, Channel]
- seasonal_init, trend_init = self.decompsition(x)
- seasonal_init, trend_init = seasonal_init.permute(0, 2, 1), trend_init.permute(
- 0, 2, 1
- )
- if self.individual:
- seasonal_output = torch.zeros(
- [seasonal_init.size(0), seasonal_init.size(1), self.pred_len],
- dtype=seasonal_init.dtype,
- ).to(seasonal_init.device)
- trend_output = torch.zeros(
- [trend_init.size(0), trend_init.size(1), self.pred_len],
- dtype=trend_init.dtype,
- ).to(trend_init.device)
- for i in range(self.channels):
- seasonal_output[:, i, :] = self.Linear_Seasonal[i](
- seasonal_init[:, i, :]
- )
- trend_output[:, i, :] = self.Linear_Trend[i](trend_init[:, i, :])
- else:
- seasonal_output = self.Linear_Seasonal(seasonal_init)
- trend_output = self.Linear_Trend(trend_init)
- x = seasonal_output + trend_output
- x = x.permute(0, 2, 1)
- x = self.line(x) # to [Batch, Output length, Channel]
- B , L , C = x.shape
- x = x.reshape(B,-1)
- return x
- if __name__ == "__main__":
- B = 32
- ecmwf = torch.randn(B, 144, 1)
- model = DLinearModel(144, 1440)
- y_hat = model(ecmwf)
- print("Output shape:", y_hat.shape)
|