DLinear.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import torch
  2. import torch.nn as nn
  3. import torch.nn.functional as F
  4. import numpy as np
  5. class moving_avg(nn.Module):
  6. """
  7. Moving average block to highlight the trend of time series
  8. """
  9. def __init__(self, kernel_size, stride):
  10. super(moving_avg, self).__init__()
  11. self.kernel_size = kernel_size
  12. self.avg = nn.AvgPool1d(kernel_size=kernel_size, stride=stride, padding=0)
  13. def forward(self, x):
  14. # padding on the both ends of time series
  15. front = x[:, 0:1, :].repeat(1, (self.kernel_size - 1) // 2, 1)
  16. end = x[:, -1:, :].repeat(1, (self.kernel_size - 1) // 2, 1)
  17. x = torch.cat([front, x, end], dim=1)
  18. x = self.avg(x.permute(0, 2, 1))
  19. x = x.permute(0, 2, 1)
  20. return x
  21. class series_decomp(nn.Module):
  22. """
  23. Series decomposition block
  24. """
  25. def __init__(self, kernel_size):
  26. super(series_decomp, self).__init__()
  27. self.moving_avg = moving_avg(kernel_size, stride=1)
  28. def forward(self, x):
  29. moving_mean = self.moving_avg(x)
  30. res = x - moving_mean
  31. return res, moving_mean
  32. class DLinearModel(nn.Module):
  33. """
  34. DLinear
  35. """
  36. def __init__(self, seq_len, pred_len, individual=True, channels=12,channels_outs=1,kernel_size=25):
  37. """
  38. seq_len: 历史输入长度
  39. pred_len: 预测长度
  40. individual: 是一个布尔值(True / False),控制 是否为每个通道单独建一个线性层。
  41. channels: 表示输入序列的 特征数(通道数)
  42. """
  43. super(DLinearModel, self).__init__()
  44. self.seq_len = seq_len
  45. self.pred_len = pred_len
  46. # Decompsition Kernel Size
  47. self.decompsition = series_decomp(kernel_size)
  48. self.individual = individual
  49. self.channels = channels
  50. if self.individual:
  51. self.Linear_Seasonal = nn.ModuleList()
  52. self.Linear_Trend = nn.ModuleList()
  53. self.Linear_Decoder = nn.ModuleList()
  54. for i in range(self.channels):
  55. self.Linear_Seasonal.append(nn.Linear(self.seq_len, self.pred_len))
  56. self.Linear_Seasonal[i].weight = nn.Parameter(
  57. (1 / self.seq_len) * torch.ones([self.pred_len, self.seq_len])
  58. )
  59. self.Linear_Trend.append(nn.Linear(self.seq_len, self.pred_len))
  60. self.Linear_Trend[i].weight = nn.Parameter(
  61. (1 / self.seq_len) * torch.ones([self.pred_len, self.seq_len])
  62. )
  63. self.Linear_Decoder.append(nn.Linear(self.seq_len, self.pred_len))
  64. else:
  65. self.Linear_Seasonal = nn.Linear(self.seq_len, self.pred_len)
  66. self.Linear_Trend = nn.Linear(self.seq_len, self.pred_len)
  67. self.Linear_Decoder = nn.Linear(self.seq_len, self.pred_len)
  68. self.Linear_Seasonal.weight = nn.Parameter(
  69. (1 / self.seq_len) * torch.ones([self.pred_len, self.seq_len])
  70. )
  71. self.Linear_Trend.weight = nn.Parameter(
  72. (1 / self.seq_len) * torch.ones([self.pred_len, self.seq_len])
  73. )
  74. self.line = nn.Linear(self.channels,channels_outs)
  75. def forward(self, x):
  76. # x: [Batch, Input length, Channel]
  77. seasonal_init, trend_init = self.decompsition(x)
  78. seasonal_init, trend_init = seasonal_init.permute(0, 2, 1), trend_init.permute(
  79. 0, 2, 1
  80. )
  81. if self.individual:
  82. seasonal_output = torch.zeros(
  83. [seasonal_init.size(0), seasonal_init.size(1), self.pred_len],
  84. dtype=seasonal_init.dtype,
  85. ).to(seasonal_init.device)
  86. trend_output = torch.zeros(
  87. [trend_init.size(0), trend_init.size(1), self.pred_len],
  88. dtype=trend_init.dtype,
  89. ).to(trend_init.device)
  90. for i in range(self.channels):
  91. seasonal_output[:, i, :] = self.Linear_Seasonal[i](
  92. seasonal_init[:, i, :]
  93. )
  94. trend_output[:, i, :] = self.Linear_Trend[i](trend_init[:, i, :])
  95. else:
  96. seasonal_output = self.Linear_Seasonal(seasonal_init)
  97. trend_output = self.Linear_Trend(trend_init)
  98. x = seasonal_output + trend_output
  99. x = x.permute(0, 2, 1)
  100. x = self.line(x) # to [Batch, Output length, Channel]
  101. B , L , C = x.shape
  102. x = x.reshape(B,-1)
  103. return x
  104. if __name__ == "__main__":
  105. B = 32
  106. ecmwf = torch.randn(B, 144, 1)
  107. model = DLinearModel(144, 1440)
  108. y_hat = model(ecmwf)
  109. print("Output shape:", y_hat.shape)