| 128 | |
| 129 | |
| 130 | class TSTiEncoder(nn.Module): #i means channel-independent |
| 131 | def __init__(self, c_in, patch_num, patch_len, max_seq_len=1024, |
| 132 | n_layers=3, d_model=128, n_heads=16, d_k=None, d_v=None, |
| 133 | d_ff=256, norm='BatchNorm', attn_dropout=0., dropout=0., act="gelu", store_attn=False, |
| 134 | key_padding_mask='auto', padding_var=None, attn_mask=None, res_attention=True, pre_norm=False, |
| 135 | pe='zeros', learn_pe=True, verbose=False, **kwargs): |
| 136 | |
| 137 | |
| 138 | super().__init__() |
| 139 | |
| 140 | self.patch_num = patch_num |
| 141 | self.patch_len = patch_len |
| 142 | |
| 143 | # Input encoding |
| 144 | q_len = patch_num |
| 145 | self.W_P = nn.Linear(patch_len, d_model) # Eq 1: projection of feature vectors onto a d-dim vector space |
| 146 | self.seq_len = q_len |
| 147 | |
| 148 | # Positional encoding |
| 149 | self.W_pos = positional_encoding(pe, learn_pe, q_len, d_model) |
| 150 | |
| 151 | # Residual dropout |
| 152 | self.dropout = nn.Dropout(dropout) |
| 153 | |
| 154 | # Encoder |
| 155 | self.encoder = TSTEncoder(q_len, d_model, n_heads, d_k=d_k, d_v=d_v, d_ff=d_ff, norm=norm, attn_dropout=attn_dropout, dropout=dropout, |
| 156 | pre_norm=pre_norm, activation=act, res_attention=res_attention, n_layers=n_layers, store_attn=store_attn) |
| 157 | |
| 158 | |
| 159 | def forward(self, x, |
| 160 | edge_index: torch.LongTensor, |
| 161 | edge_weight: torch.FloatTensor) -> Tensor: # x: [bs x nvars x patch_len x patch_num] |
| 162 | |
| 163 | n_vars = x.shape[1] |
| 164 | # Input encoding |
| 165 | x = x.permute(0,1,3,2) # x: [bs x nvars x patch_num x patch_len] |
| 166 | x = self.W_P(x) # x: [bs x nvars x patch_num x d_model] |
| 167 | |
| 168 | u = torch.reshape(x, (x.shape[0]*x.shape[1],x.shape[2],x.shape[3])) # u: [bs * nvars x patch_num x d_model] |
| 169 | u = self.dropout(u + self.W_pos) # u: [bs * nvars x patch_num x d_model] |
| 170 | |
| 171 | # Encoder |
| 172 | z = self.encoder(u, edge_index, edge_weight) # z: [bs * nvars x patch_num x d_model] |
| 173 | z = torch.reshape(z, (-1,n_vars,z.shape[-2],z.shape[-1])) # z: [bs x nvars x patch_num x d_model] |
| 174 | z = z.permute(0,1,3,2) # z: [bs x nvars x d_model x patch_num] |
| 175 | |
| 176 | return z |
| 177 | |
| 178 | |
| 179 | |