0

I am building a neural network for Bengali numerical digit classification using PyTorch. I am facing difficulties building the dataset class to load my dataset using a data loader. I have a folder with all the images (numerical digits from 0-9) and a CSV file with 2 columns, the first column contains the name of the image, and the second contains the label(0-9). This is my data loader class which probably isn't causing the error.

class BDRWDataset(Dataset):
"""BDRW dataset."""

def __init__(self, csv_file, imgs_dir, transform=None):
    """
    Args:
        csv_file (string): Path to the csv file with labels.
        imgs_dir (string): Directory with all the images.
        transform (callable, optional): Optional transform to be applied
            on a sample.
    """
    self.labels = pd.read_csv(csv_file).iloc[:, 1].to_numpy().reshape(-1,1)
    self.imgs_dir = imgs_dir
    self.transform = transform

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

def __getitem__(self, idx):
    if torch.is_tensor(idx):
        idx = idx.tolist()

    img_path = '/content/BDRW_train/digit_' + str(idx) + '.jpg'
    image = io.imread(img_name, plugin='matplotlib')
    image = Image.fromarray(np.uint8(image))
    label = self.labels[idx]
    label = float(label)

    if self.transform:
        image = self.transform(image)        

    return (image, label)

I create an instance of this class.

transformed_dataset = BDRWDataset(csv_file='/content/labels.csv',imgs_dir='/content/BDRW_train',
                              transform=transforms.Compose([
                                           Rescale((28, 28)),
                                           transforms.Normalize((0.5,), (0.5,)),
                                           ToTensor()
                                           ]))

I have defined rescale and to tensor as follows

class Rescale(object):
"""Rescale the image in a sample to a given size.

Args:
    output_size (tuple or int): Desired output size. If tuple, output is
        matched to output_size. If int, smaller of image edges is matched
        to output_size keeping aspect ratio the same.
"""

def __init__(self, output_size):
    assert isinstance(output_size, (int, tuple))
    self.output_size = output_size

def __call__(self, sample):
    image, label = sample

    h, w = image.shape[:2]
    if isinstance(self.output_size, int):
        if h > w:
            new_h, new_w = self.output_size * h / w, self.output_size
        else:
            new_h, new_w = self.output_size, self.output_size * w / h
    else:
        new_h, new_w = self.output_size

    new_h, new_w = int(new_h), int(new_w)

    img = transform.resize(image, (new_h, new_w))

    return img, label

class ToTensor(object):
"""Convert ndarrays in sample to Tensors."""

def __call__(self, sample):
    image, label = sample['image'], sample['label']

    # swap color axis because
    # numpy image: H x W x C
    # torch image: C X H X W
    image = image.transpose((2, 0, 1))
    return (torch.from_numpy(image), torch.from_numpy(label))

Splitting the dataset into test and train and created train loader and validation loader using torch.utils.data.DataLoader

The neural network is

class CNN(nn.Module):
def __init__(self):
    super(CNN, self).__init__()
    self.layer1 = nn.Sequential(
        nn.Conv2d(1, 16, kernel_size=5, padding=2),
        nn.BatchNorm2d(16),
        nn.ReLU(),
        nn.MaxPool2d(2))
    self.layer2 = nn.Sequential(
        nn.Conv2d(16, 32, kernel_size=5, padding=2),
        nn.BatchNorm2d(32),
        nn.ReLU(),
        nn.MaxPool2d(2))
    self.fc = nn.Linear(7*7*32, 10)

def forward(self, x):
    out = self.layer1(x)
    out = self.layer2(out)
    out = out.view(out.size(0), -1)
    out = self.fc(out)
    return out

I create an instance of this class and start training

cnn = CNN()
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(cnn.parameters(), lr=learning_rate)

losses = [];
for epoch in range(num_epochs):
    for i, (image, label) in enumerate(valloader):
        image = Variable(image.float())
        label = Variable(label)

        # Forward + Backward + Optimize
        optimizer.zero_grad()
        outputs = cnn(image)
        loss = criterion(output, label)
        loss.backward()
        optimizer.step()

        losses.append(loss.data[0]);

        if (i+1) % 100 == 0:
            print ('Epoch : %d/%d, Iter : %d/%d,  Loss: %.4f' 
                   %(epoch+1, num_epochs, i+1, len(train_dataset)//batch_size, loss.data[0]))

This is where I get the error

AttributeError                            Traceback (most recent call last)
/usr/local/lib/python3.6/dist-packages/PIL/Image.py in open(fp, mode)
   2812     try:
-> 2813         fp.seek(0)
   2814     except (AttributeError, io.UnsupportedOperation):

AttributeError: 'str' object has no attribute 'seek'

During handling of the above exception, another exception occurred:

AttributeError                            Traceback (most recent call last)
9 frames
/usr/local/lib/python3.6/dist-packages/PIL/Image.py in open(fp, mode)
   2813         fp.seek(0)
   2814     except (AttributeError, io.UnsupportedOperation):
-> 2815         fp = io.BytesIO(fp.read())
   2816         exclusive_fp = True
   2817 

AttributeError: 'str' object has no attribute 'read'

It refers to PIL Image which I have used in the dataloader. So it seems to me that's where I am doing something wrong.

https://colab.research.google.com/drive/17XdP7gUoMNLxPCJ6PHEi3B09UQItzKyf?usp=sharing

This is the notebook I am working on. Please help me debug the errors in the code.

https://drive.google.com/open?id=1DznuHV9Fi5jVEbGdP-tg3ckmp5CNDOj1

This is the dataset I am working on.

  • 1
    Can you put your error in a better format along with the code snippet where you are getting the error instead of the whole notebook? It becomes quite difficult to debug when you post the whole notebook. – nsidn98 May 15 '20 at 07:54
  • Thanks for the tip. I'll update the question. – aman.khashbar May 15 '20 at 10:40

0 Answers0