import torch class Normalization(): """ This class is for normalizing the spectrograms batch by batch. The normalization used is min-max, two modes 'framewise' and 'imagewise' can be selected. In this paper, we found that 'imagewise' normalization works better than 'framewise' If framewise is used, then X must follow the shape of (B, F, T) """ def __init__(self, min, max, mode='imagewise'): if mode == 'framewise': def normalize(x): size = x.shape x_max = x.max(1, keepdim=True)[0] # Finding max values for each frame x_min = x.min(1, keepdim=True)[0] x_std = (x-x_min)/(x_max-x_min) # If there is a column with all zero, nan will occur x_std[torch.isnan(x_std)]=0 # Making nan to 0 x_scaled = x_std * (max - min) + min return x_scaled elif mode == 'imagewise': def normalize(x): # x_max = x.view(size[0], size[1]*size[2]).max(1, keepdim=True)[0] # x_min = x.view(size[0], size[1]*size[2]).min(1, keepdim=True)[0] x_max = x.flatten(1).max(1, keepdim=True)[0] x_min = x.flatten(1).min(1, keepdim=True)[0] x_max = x_max.unsqueeze(1) # Make it broadcastable x_min = x_min.unsqueeze(1) # Make it broadcastable x_std = (x-x_min)/(x_max-x_min) x_scaled = x_std * (max - min) + min x_scaled[torch.isnan(x_scaled)]=min # if piano roll is empty, turn them to min return x_scaled elif mode == 'rowwise': def normalize(x): x_max = x.max(2)[0].unsqueeze(2) x_min = x.min(2)[0].unsqueeze(2) x_std = (x-x_min)/(x_max-x_min) x_scaled = x_std * (max - min) + min x_scaled[torch.isnan(x_scaled)]=min return x_scaled else: print(f'please choose the correct mode') self.normalize = normalize def __call__(self, x): return self.normalize(x)