Advice on implementing input and output data scaling

I’ve searched for a while and I can’t find any examples or conclusive guidance on how to implement input or output scaling.

Situation:
I am training an RNN on sequence input data to predict outputs (many-to-many). Both the inputs and outputs are continuous-valued so I should scale them (to zero mean and unit variance).

Obviously there is no built-in function to do scaling in Pytorch. I thought transforms.Normalize might be suitable but every time I try to use it on my data it says TypeError: tensor is not a torch image. Is it only designed for images?

I can easily implement scaling by hand or as a custom transformer as others have so this is not the main issue. The bigger question is where to put the code.

  1. One way is to add this to my custom dataset. I could initialize the scaler mean and variance when the dataset is initialized and then add the transformation to the dataset’s __getitem__ method Since I’m also doing output scaling then I will have to ‘hang on’ to the transform method so I can do the inverse operation to the predictions before comparing them with the targets.

  2. Another option is to add it to the data loader.

  3. Some people think it should be added to the estimator model (RNN in this case).

  4. Keep it out of all objects and manually add it to the high-level code running the training and prediction tasks.

Please advise.

In the absence of any responses to my question I developed a custom transform (based on this example) and pass two instances of it (one as input transform, one as output_transform) to the custom dataset at intialisation (option 1). Then I will use the output_transform.inverse_transform() method to “decode” the predictions later when using the estimator.

Here is the code if anyone is interested:

class StandardScaler():
    """Standardize data by removing the mean and scaling to
    unit variance.  This object can be used as a transform
    in PyTorch data loaders.

    Args:
        mean (FloatTensor): The mean value for each feature in the data.
        scale (FloatTensor): Per-feature relative scaling.
    """

    def __init__(self, mean=None, scale=None):
        if mean is not None:
            mean = torch.FloatTensor(mean)
        if scale is not None:
            scale = torch.FloatTensor(scale)
        self.mean_ = mean
        self.scale_ = scale

    def fit(self, sample):
        """Set the mean and scale values based on the sample data.
        """
        self.mean_ = sample.mean(0, keepdim=True)
        self.scale_ = sample.std(0, unbiased=False, keepdim=True)
        return self

    def __call__(self, sample):
        return (sample - self.mean_)/self.scale_

    def inverse_transform(self, sample):
        """Scale the data back to the original representation
        """
        return sample * self.scale_ + self.mean_
1 Like