DataLoader shows array instead of matrix

I am new to pytorch and stuck with probably a basic problem. I have two images. One of them is my input which must to be trained wrt other one which is ground truth. I built 250x250 pixelwise data for these two images. I wrote a simple dataset class and dataloader for them . When I check the size of my image, it gives me 1x250 instead of 250x250. So it basically considers every array in my matrix as a separate data but the whole 250x250 matrix is my single data. What am doing wrong? or is it just right?

If i do this correctly, i will load about hundreds of input and target images (250x250 matrices) for my study. Now i just try to learn how to do it.

I am posting my code below. Thank you in advance.

FOLDER_DATASET = “./ames03/”

class CustomData(Dataset):

def __init__(self,mat_path):
    data_DF = scipy.io.loadmat(mat_path + "ames03.mat")
    self.images = torch.from_numpy(data_DF['MD'])
    data_targets = scipy.io.loadmat(mat_path + "ames03_AOA=0.mat")
    self.targets = torch.from_numpy(data_targets['z1'])


def __getitem__(self,index):
    x = self.images[index]
    y = self.targets[index]
    return x, y

def __len__(self):
    return len(self.images)

dataset = CustomData(FOLDER_DATASET)
loader = torch.utils.data.DataLoader(dataset=dataset, batch_size=1)

dataiter = iter(loader)
image, target = dataiter.next()

print(image.size())

It looks like you’ve just loaded a single image using ames03.mat or does this .mat file contain multiple images?
Usually you would pass a list of files to __init__ and load them lazily in __getitem__.
Would that be possible?

Thank you for your reply.
Yes I have loaded one image with “MD” variable in ames03.mat in the form of 250x250 matrix and convert it to tensor for my trainable image. Also, i’ve loaded another image with “z1” variable in ames03_AOA=0.mat for my ground truth image. So far , if I have a mistake, tell me please.

Since i loaded only one image data for “images” and “targets” respectively, I expect only 0 for the index of getitem. But when I call my dataset, there seems to be 250 data in the form of 1x250 not 1 data in the form of 250x250.

You asked that whether this .mat file contain multiple images? It contains only one image. This file is the output of my matlab script. It stores just a matrix in the form of 250x250. My code somehow thinks that this file has 250 data with 1x250( which are each row of this matrix).

If you only have a single image (and target), you don’t necessarily need to wrap it in a Dataset.
Usually you would like to load more than a single sample, so that the index in __getitem__ is used to select the current sample.

This is done via lazy loading:
You would pass e.g. a list of paths to __init__ and load each image/file in __getitem__ by selecting the path to the current image from the passed list. Here is a small dummy example (without loading a target)

class MyLazyDataset(Dataset):
    def __init__(self, image_paths, transform=None):
        self.image_paths = image_paths
        self.transform = transforms # e.g. transforms.ToTensor()
        
    def __getitem__(self, index):
        # Get current path
        current_image_path = self.image_paths[index]
        # Load sample
        x = Image.open(current_image_path)
        # Apply transformation, if defined
        if self.transform is not None:
            x = self.transform(x)
        return x

    def __len__(self):
        # return number of images
        return len(self.image_paths)

Alternatively, you could also preload the data, if it’s small:

class MyDataset(Dataset):
    def __init__(self, data):
        self.data = data # data could have the shape [nb_samples, 3, 224, 224]
        
    def __getitem__(self, index):
        x = self.data[index]
        # x will have the shape [3, 224, 224]
        return x

    def __len__(self):
        # return number of images
        return len(self.data)

Since your loaded tensor has the shape [250, 250], indexing it in the first dimension will return a tensor with the shape [250].

Actually I don’t have single image. I have hundreds of images. I loaded just a single one because i am trying to learn how dataset class and dataloader works.

I thought loading my values in each pixel (let’s say pressure or velocity) instead of loading image would be more practical but as i understand correctly it can’t be done with the shape of [n, n]. In this matrix a nondimensional physical quantity over a domain is stored so maybe i wouldn’t deal with normalization later instead of working with pixel values between 0-255.

Can you give me an example of data format that i should pass dataset if it isn’t too much for you? As i said before i am new in pytorch. Thank you in advance.

I’m not sure I understand your use case completely.

Would you like to load each pixel value individually and pass it as a single value to your model?
That would be possible, so let me know, if that’s really your use case.

Sure! I would suggest to use my first example and pass a list of paths to your .mat files as the arguments to __init__:

class MyMatDataset(Dataset):
    def __init__(self, image_paths, target_paths):
        self.image_paths = image_paths
        self.target_paths = target_paths
        
    def __getitem__(self, index):
        x = scipy.io.loadmat(self.image_paths[index])
        x = torch.from_numpy(x['MD'])
        y = scipy.io.loadmat(self.target_paths[index])
        y = torch.from_numpy(y['z1'])

        return x, y

    def __len__(self):
        return len(self.image_paths)

# Create your data and target paths and make sure the order is right
image_paths = ['./ames01.mat', './ames02.mat', ...]
target_paths = ['./ames01_target.mat', './ames02_target.mat', ...]
dataset = MyMatDataset(image_paths, target_paths)
loader = DataLoader(dataset)

Consider I have a geometry and some pressure distribution around it. For each case geometry is changing so does pressure distribution. I have solutions of pressure distribution for each geometry. What i want to do is to build an encoder decoder model which predicts pressure distribution for a new geometry when i want to. To do that i need two images in my dataset. One is showing geometry and the other one is showing pressure distribution around it which behaves ground truth.

As i said i have solutions of pressure for each geometry. I can plot them and generate images of them but i already have raw data for pressures which is in the shape of [n, n]. I can also have geometry data [n, n]. So i thought that i do not need to generate images if i have this raw data.

I am saying again i am new in pytorch:) If you have any suggestion about my study or tutorial or any other document, please share with me.

In that case my example code should work.
Have a look at the Training a Classifier tutorial as it might give you a good starting point.

PS: Also, these tutorials are useful to get started with PyTorch :wink:

Yes, i am about to reply. It works fine. Thank you:)
I tried it with giving paths for two data. It doesn’t print second one. It says index 1 is out of bounds but i will deal with it:) Thanks again.

Sure! Let us know, if you get stuck. :slight_smile: