zezhishao / D2STGNN

Code for our VLDB'22 paper Decoupled Dynamic Spatial-Temporal Graph Neural Network for Traffic Forecasting.
143 stars 15 forks source link

How does "time_in_day_feat = self.T_i_D_emb[history_data[:, :, :, num_feat] * 288] " work? #2

Closed addicter2017 closed 1 year ago

addicter2017 commented 1 year ago

Dear Shao,

I tried to reproduce your result with my own dataset, one thing bothered me is that the dimension of _historydata of METR-LA is (batch_size,12,207,3),and the dimension of self.T_i_D_emb is (288,10). How does the code in my question work where the input data can be transferred to (batch_size,12,207,10)? I created random tensors in the console but failed to obtain the same result. Could you please give me some insight in it? Here is the reproduction code:

import torch
import torch.nn as nn

history = torch.randn((16,12,207,3))
T_i_D_emb = nn.Parameter(torch.empty(288,10))
nn.init.xavier_uniform_(T_i_D_emb)
T_i_D_emb[(history[:, :, :, 1] * 288).type(torch.LongTensor)]
time_in_day_feat = T_i_D_emb[(history[:, :, :, 1] * 288).type(torch.LongTensor)] 

error info: Traceback (most recent call last): File "/home/trp-mrta/anaconda3/envs/step_env/lib/python3.9/code.py", line 90, in runcode exec(code, self.locals) File "", line 1, in IndexError: index 368 is out of bounds for dimension 0 with size 288

The code wrote by you runs smoothly without any problem,but the version above failed.

zezhishao commented 1 year ago

Thanks for your attention. Here is a brief introduction to my data (METR-LA).

The 3 in (batch_size, 12, 207, 3) is the feature dimension.

The first dimension is the target feature (e.g., traffic speed in METR-LA). This feature is used in the input embedding layer. You can refer to here and here. You can use more target features in the input embedding process by modifying the in_feat here.

The second dimension is the time in day feature, which is normalized to 0~1 (0/288, 1/288, ..., 287/288). The 288 means there are 288 time steps per day (i.e., every 5 minutes). Therefore, the (history[:, :, :, 1] * 288).type(torch.LongTensor) in the code transforms the 0-1 normalized features back to integer numbers to serve as indexes.

The third dimension is the day in week feature, which is not normalized (0, 1, 2, ..., 6). Therefore, we can directly use it as the index.

I think you can generate the index and embeddings according to your data.

addicter2017 commented 1 year ago

Thanks for your quick response!

I understood the meaning of the input data, and that's not the thing bothered me. The key point of my problem is that why the (288,10)size tensor receives a (16,12,207) tensor and becomes (16,12,207,10)? The code is in model.py line 114. Thanks again!

time_in_day_feat = T_i_D_emb[(history[:, :, :, 1] * 288).type(torch.LongTensor)] 
zezhishao commented 1 year ago

In (history[:, :, :, 1] * 288).type(torch.LongTensor) (16, 12, 207), Each element (range from 0 to 287) serves as an index to get the corresponding positions in the embedding matrix (288, 10). Therefore, you will get (16, 12, 207, 10).

addicter2017 commented 1 year ago

Understood!That's pretty clear!