TransformerEn.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import math
  2. import torch
  3. import torch.nn as nn
  4. class PositionalEncoding(nn.Module):
  5. """
  6. 正弦位置编码
  7. 输入: [batch, seq_len, d_model]
  8. 输出: [batch, seq_len, d_model]
  9. """
  10. def __init__(self, d_model, max_len=5000, dropout=0.1):
  11. super().__init__()
  12. self.dropout = nn.Dropout(dropout)
  13. pe = torch.zeros(max_len, d_model)
  14. position = torch.arange(0, max_len, dtype=torch.float32).unsqueeze(1)
  15. div_term = torch.exp(
  16. torch.arange(0, d_model, 2, dtype=torch.float32)
  17. * (-math.log(10000.0) / d_model)
  18. )
  19. pe[:, 0::2] = torch.sin(position * div_term)
  20. # 如果 d_model 是奇数,这里要避免维度不匹配
  21. if d_model % 2 == 0:
  22. pe[:, 1::2] = torch.cos(position * div_term)
  23. else:
  24. pe[:, 1::2] = torch.cos(position * div_term[:-1])
  25. pe = pe.unsqueeze(0) # [1, max_len, d_model]
  26. self.register_buffer("pe", pe)
  27. def forward(self, x):
  28. seq_len = x.size(1)
  29. x = x + self.pe[:, :seq_len, :]
  30. return self.dropout(x)
  31. class TransformerEncoderForecaster(nn.Module):
  32. """
  33. Transformer Encoder 时间序列预测模型
  34. 输入:
  35. x: [batch, input_len, n_features]
  36. 输出:
  37. y_pred: [batch, pred_len]
  38. """
  39. def __init__(
  40. self,
  41. n_features,
  42. pred_len,
  43. d_model=128,
  44. n_heads=8,
  45. num_layers=3,
  46. dim_feedforward=256,
  47. dropout=0.1,
  48. pooling="last", # 可选: "last" 或 "mean"
  49. ):
  50. super().__init__()
  51. self.pred_len = pred_len
  52. self.pooling = pooling
  53. # 将原始多变量特征映射到 Transformer 的隐藏维度
  54. self.input_projection = nn.Linear(n_features, d_model)
  55. # 位置编码
  56. self.pos_encoder = PositionalEncoding(
  57. d_model=d_model,
  58. max_len=5000,
  59. dropout=dropout,
  60. )
  61. # Transformer Encoder 层
  62. encoder_layer = nn.TransformerEncoderLayer(
  63. d_model=d_model,
  64. nhead=n_heads,
  65. dim_feedforward=dim_feedforward,
  66. dropout=dropout,
  67. activation="gelu",
  68. batch_first=True,
  69. norm_first=True,
  70. )
  71. self.encoder = nn.TransformerEncoder(
  72. encoder_layer=encoder_layer,
  73. num_layers=num_layers,
  74. )
  75. # 输出层:将编码后的历史信息映射到未来 pred_len 个预测值
  76. self.head = nn.Sequential(
  77. nn.LayerNorm(d_model),
  78. nn.Linear(d_model, 128),
  79. nn.GELU(),
  80. nn.Dropout(dropout),
  81. nn.Linear(128, pred_len),
  82. )
  83. def forward(self, x):
  84. # x: [batch, input_len, n_features]
  85. x = self.input_projection(x) # [batch, input_len, d_model]
  86. x = self.pos_encoder(x) # [batch, input_len, d_model]
  87. x = self.encoder(x) # [batch, input_len, d_model]
  88. if self.pooling == "mean":
  89. x = x.mean(dim=1) # [batch, d_model]
  90. else:
  91. x = x[:, -1, :] # [batch, d_model]
  92. y_pred = self.head(x) # [batch, pred_len]
  93. return y_pred
  94. if __name__ == "__main__":
  95. model = TransformerEncoderForecaster(n_features=10, pred_len=288, d_model=128, n_heads=8, num_layers=3, dim_feedforward=256, dropout=0.1, pooling="last")
  96. print(model)
  97. # 构造随机输入数据: [batch, input_len, n_features]
  98. import torch
  99. batch_size = 4
  100. input_len = 288
  101. n_features = 10
  102. x = torch.randn(batch_size, input_len, n_features)
  103. # 前向传播
  104. y_pred = model(x)
  105. print("输出 shape:", y_pred.shape)