In this experiment, all files located in the /home/ directory of the NCHC High-speed File System (HFS) were reset. All files were re-uploaded, and the experiment was conducted again. The training dataset used in this experiment is the same as last week’s. However, the configuration files were modified as follows:
Configuration Files
training.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Training configurationbatch_size:1# Batch sizeoutput_directory:"./results/real_time"# Output directory for checkpoints and logsckpt_iter:"max"# Checkpoint mode (max or min)iters_per_ckpt:1000# Checkpoint frequency (number of epochs)iters_per_logging:100# Log frequency (number of iterations)n_iters:20000# Maximum number of iterationslearning_rate:0.001# Learning rate# Additional training settingsonly_generate_missing:true# Generate missing values onlyuse_model:2# Model to use for trainingmasking:"rm"# Masking strategy for missing valuesmissing_k:200# Number of missing values# Data pathsdata:train_path:"./datasets/real_time/pollutants_train.npy"# Path to training data
wavenet:# WaveNet model parametersinput_channels:26# Number of input channelsoutput_channels:26# Number of output channelsresidual_layers:36# Number of residual layersresidual_channels:256# Number of channels in residual blocksskip_channels:256# Number of channels in skip connections# Diffusion step embedding dimensionsdiffusion_step_embed_dim_input:128# Input dimensiondiffusion_step_embed_dim_hidden:512# Middle dimensiondiffusion_step_embed_dim_output:512# Output dimension# Structured State Spaces sequence model (S4) configurationss4_max_sequence_length:2000# Maximum sequence lengths4_state_dim:64# State dimensions4_dropout:0.0# Dropout rates4_bidirectional:true# Whether to use bidirectional layerss4_use_layer_norm:true# Whether to use layer normalizationdiffusion:# Diffusion model parametersT:200# Number of diffusion stepsbeta_0:0.0001# Initial beta valuebeta_T:0.02# Final beta value
inference.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Inference configurationbatch_size:1# Batch size for inferenceoutput_directory:"./results/real_time/12/inference/mnr"# Output directory for inference resultsckpt_path:"./results/real_time"# Path to checkpoint for inferencetrials:1# Replications# Additional training settingsonly_generate_missing:true# Generate missing values onlyuse_model:2# Model to use for trainingmasking:"mnr"# Masking strategy for missing valuesmissing_k:12# Number of missing values# Data pathsdata:test_path:"./datasets/real_time/pollutants_test.npy"# Path to test data
Adjustment
After troubleshooting, the batch_size parameter was adjusted in this experiment in hopes of achieving better results. The affected code is as follows:
As seen in the run_job() function from /scripts/diffusion/infer.py
defget_dataloader(path:str,batch_size:int,is_shuffle:bool=True,device:Union[str,torch.device]="cpu",num_workers:int=0,)->DataLoader:"""
Get a PyTorch DataLoader for the dataset stored at the given path.
Args:
path (str): Path to the dataset file.
batch_size (int): Size of each batch.
is_shuffle (bool, optional): Whether to shuffle the dataset. Defaults to True.
device (Union[str, torch.device], optional): Device to move the data to. Defaults to "cpu".
num_workers (int, optional): Number of subprocesses to use for data loading. Defaults to 8.
Returns:
DataLoader: PyTorch DataLoader for the dataset.
"""dataset=TensorDataset(torch.from_numpy(np.load(path)).to(dtype=torch.float32))pin_memory=device=="cuda"ordevice==torch.device("cuda")returnDataLoader(dataset,batch_size=batch_size,shuffle=is_shuffle,pin_memory=pin_memory,num_workers=num_workers,)
Therefore, we can deduce that the value returned by the dataloader consists of all data along the first dimension of the input, with the size determined by batch_size. For example, if the current data shape is (5, 2000, 26) and batch_size is set to 1, then each epoch will have a size of (1, 2000, 26), and a single iteration will contain $5 \div 1 = 5$ epochs. This also allows us to understand the purpose of the loop within the DiffusionGenerator class in /sssd/inference/generator.py.
Therefore, the batch_size should be set to a value smaller than the size of the first dimension in the dataset and preferably be a divisor of it.
The results based on the above configuration are as follows:
Imputation Results
All the following methods were tested under missing value conditions of 200, 24, and 12. The test code is as follows, only missing_k needs to be adjusted.
# test imputationimportosimportnumpyasnpimportmatplotlib.pyplotaspltfromtqdmimporttqdmtest_data=np.load(r'real_time\pollutants_test.npy').transpose(0,2,1)## functionsdefimputation_plot(full_data,missing_data,imputation_data,title,save_path):"""
Plot the first 3 dimensions of the first sample, comparing full data and missing data.
"""os.makedirs(save_path,exist_ok=True)show_dims=2fig,axes=plt.subplots(show_dims,1,figsize=(12,8),sharex=True)#imputation_data = np.where(np.isnan(missing_data), imputation_data, np.nan)forjinrange(show_dims):axes[j].plot(full_data[0,j],color='gray',label='full data',alpha=0.6)axes[j].plot(imputation_data[0,j],color='orange',label='imputation data',alpha=0.6)axes[j].plot(missing_data[0,j],color='red',label=title)axes[j].set_ylabel(f'Dim {j}')axes[j].legend()plt.suptitle(title)plt.xlabel('Time')plt.tight_layout()plt.savefig(f"{save_path}.png",dpi=300)#plt.show()defimputation_plot_each_dim(full_data,missing_data,imputation_data,title,save_dir):"""
Plot each dimension of the first sample separately, comparing full data, missing data, and imputation data.
Save each plot as a separate file.
"""num_dims=full_data.shape[1]os.makedirs(save_dir,exist_ok=True)forjintqdm(range(num_dims)):fig,ax=plt.subplots(figsize=(12,4))ax.plot(full_data[0,j],color='gray',label='full data',alpha=0.6)ax.plot(imputation_data[0,j],color='orange',label='imputation data',alpha=0.6)ax.plot(missing_data[0,j],color='red',label=title)ax.set_ylabel(f'Dim {j}')ax.set_xlabel('Time')ax.set_title(f'{title} - Dimension {j}')ax.legend(loc='center left',bbox_to_anchor=(1,0.5))fig.tight_layout(rect=[0,0,0.85,1])save_path=os.path.join(save_dir,f"{title}_dim{j}.png")plt.savefig(save_path,dpi=300)plt.close(fig)defanalysis_predict_data(missing_k,path):folder_path=f'.\\real_time\\imputation\\{missing_k}\\predict\\{path}\\T200_beta00.0001_betaT0.02\\max'os.makedirs(folder_path,exist_ok=True)length=len(os.listdir(folder_path))imputation=[]foriinrange(length):file_path=os.path.join(folder_path,f'imputation{i}.npy')arr=np.load(file_path)imputation.append(arr)predict_data=np.concatenate(imputation,axis=0)print(f'Shape: {predict_data.shape}')print(f'NAs: {np.isnan(predict_data).sum()}')# print(predict_data[0, 0])print(f'MSPE for all: {((test_data-predict_data)**2).mean()}')test_data_predict=np.load(f'real_time\\{missing_k}\\pollutants_test_{path}.npy').transpose(0,2,1)print(f'MSPE only for missing: {((test_data[np.isnan(test_data_predict)]-predict_data[np.isnan(test_data_predict)])**2).mean()}')imputation_plot(test_data,test_data_predict,predict_data,f'imputation {path} test data',f'real_time\\imputation\\{missing_k}\\result\\predict\\imputation0_{path}')imputation_plot_each_dim(test_data,test_data_predict,predict_data,f'imputation {path} test data',f'real_time\\imputation\\{missing_k}\\result\\predict\\imputation0_{path}')# test_data[0, 0][1:10]# test_data_predict[0, 0][1:10]# predict_data[0, 0][1:10]missing_k=200## rmanalysis_predict_data(missing_k,'rm')## rbmanalysis_predict_data(missing_k,'rbm')## bmanalysis_predict_data(missing_k,'bm')## tfanalysis_predict_data(missing_k,'tf')# originaldefanalysis_imputation_data(missing_k,path):folder_path=f'.\\real_time\\imputation\\{missing_k}\\inference\\{path}\\T200_beta00.0001_betaT0.02\\max'os.makedirs(folder_path,exist_ok=True)length=len(os.listdir(folder_path))imputation=[]foriinrange(length):file_path=os.path.join(folder_path,f'imputation{i}.npy')arr=np.load(file_path)imputation.append(arr)imputation_data=np.concatenate(imputation,axis=0)print(f'Shape: {imputation_data.shape}')print(f'NAs: {np.isnan(imputation_data).sum()}')# print(imputation_data[0, 0])print(f'MSPE: {((test_data-imputation_data)**2).mean()}')imputation_plot(test_data,test_data,imputation_data,f'imputation {path} test data',f'real_time\\imputation\\{missing_k}\\result\\original\\imputation0_{path}')imputation_plot_each_dim(test_data,test_data,imputation_data,f'imputation {path} test data',f'real_time\\imputation\\{missing_k}\\result\\original\\imputation0_{path}')# test_data[0, 0][1:10]# test_data_imputation[0, 0][1:10]# imputation_data[0, 0][1:10]## rmanalysis_imputation_data(missing_k,'rm')## bmanalysis_imputation_data(missing_k,'bm')## mnranalysis_imputation_data(missing_k,'mnr')## tfanalysis_imputation_data(missing_k,'tf')
Original Program (test without missing values)
200
rm
MSPE for the entire test set: 0.0007726947053672325
gallery_made_with_nanogallery2-original-200-rm
bm
MSPE for the entire test set: 0.24869654130201302
gallery_made_with_nanogallery2-original-200-bm
mnr
MSPE for the entire test set: 0.2518200360151487
gallery_made_with_nanogallery2-original-200-mnr
forecast
MSPE for the entire test set: 0.2584019887489863
gallery_made_with_nanogallery2-original-200-tf
24
rm
MSPE for the entire test set: 0.0007776705576000954
gallery_made_with_nanogallery2-original-24-rm
bm
MSPE for the entire test set: 0.24558736147078322
gallery_made_with_nanogallery2-original-24-bm
mnr
MSPE for the entire test set: 0.2779062416883658
gallery_made_with_nanogallery2-original-24-mnr
forecast
MSPE for the entire test set: 0.2426996368188828
gallery_made_with_nanogallery2-original-24-tf
12
rm
MSPE for the entire test set: 0.000343678513735235
gallery_made_with_nanogallery2-original-12-rm
bm
MSPE for the entire test set: 0.12490228987565512
gallery_made_with_nanogallery2-original-12-bm
mnr
MSPE for the entire test set: 0.12561325934437964
gallery_made_with_nanogallery2-original-12-mnr
forecast
MSPE for the entire test set: 0.1331316997123435
gallery_made_with_nanogallery2-original-12-tf
Prediction (test contain missing values)
200
rm
MSPE for the entire test set: 0.4033083841718653
MSPE only for the missing values in the test set: 0.5150290538329023
gallery_made_with_nanogallery2-predict-200-rm
bm
MSPE for the entire test set: 1.9847157860554776
MSPE only for the missing values in the test set: 4.961677683754047
gallery_made_with_nanogallery2-predict-200-bm
rbm
MSPE for the entire test set: 0.7959954168054797
MSPE only for the missing values in the test set: 1.2573786423253352
gallery_made_with_nanogallery2-predict-200-rbm
forecast
MSPE for the entire test set: 2.0579853656490044
MSPE only for the missing values in the test set: 5.144843697957479
gallery_made_with_nanogallery2-predict-200-tf
24
rm
MSPE for the entire test set: 0.38739405016442136
MSPE only for the missing values in the test set: 0.37690720477779943
gallery_made_with_nanogallery2-predict-24-rm
bm
MSPE for the entire test set: 1.9683662364048184
MSPE only for the missing values in the test set: 4.113597133774161e-05
gallery_made_with_nanogallery2-predict-24-bm
rbm
MSPE for the entire test set: 0.8399087830021398
MSPE only for the missing values in the test set: 0.8648797892201264
gallery_made_with_nanogallery2-predict-24-rbm
forecast
MSPE for the entire test set: 2.014067660524411
MSPE only for the missing values in the test set: 4.566016572936741
gallery_made_with_nanogallery2-predict-24-tf
12
rm
MSPE for the entire test set: 0.00040013436784975165
MSPE only for the missing values in the test set: 0.0002673385994639709
gallery_made_with_nanogallery2-predict-12-rm
bm
MSPE for the entire test set: 0.1269181803083845
MSPE only for the missing values in the test set: 5.284446942912535
gallery_made_with_nanogallery2-predict-12-bm
rbm
MSPE for the entire test set: 0.00045168305235805304
MSPE only for the missing values in the test set: 0.0025162975939579785
gallery_made_with_nanogallery2-predict-12-rbm
forecast
MSPE for the entire test set: 0.12043755824949312
MSPE only for the missing values in the test set: 5.0144033937895385
gallery_made_with_nanogallery2-predict-12-tf
Findings
As a side note, this project does not support training with multiple GPUs. Modifications could be considered in the future to add such support.
Every 0.1s: nvidia-smi j5shm3test1140504-tv9mh: Sun May 4 14:26:39 2025Sun May 4 14:26:39 2025+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.161.08 Driver Version: 535.161.08 CUDA Version: 12.8 ||-----------------------------------------+----------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC || Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |||| MIG M. ||=========================================+======================+======================||0 Tesla V100-SXM2-32GB On | 00000000:3D:00.0 Off |0|| N/A 45C P0 190W / 300W | 18629MiB / 32768MiB | 100% Default |||| N/A |+-----------------------------------------+----------------------+----------------------+
|1 Tesla V100-SXM2-32GB On | 00000000:3E:00.0 Off |0|| N/A 33C P0 41W / 300W | 3MiB / 32768MiB | 0% Default |||| N/A |+-----------------------------------------+----------------------+----------------------+
+---------------------------------------------------------------------------------------+
| Processes: || GPU GI CI PID Type Process name GPU Memory || ID ID Usage ||=======================================================================================|+---------------------------------------------------------------------------------------+
Conclusion
Original Program (test without missing values)
NAs
Method
200
24
12
MSPE for entire test set
rm
0.00077
0.00078
0.00034
bm
0.24870
0.24559
0.12490
mnr
0.25182
0.27791
0.12561
forecast
0.25840
0.24270
0.13313
Prediction (test contain missing values)
NAs
Method
200
24
12
MSPE for entire test set
rm
0.40331
0.38739
0.00040
bm
1.98472
1.96837
0.12692
rbm
0.79600
0.83991
0.00045
forecast
2.05799
2.01407
0.12044
MSPE for missing values
rm
0.51503
0.37691
0.00027
bm
4.96168
0.00004
5.28445
rbm
1.25738
0.86488
0.00252
forecast
5.14484
4.56602
5.01440
It was observed that training with masking: "rm" resulted in better imputation performance for rm-type missing values, but poorer performance for other types of missing data. This may be due to the limited number of checkpoints (only 2,000) and the model being trained specifically with masking: "rm", which might not be sufficient for the model to learn features related to other missing data scenarios. Further testing will be conducted using the tf imputation method.
Environment
Local Operating System: Windows 11 24H2
Programming Language: Python 3.12.9
Computing Platform: National Center for High-Performance Computing (NCHC) – Taiwan AI Cloud
Juan Lopez Alcaraz, Nils Strodthoff. (2022). Diffusion-based time series imputation and forecasting with structured state space models. Transactions on Machine Learning Research. Retrieved from https://openreview.net/forum?id=hHiIbk7ApW