0
$\begingroup$

Hi I am wondering when it comes to normalising images across each of the channels, do you use the same scaling factors that is used for training for testing set as well or separate ones. In traditional ML problems using scikit-learn, the usual procedure is normalise the training data and apply the same scaler for testing data

from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, shuffle = True)
scaler = MinMaxScaler()
X_train_norm = scaler.fit_transform(X_train)
X_test_norm = scaler.transform(X_test)

However when using deep learning I am wondering whether the same procedure is used for image data

For example

import torch 
from torchvision import transforms
from torchvision.datasets import ImageFolder
from torch.utils.data import DataLoader

# Resize Images to (3,150,150) and convert to torch tensors which gives values between 0 and 1 instead of 0 and 255. So need to divide by 255

train_transforms = transforms.Compose([
    transforms.Resize((150,150)),
    transforms.ToTensor(),
])

test_transforms = transforms.Compose([
    transforms.Resize((150,150)),
    transforms.ToTensor(),
])

train_datasets = ImageFolder(root = "data/dogs-vs-cats/concise_dataset/train", transform = train_transforms)
test_datasets = ImageFolder(root = "data/dogs-vs-cats/concise_dataset/test", transform = test_transforms)

# just a function to get mean of the mean and std for each channel across the entire train and test sets separately
def get_mean_and_std(dataset):
    mean_values = torch.zeros(len(dataset),3)
    std_values = torch.zeros(len(dataset),3)
    for idx, (img, lab) in enumerate(dataset):
        mean_values[idx, :] = img.mean(dim = [1,2])
        std_values[idx, :] = img.std(dim = [1,2])

    print(f"mean of entire dataset : {mean_values.mean(dim = 0)}")
    print(f"std of entire dataset : {std_values.mean(dim = 0)}")

get_mean_and_std(train_datasets)
# mean of entire dataset : tensor([0.4854, 0.4515, 0.4143])
# std of entire dataset : tensor([0.2233, 0.2178, 0.2185])

get_mean_and_std(test_datasets)
# mean of entire dataset : tensor([0.4902, 0.4571, 0.4188])
# std of entire dataset : tensor([0.2257, 0.2203, 0.2207])

Now apply these means and standard deviations separately for training and testing data.

train_transforms = transforms.Compose([
    transforms.Resize((150,150)),
    transforms.ToTensor(),
    transforms.Normalize(mean = [0.4854, 0.4515, 0.4143], std = [0.2233, 0.2178, 0.2185])
])

test_transforms = transforms.Compose([
    transforms.Resize((150,150)),
    transforms.ToTensor(),
    transforms.Normalize(mean = [0.4902, 0.4571, 0.4188], std = [0.2257, 0.2203, 0.2207])
])

or should I apply the same mean and std of train set to the test set?

test_transforms = transforms.Compose([
    transforms.Resize((150,150)),
    transforms.ToTensor(),
    transforms.Normalize(mean = [0.4854, 0.4515, 0.4143], std = [0.2233, 0.2178, 0.2185])
])
$\endgroup$

1 Answer 1

2
$\begingroup$

The method is the same as it is for traditional ML problems, i.e. you need to apply the same mean and standard deviation to the test data as you do for the training data. The mean and standard deviation used are derived from the training data, but depending on the type of problem and data used you can also use the values derived from the ImageNet dataset.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.